Add functions all about handling Message of the Day server info. Adds the `motd` console command, as well as `motdfile`.

This commit is contained in:
Marco Cawthorne 2023-03-25 16:28:06 -07:00
parent 6c0256782f
commit 338e89c06a
Signed by: eukara
GPG Key ID: CE2032F0A2882A22
12 changed files with 233 additions and 7 deletions

View File

@ -374,6 +374,9 @@ Cmd_Parse(string sCMD)
case "player_geomtest":
CMD_player_geomtest();
break;
case "motd":
print(MOTD_GetTextBody());
break;
/* XR binds, engine binds them currently */
case "+attack_left":
@ -455,6 +458,9 @@ Cmd_Init(void)
registercommand("vote");
registercommand("callvote");
/* motd */
registercommand("motd");
/* hud weapon selection system */
registercommand("slot1");
registercommand("slot2");

View File

@ -76,6 +76,7 @@ CSQC_Init(float apilevel, string enginename, float engineversion)
Decals_Init();
Way_Init();
Materials_Init();
MOTD_Init();
/* let the menu know we're a multi or a singleplayer game */
if (serverkeyfloat("sv_playerslots") == 1)

View File

@ -104,6 +104,16 @@ void Font_DrawRText_RGBA(vector vecOrigin, string strText, vector col, float a,
@param iAlignFlags sets how the text may be aligned. */
void Font_DrawField(vector vecOrigin, vector vecSize, string strText, font_s fnt, alignflags_t iAlignFlags);
/** Draws a textfield with line wrapping at a custom text height.
@param vecOrigin is the absolute starting position.
@param vecSize is the total area in pixels that the field takes up on the screen.
@param iTextHeight is the desired text height in pixels.
@param strText is the text to be drawn onto the screen.
@param fnt is the font to be used for rendering the text.
@param iAlignFlags sets how the text may be aligned. */
void Font_DrawFieldAtHeight(vector vecOrigin, vector vecSize, int iTextHeight, string strText, font_s fnt, alignflags_t iAlignFlags);
/** Converts a normalized RGB color vector to a hex color string.
@param vecColor is the normalized input color. E.g. [1.0f, 0.0f, 0.0f]

View File

@ -162,6 +162,17 @@ Font_DrawField(vector vecOrigin, vector vecSize, string strText, font_s fnt, ali
drawfontscale = [1,1,0];
}
void
Font_DrawFieldAtHeight(vector vecOrigin, vector vecSize, int iTextHeight, string strText, font_s fnt, alignflags_t iAlignFlags)
{
drawfont = (float)fnt.iID;
drawfontscale[0] = (float)iTextHeight / 8;
drawfontscale[1] = (float)iTextHeight / 8;
drawtextfield(vecOrigin, vecSize, (float)iAlignFlags, strText);
drawfont = 0;
drawfontscale = [1,1,0];
}
string
Font_RGBtoHex(vector vecColor)
{

View File

@ -374,6 +374,7 @@ initents(void)
{
/* sound shader init */
Materials_Init();
MOTD_Init();
PMove_Init();
/* TODO: turn these effects into sound shaders */

View File

@ -89,6 +89,7 @@ string __fullspawndata;
#include "decalgroups.h"
#include "colors.h"
#include "weapons.h"
#include "motd.h"
#define BSPVER_PREREL 28
#define BSPVER_Q1 29

View File

@ -33,6 +33,7 @@ sentences.qc
NSSpraylogo.qc
util.qc
weapons.qc
motd.qc
../xr/include.src
#endlist

40
src/shared/motd.h Normal file
View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2023 Vera Visions LLC.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef SERVER
var string autocvar_motdfile = "motd.txt";
#define MOTD_FILE autocvar_motdfile
/** Hard-limit to how many lines are allowed within a message of the day. */
#define MOTD_LINES 32
/** Called on the server to load the default 'message of the day' file. */
void MOTD_LoadDefault(void);
/** Called on the server to load a specific 'message of the day' file. */
void MOT_LoadFromFile(string);
#endif
/** Called by CSQC_Init() on the client game and by initents() on the server game to
set up a networked 'message of the day'. */
void MOTD_Init(void);
#ifdef CLIENT
/** Returns the full text body of the 'message of the day' that is on the server. Can be retrieved by clients via the `motd` console command. */
string MOTD_GetTextBody(void);
/** Returns how many individual lines are present in the message of the day. */
int MOTD_GetLineCount(void);
#endif

102
src/shared/motd.qc Normal file
View File

@ -0,0 +1,102 @@
/*
* Copyright (c) 2023 Vera Visions LLC.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef CLIENT
static string g_motd_body;
static int g_motd_lines;
#endif
void
MOTD_Init(void)
{
#ifdef SERVER
/* wipe the slate clean */
for (int i = 0; i < MOTD_LINES; i++) {
localcmd(sprintf("serverinfo motdline%i \"\"\n", i));
}
localcmd("serverinfo motdlines \"\"\n");
#endif
#ifdef CLIENT
int motdLines = stoi(serverkey("motdlines"));
g_motd_body = "";
for (int i = 0; i < motdLines; i++) {
string line = serverkey(sprintf("motdline%i", i));
if (line != "/") {
g_motd_body = strcat(g_motd_body, line, "\n");
} else {
g_motd_body = strcat(g_motd_body, "\n");
}
}
g_motd_lines = motdLines;
#endif
}
#ifdef SERVER
void
MOTD_LoadDefault(void)
{
MOT_LoadFromFile(MOTD_FILE);
}
void
MOT_LoadFromFile(string fileName)
{
/* init motd */
string tempString;
int motdLines = 0;
filestream fileMotd = fopen(fileName, FILE_READ);
/* now read in the new motd */
if (fileMotd != -1) {
for (int i = 0; i < MOTD_LINES; i++) {
tempString = fgets(fileMotd);
if not (tempString) {
break;
} else if (tempString == __NULL__) {
localcmd(sprintf("serverinfo motdline%i /\n", motdLines));
} else {
localcmd(sprintf("serverinfo motdline%i %S\n", motdLines, tempString));
}
motdLines++;
}
localcmd(sprintf("serverinfo motdlines \"%i\"\n", motdLines));
fclose(fileMotd);
} else {
NSLog("Failed to parse motd from %S", MOTD_FILE);
}
}
#endif
#ifdef CLIENT
string
MOTD_GetTextBody(void)
{
if (g_motd_lines > 0i)
return g_motd_body;
else
return "Server advertises no message of the day.";
}
int
MOTD_GetLineCount(void)
{
return g_motd_lines;
}
#endif

