From 9d8f933237dbb0a7366f8e0d8a328a14896242cf Mon Sep 17 00:00:00 2001 From: terencehill Date: Thu, 10 Mar 2022 11:51:33 +0100 Subject: [PATCH] Show a welcome window with MOTD on server connection Usual welcome message not removed for compatibility with previous Xonotic versions --- gfx/menu/luma/skinvalues.txt | 3 +- gfx/menu/luminos/skinvalues.txt | 2 + gfx/menu/wickedx/skinvalues.txt | 2 + gfx/menu/xaw/skinvalues.txt | 2 + qcsrc/client/main.qc | 12 +++++ qcsrc/common/net_linked.qh | 1 + qcsrc/menu/command/menu_cmd.qc | 22 +++++++++ qcsrc/menu/skin-customizables.inc | 1 + qcsrc/menu/xonotic/_mod.inc | 1 + qcsrc/menu/xonotic/_mod.qh | 1 + qcsrc/menu/xonotic/dialog_welcome.qc | 68 ++++++++++++++++++++++++++++ qcsrc/menu/xonotic/dialog_welcome.qh | 19 ++++++++ qcsrc/menu/xonotic/mainwindow.qc | 5 ++ qcsrc/menu/xonotic/textbox.qc | 11 +++-- qcsrc/menu/xonotic/textbox.qh | 3 ++ qcsrc/server/client.qc | 17 +++++-- qcsrc/server/command/cmd.qh | 2 + 17 files changed, 165 insertions(+), 7 deletions(-) create mode 100644 qcsrc/menu/xonotic/dialog_welcome.qc create mode 100644 qcsrc/menu/xonotic/dialog_welcome.qh diff --git a/gfx/menu/luma/skinvalues.txt b/gfx/menu/luma/skinvalues.txt index eef45e9a0a..1bf37b98b8 100644 --- a/gfx/menu/luma/skinvalues.txt +++ b/gfx/menu/luma/skinvalues.txt @@ -92,9 +92,10 @@ COLOR_DIALOG_VIEW '1 1 1' COLOR_DIALOG_MODEL '1 1 1' COLOR_DIALOG_CROSSHAIR '1 1 1' COLOR_DIALOG_HUD '1 1 1' -COLOR_DIALOG_SCREENSHOTVIEWER '1 1 1' COLOR_DIALOG_SERVERINFO '1 1 1' +COLOR_DIALOG_SCREENSHOTVIEWER '1 1 1' COLOR_DIALOG_FIRSTRUN '1 1 1' +COLOR_DIALOG_WELCOME '1 1 1' COLOR_DIALOG_CVARS '1 0.2 0.15' COLOR_DIALOG_HUDCONFIRM '1 0.2 0.15' diff --git a/gfx/menu/luminos/skinvalues.txt b/gfx/menu/luminos/skinvalues.txt index 2ffe29af0c..d4fdef1cd5 100755 --- a/gfx/menu/luminos/skinvalues.txt +++ b/gfx/menu/luminos/skinvalues.txt @@ -193,6 +193,8 @@ COLOR_DIALOG_CROSSHAIR '1 1 1' COLOR_DIALOG_HUD '1 1 1' COLOR_DIALOG_SERVERINFO '1 1 1' COLOR_DIALOG_SCREENSHOTVIEWER '1 1 1' +COLOR_DIALOG_FIRSTRUN '1 1 1' +COLOR_DIALOG_WELCOME '1 1 1' COLOR_DIALOG_CVARS '1 0 0' COLOR_DIALOG_HUDCONFIRM '1 0 0' diff --git a/gfx/menu/wickedx/skinvalues.txt b/gfx/menu/wickedx/skinvalues.txt index 0580e89eb1..ca5e303dac 100644 --- a/gfx/menu/wickedx/skinvalues.txt +++ b/gfx/menu/wickedx/skinvalues.txt @@ -193,6 +193,8 @@ COLOR_DIALOG_CROSSHAIR '1 1 1' COLOR_DIALOG_HUD '1 1 1' COLOR_DIALOG_SERVERINFO '1 1 1' COLOR_DIALOG_SCREENSHOTVIEWER '1 1 1' +COLOR_DIALOG_FIRSTRUN '1 1 1' +COLOR_DIALOG_WELCOME '1 1 1' COLOR_DIALOG_CVARS '1 0 0' COLOR_DIALOG_HUDCONFIRM '1 0 0' diff --git a/gfx/menu/xaw/skinvalues.txt b/gfx/menu/xaw/skinvalues.txt index af7d8ce165..aa4350cc56 100644 --- a/gfx/menu/xaw/skinvalues.txt +++ b/gfx/menu/xaw/skinvalues.txt @@ -37,6 +37,8 @@ COLOR_DIALOG_CROSSHAIR '1 1 1' COLOR_DIALOG_HUD '1 1 1' COLOR_DIALOG_SERVERINFO '1 1 1' COLOR_DIALOG_SCREENSHOTVIEWER '1 1 1' +COLOR_DIALOG_FIRSTRUN '1 1 1' +COLOR_DIALOG_WELCOME '1 1 1' COLOR_DIALOG_CVARS '1 0 0' COLOR_DIALOG_HUDCONFIRM '1 0 0' diff --git a/qcsrc/client/main.qc b/qcsrc/client/main.qc index 7acbfe6cba..f3f06acd55 100644 --- a/qcsrc/client/main.qc +++ b/qcsrc/client/main.qc @@ -1286,6 +1286,18 @@ NET_HANDLE(TE_CSQC_WEAPONCOMPLAIN, bool isNew) } } +string welcomedialog_args; +NET_HANDLE(TE_CSQC_SERVERINFO, bool isNew) +{ + if(welcomedialog_args) + strunzone(welcomedialog_args); + welcomedialog_args = strcat("name \"", ReadString(), "\""); + welcomedialog_args = strcat(welcomedialog_args, " motd \"", MakeConsoleSafe(strreplace("\n", "\\n", ReadString())), "\""); + localcmd("\nmenu_cmd directmenu Welcome ", welcomedialog_args, "\n"); + welcomedialog_args = string_null; + return true; +} + string _getcommandkey(string cmd_name, string command, bool forcename) { string keys; diff --git a/qcsrc/common/net_linked.qh b/qcsrc/common/net_linked.qh index 6651c6cb9b..0b5923f173 100644 --- a/qcsrc/common/net_linked.qh +++ b/qcsrc/common/net_linked.qh @@ -5,6 +5,7 @@ REGISTER_NET_TEMP(TE_CSQC_RACE) REGISTER_NET_TEMP(TE_CSQC_TEAMNAGGER) REGISTER_NET_TEMP(TE_CSQC_PINGPLREPORT) REGISTER_NET_TEMP(TE_CSQC_WEAPONCOMPLAIN) +REGISTER_NET_TEMP(TE_CSQC_SERVERINFO) REGISTER_NET_TEMP(TE_CSQC_VEHICLESETUP) const int RACE_NET_CHECKPOINT_HIT_QUALIFYING = 0; // byte checkpoint, short time, short recordtime, string recordholder diff --git a/qcsrc/menu/command/menu_cmd.qc b/qcsrc/menu/command/menu_cmd.qc index c4593e87aa..8de4bf4f03 100644 --- a/qcsrc/menu/command/menu_cmd.qc +++ b/qcsrc/menu/command/menu_cmd.qc @@ -7,6 +7,7 @@ #include +.void(entity me, float argsbuf) readInputArgs; .entity firstChild, nextSibling; string _dumptree_space; @@ -97,6 +98,27 @@ void GameCommand(string theCommand) m_play_click_sound(MENU_SOUND_OPEN); m_goto(strcat(filter, argv(1))); // switch to a menu item } + else if(argc > 2 && !isdemo()) + { + entity e = NULL; + float argsbuf = 0; + string s = strzone(argv(1)); // dialog name + for(int i = 0; (e = nextent(e)); ) + if(e.classname != "vtbl" && e.name == strcat(filter, s)) + { + argsbuf = buf_create(); + if(argsbuf >= 0) + if(e.readInputArgs) + { + for(i = 2; i < argc; ++i) + bufstr_add(argsbuf, argv(i), 1); + e.readInputArgs(e, argsbuf); + m_goto(strcat(filter, s)); + } + if(argsbuf >= 0) + buf_del(argsbuf); + } + } return; } diff --git a/qcsrc/menu/skin-customizables.inc b/qcsrc/menu/skin-customizables.inc index 54f6283b80..15bd5356b8 100644 --- a/qcsrc/menu/skin-customizables.inc +++ b/qcsrc/menu/skin-customizables.inc @@ -70,6 +70,7 @@ SKINBEGIN SKINVECTOR(COLOR_DIALOG_CROSSHAIR, '1 0.7 0.7'); SKINVECTOR(COLOR_DIALOG_HUD, '1 0.7 0.7'); SKINVECTOR(COLOR_DIALOG_SERVERINFO, '0.7 0.7 1'); + SKINVECTOR(COLOR_DIALOG_WELCOME, '1 0.7 0.7'); SKINVECTOR(COLOR_DIALOG_CVARS, '1 0 0'); SKINVECTOR(COLOR_DIALOG_SCREENSHOTVIEWER, '0.7 0.7 1'); SKINVECTOR(COLOR_DIALOG_HUDCONFIRM, '1 0 0'); diff --git a/qcsrc/menu/xonotic/_mod.inc b/qcsrc/menu/xonotic/_mod.inc index 1c09f35866..cd3b9cb471 100644 --- a/qcsrc/menu/xonotic/_mod.inc +++ b/qcsrc/menu/xonotic/_mod.inc @@ -86,6 +86,7 @@ #include #include #include +#include #include #include #include diff --git a/qcsrc/menu/xonotic/_mod.qh b/qcsrc/menu/xonotic/_mod.qh index 7c3ab9059b..a1e9e31e1c 100644 --- a/qcsrc/menu/xonotic/_mod.qh +++ b/qcsrc/menu/xonotic/_mod.qh @@ -86,6 +86,7 @@ #include #include #include +#include #include #include #include diff --git a/qcsrc/menu/xonotic/dialog_welcome.qc b/qcsrc/menu/xonotic/dialog_welcome.qc new file mode 100644 index 0000000000..14dabdc4c0 --- /dev/null +++ b/qcsrc/menu/xonotic/dialog_welcome.qc @@ -0,0 +1,68 @@ +#include "dialog_welcome.qh" + +#include "image.qh" +#include "textlabel.qh" +#include "textbox.qh" +#include "radiobutton.qh" +#include "commandbutton.qh" +#include "slider.qh" + +void welcomeDialog_resetStrings(entity me) +{ + if(me.serverinfo_name) + strunzone(me.serverinfo_name); + me.serverinfo_name = strzone(_("")); + + if(me.serverinfo_MOTD) + strunzone(me.serverinfo_MOTD); + me.serverinfo_MOTD = strzone(_("")); +} +void XonoticWelcomeDialog_configureDialog(entity me) +{ + welcomeDialog_resetStrings(me); + SUPER(XonoticWelcomeDialog).configureDialog(me); +} +void XonoticWelcomeDialog_readInputArgs(entity me, float argsbuf) +{ + int i = 0; + string s; + welcomeDialog_resetStrings(me); + if(argsbuf >= 0) + while((s = bufstr_get(argsbuf, i)) != "") + { + if(s == "name") + { + if(me.serverinfo_name) + strunzone(me.serverinfo_name); + me.serverinfo_name = strzone(bufstr_get(argsbuf, i + 1)); + ++i; + } + else if(s == "motd") + { + if(me.serverinfo_MOTD) + strunzone(me.serverinfo_MOTD); + me.serverinfo_MOTD = strzone(bufstr_get(argsbuf, i + 1)); + ++i; + } + ++i; + } + //me.serverinfo_name_ent.setText(me.serverinfo_name_ent, me.serverinfo_name); + me.serverinfo_MOTD_ent.setText(me.serverinfo_MOTD_ent, me.serverinfo_MOTD); + me.frame.setText(me.frame, me.serverinfo_name); +} + +void XonoticWelcomeDialog_fill(entity me) +{ + entity e; + + me.TR(me); + me.TD(me, me.rows - 1, me.columns, me.serverinfo_MOTD_ent = makeXonoticTextBox()); + me.serverinfo_MOTD_ent.align = 0.5; + me.serverinfo_MOTD_ent.allowColors = true; + me.serverinfo_MOTD_ent.escapedNewLines = true; + me.gotoRC(me, me.rows - 1, 0); + me.TD(me, 1, me.columns, e = makeXonoticButton(_("OK"), '0 0 0')); + e.onClick = Dialog_Close; + e.onClickEntity = me; + e.preferredFocusPriority = 1; +} diff --git a/qcsrc/menu/xonotic/dialog_welcome.qh b/qcsrc/menu/xonotic/dialog_welcome.qh new file mode 100644 index 0000000000..44458bfdeb --- /dev/null +++ b/qcsrc/menu/xonotic/dialog_welcome.qh @@ -0,0 +1,19 @@ +#pragma once + +#include "rootdialog.qh" +CLASS(XonoticWelcomeDialog, XonoticRootDialog) + METHOD(XonoticWelcomeDialog, fill, void(entity)); + ATTRIB(XonoticWelcomeDialog, title, string, _("Welcome")); + ATTRIB(XonoticWelcomeDialog, color, vector, SKINCOLOR_DIALOG_WELCOME); + ATTRIB(XonoticWelcomeDialog, intendedWidth, float, 0.8); + ATTRIB(XonoticWelcomeDialog, rows, float, 12); + ATTRIB(XonoticWelcomeDialog, columns, float, 4); + ATTRIB(XonoticWelcomeDialog, name, string, "Welcome"); + + METHOD(XonoticWelcomeDialog, configureDialog, void(entity)); + METHOD(XonoticWelcomeDialog, readInputArgs, void(entity, float)); + ATTRIB(XonoticWelcomeDialog, serverinfo_name, string, string_null); + //ATTRIB(XonoticWelcomeDialog, serverinfo_name_ent, entity, world); + ATTRIB(XonoticWelcomeDialog, serverinfo_MOTD, string, string_null); + ATTRIB(XonoticWelcomeDialog, serverinfo_MOTD_ent, entity, world); +ENDCLASS(XonoticWelcomeDialog) diff --git a/qcsrc/menu/xonotic/mainwindow.qc b/qcsrc/menu/xonotic/mainwindow.qc index f5d2aca98e..8377c561e4 100644 --- a/qcsrc/menu/xonotic/mainwindow.qc +++ b/qcsrc/menu/xonotic/mainwindow.qc @@ -43,6 +43,7 @@ #include "dialog_multiplayer_create_mutators.qh" #include "dialog_sandboxtools.qh" #include "dialog_monstertools.qh" +#include "dialog_welcome.qh" #include "dialog_teamselect.qh" #include "dialog_uid2name.qh" #include "dialog_singleplayer.qh" @@ -121,6 +122,10 @@ void MainWindow_configureMainWindow(entity me) i.configureDialog(i); me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z); + i = NEW(XonoticWelcomeDialog); + i.configureDialog(i); + me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z); + // hud_configure dialogs i = NEW(XonoticHUDExitDialog); diff --git a/qcsrc/menu/xonotic/textbox.qc b/qcsrc/menu/xonotic/textbox.qc index 1027d0c9e1..e2eaf2a854 100644 --- a/qcsrc/menu/xonotic/textbox.qc +++ b/qcsrc/menu/xonotic/textbox.qc @@ -32,13 +32,14 @@ void XonoticTextBox_setText(entity me, string text) string t; buf = buf_create(); - for (int i = 0, n = tokenizebyseparator(text, "\n"); i < n; ++i) + string separator = (me.escapedNewLines) ? "\\n" : "\n"; + for (int i = 0, n = tokenizebyseparator(text, separator); i < n; ++i) { t = substring(argv(i), 0, -1); getWrappedLine_remaining = t; while (getWrappedLine_remaining) { - t = getWrappedLine(1, me.realFontSize, draw_TextWidth_WithColors); + t = getWrappedLine(1, me.realFontSize, (me.allowColors) ? draw_TextWidth_WithColors : draw_TextWidth_WithoutColors); bufstr_set(buf, line, t); line++; } @@ -86,5 +87,9 @@ void XonoticTextBox_resizeNotify(entity me, vector relOrigin, vector relSize, ve void XonoticTextBox_drawListBoxItem(entity me, int i, vector absSize, bool isSelected, bool isFocused) { string s = me.getTextBoxLine(me, i); - draw_Text(vec2(0, 0), s, me.realFontSize, me.colorL, me.alpha, true); + vector color = (me.allowColors) ? '1 1 1' : me.colorL; + if (me.align == 0.5) + draw_CenterText(me.realUpperMargin * eY + 0.5 * eX, s, me.realFontSize, color, 1, me.allowColors); + else + draw_Text(vec2(0, 0), s, me.realFontSize, color, me.alpha, me.allowColors); } diff --git a/qcsrc/menu/xonotic/textbox.qh b/qcsrc/menu/xonotic/textbox.qh index b27481671a..3289d7b4db 100644 --- a/qcsrc/menu/xonotic/textbox.qh +++ b/qcsrc/menu/xonotic/textbox.qh @@ -9,6 +9,9 @@ CLASS(XonoticTextBox, XonoticListBox) METHOD(XonoticTextBox, resizeNotify, void(entity, vector, vector, vector, vector)); METHOD(XonoticTextBox, drawListBoxItem, void(entity, int, vector, bool, bool)); ATTRIB(XonoticTextBox, allowFocusSound, float, 0); + ATTRIB(XonoticTextBox, align, float, 0); + ATTRIB(XonoticTextBox, allowColors, bool, false); + ATTRIB(XonoticTextBox, escapedNewLines, bool, false); ATTRIB(XonoticTextBox, alpha, float, SKINALPHA_TEXT); ATTRIB(XonoticTextBox, fontSize, float, SKINFONTSIZE_NORMAL); ATTRIB(XonoticTextBox, realFontSize, vector, '0 0 0'); diff --git a/qcsrc/server/client.qc b/qcsrc/server/client.qc index 8ae3df1938..3d0fffe0a0 100644 --- a/qcsrc/server/client.qc +++ b/qcsrc/server/client.qc @@ -1055,10 +1055,9 @@ string getwelcomemessage(entity this) modifications = strcat(modifications, ", Jet pack"); modifications = substring(modifications, 2, strlen(modifications) - 2); - string versionmessage = GetClientVersionMessage(this); - string s = strcat(versionmessage, "^8\n^8\nserver is ^9", autocvar_hostname, "^8\n"); + string s = GetClientVersionMessage(this); - s = strcat(s, "^8\nmatch type is ^1", gamemode_name, "^8\n"); + s = strcat(s, "^8\n\nmatch type is ^1", gamemode_name, "^8\n"); if(modifications != "") s = strcat(s, "^8\nactive modifications: ^3", modifications, "^8\n"); @@ -1086,6 +1085,14 @@ string getwelcomemessage(entity this) return s; } +void serverinfo_welcomemessage_send(entity this) +{ + msg_entity = this; + WriteHeader(MSG_ONE, TE_CSQC_SERVERINFO); + WriteString(MSG_ONE, autocvar_hostname); + WriteString(MSG_ONE, getwelcomemessage(this)); +} + /** ============= ClientConnect @@ -1173,7 +1180,11 @@ void ClientConnect(entity this) CS(this).model_randomizer = random(); if (IS_REAL_CLIENT(this)) + { + if (!autocvar_g_campaign) + serverinfo_welcomemessage_send(this); sv_notice_join(this); + } this.move_qcphysics = autocvar_sv_qcphysics; diff --git a/qcsrc/server/command/cmd.qh b/qcsrc/server/command/cmd.qh index 802afc8bde..344cba0eb0 100644 --- a/qcsrc/server/command/cmd.qh +++ b/qcsrc/server/command/cmd.qh @@ -8,5 +8,7 @@ int autocvar_sv_clientcommand_antispam_count; string MapVote_Suggest(entity this, string m); +void serverinfo_welcomemessage_send(entity this); + // used by common/command/generic.qc:GenericCommand_dumpcommands to list all commands into a .txt file void ClientCommand_macro_write_aliases(float fh); -- 2.39.2