View File

@ -89,6 +89,7 @@ VGUIButton::SetTitle(string strName)
m_strTitle = strName;
m_strTitleActive = sprintf("^3%s", m_strTitle);
m_strTitle = sprintf("%s%s", Font_RGBtoHex(UI_MAINCOLOR), strName);
drawfont = g_fntDefault.iID;
newsize[0] = stringwidth(m_strTitle, TRUE, [g_fntDefault.iScaleX, g_fntDefault.iScaleY]) + 16;

View File

@ -14,6 +14,7 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/** A VGUI label/text field. */
class VGUILabel:VGUIWidget
{
public:
@ -24,15 +25,19 @@ public:
virtual void Draw(void);
virtual bool Input(float, float, float, float);
virtual void Spawned(void);
virtual void SetTextSize(int);
private:
string m_strTitle;
int m_labelFlags;
int m_textSize;
};
void
VGUILabel::VGUILabel(void)
{
m_strTitle = __NULL__;
m_labelFlags = AF_TOP | AF_LEFT;
}
void
@ -56,11 +61,29 @@ VGUILabel::SetTitle (string strName)
SetSize([2 + stringwidth(m_strTitle, TRUE, [g_fntDefault.iScaleX, g_fntDefault.iScaleY]), 16]);
}
void
VGUILabel::SetTextSize(int val)
{
m_textSize = val;
}
void
VGUILabel::Draw(void)
{
if (m_strTitle) {
Font_DrawField(m_parent.m_vecOrigin + m_vecOrigin, m_vecSize, m_strTitle, g_fntDefault, 0);
vector pos;
vector size;
pos = m_parent.m_vecOrigin + m_vecOrigin;
size = m_vecSize;
drawsetcliparea(pos[0], pos[1], size[0], size[1]);
if (!m_textSize)
Font_DrawField(pos, size, m_strTitle, g_fntDefault, m_labelFlags);
else
Font_DrawFieldAtHeight(pos, size, m_textSize, m_strTitle, g_fntDefault, m_labelFlags);
drawresetcliparea();
}
}

View File

@ -18,9 +18,18 @@ enumflags
{
WINDOW_DRAGGING,
WINDOW_RESIZING,
WINDOW_CANRESIZE
};
typedef enumflags
{
VGUIWindowBorderless,
VGUIWindowTitled,
VGUIWindowClosable,
VGUIWindowMiniaturizable,
VGUIWindowResizeable,
VGUIWindowMovable,
} vguiWindowStyle_t;
/** Top-most window class in VGUILib */
class VGUIWindow:VGUIWidget
{
@ -42,6 +51,9 @@ public:
/** Called when the window has been repositioned by the user. */
nonvirtual void CallOnMove(void(void) vFunc);
/** Sets the style mask of the specified window. */
nonvirtual void SetStyleMask(vguiWindowStyle_t);
/* overrides */
virtual void Draw(void);
virtual void SizeChanged(vector, vector);
@ -54,6 +66,7 @@ private:
vector m_vecDragOffset;
string m_strTitle;
string m_strIcon;
vguiWindowStyle_t m_styleMask;
VGUIButton m_btnClose;
@ -66,6 +79,21 @@ VGUIWindow::VGUIWindow(void)
{
m_vecColor = UI_MAINCOLOR;
m_flAlpha = 1.0f;
m_styleMask = VGUIWindowMovable |
VGUIWindowTitled |
VGUIWindowClosable |
VGUIWindowMiniaturizable |
VGUIWindowResizeable;
}
void
VGUIWindow::SetStyleMask(vguiWindowStyle_t val)
{
if (!(val & VGUIWindowClosable)) {
m_btnClose.Hide();
}
m_styleMask = val;
}
void
@ -140,7 +168,7 @@ void VGUIWindow::Draw(void)
drawfill(m_vecOrigin + [0, 1], [1, m_vecSize[1] - 2], m_vecColor, 1.0f);
drawfill(m_vecOrigin + [m_vecSize[0] - 1, 1], [1, m_vecSize[1] - 2], m_vecColor, 1.0f);
if (m_iFlags & WINDOW_CANRESIZE) {
if (m_styleMask & VGUIWindowResizeable) {
drawpic(m_vecOrigin + m_vecSize - [16,16], "textures/ui/steam/icon_resizer", [16,16], m_vecColor, 1.0f, 0);
}
#else
@ -150,11 +178,12 @@ void VGUIWindow::Draw(void)
drawfill(m_vecOrigin + [0, 1], [1, m_vecSize[1] - 2], [1,1,1], 0.5f);
drawfill(m_vecOrigin + [m_vecSize[0] - 1, 1], [1, m_vecSize[1] - 2], [0,0,0], 0.5f);
if (m_iFlags & WINDOW_CANRESIZE) {
if (m_styleMask & VGUIWindowResizeable) {
drawpic(m_vecOrigin + m_vecSize - [16,16], "textures/ui/steam/icon_resizer", [16,16], m_vecColor, 1.0f, 0);
}
#endif
if (m_styleMask & VGUIWindowTitled)
if (m_strTitle) {
if (m_strIcon) {
Font_DrawText(m_vecOrigin + [26, 8], m_strTitle, g_fntDefault);
@ -163,7 +192,7 @@ void VGUIWindow::Draw(void)
Font_DrawText(m_vecOrigin + [8, 8], m_strTitle, g_fntDefault);
}
}
#ifdef UI_DEVELOPER
if (m_iFlags & WINDOW_DRAGGING) {
Font_DrawText([8, video_res[1] - 18], sprintf("Window Position: %d, %d\n", m_vecOrigin[0], m_vecOrigin[1]), g_fntDefault);
@ -180,9 +209,9 @@ bool VGUIWindow::Input (float flEVType, float flKey, float flChar, float flDevID
if (flEVType == IE_KEYDOWN) {
if (flKey == K_MOUSE1) {
if (m_iFlags & WINDOW_CANRESIZE && Util_MouseAbove(g_vecMousePos, m_vecOrigin + (m_vecSize - [16,16]), [16,16])) {
if (m_styleMask & VGUIWindowResizeable && Util_MouseAbove(g_vecMousePos, m_vecOrigin + (m_vecSize - [16,16]), [16,16])) {
m_iFlags |= WINDOW_RESIZING;
} else if (Util_MouseAbove(g_vecMousePos, m_vecOrigin, [m_vecSize[0] - 32, 16])) {
} else if (m_styleMask & VGUIWindowMovable && Util_MouseAbove(g_vecMousePos, m_vecOrigin, [m_vecSize[0] - 32, 16])) {
m_iFlags |= WINDOW_DRAGGING;
m_vecDragOffset = m_vecOrigin - g_vecMousePos;
}