Last active
April 16, 2016 21:48
-
-
Save Henningstone/c6aea68b0247a221f496 to your computer and use it in GitHub Desktop.
Patch to implement tw_netgui version 0.1-b.3-rev1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 24de4ea3e85ba68c31d3ebd110fae112a1be7f1b Mon Sep 17 00:00:00 2001 | |
From: Henningstone <[email protected]> | |
Date: Mon, 28 Dec 2015 22:19:36 +0100 | |
Subject: [PATCH] Basic NetGUI implementation | |
--- | |
datasrc/network.py | 107 ++++++++++ | |
src/engine/client/client.cpp | 8 + | |
src/game/client/components/menus.h | 3 +- | |
src/game/client/components/menus_ingame.cpp | 142 +++++++++++++ | |
src/game/client/components/netgui.cpp | 224 ++++++++++++++++++++ | |
src/game/client/components/netgui.h | 59 ++++++ | |
src/game/client/gameclient.cpp | 4 + | |
src/game/client/gameclient.h | 1 + | |
src/game/netguidefines.h | 18 ++ | |
src/game/server/gamecontext.cpp | 13 ++ | |
src/game/server/gamecontext.h | 2 + | |
src/game/server/netgui.cpp | 314 ++++++++++++++++++++++++++++ | |
src/game/server/netgui.h | 59 ++++++ | |
src/game/version.h | 1 + | |
14 files changed, 954 insertions(+), 1 deletion(-) | |
create mode 100644 src/game/client/components/netgui.cpp | |
create mode 100644 src/game/client/components/netgui.h | |
create mode 100644 src/game/netguidefines.h | |
create mode 100644 src/game/server/netgui.cpp | |
create mode 100644 src/game/server/netgui.h | |
diff --git a/datasrc/network.py b/datasrc/network.py | |
index f62e663..11e6bdf 100644 | |
--- a/datasrc/network.py | |
+++ b/datasrc/network.py | |
@@ -401,4 +401,111 @@ Messages = [ | |
NetStringStrict("m_pMessage"), | |
]), | |
+ | |
+ ### NetGUI | |
+ ## Server | |
+ NetMessage("Sv_NetGui_RemoveElement", [ | |
+ NetIntAny("m_Type"), | |
+ NetIntAny("m_ID"), | |
+ ]), | |
+ | |
+ NetMessage("Sv_NetGui_RequestData", [ | |
+ NetIntAny("m_ID"), | |
+ NetIntAny("m_Type"), | |
+ ]), | |
+ | |
+ NetMessage("Sv_NetGui_UIRect", [ | |
+ NetIntAny("m_ID"), | |
+ NetArray(NetIntRange("m_Dimension", 0, 100), 4), | |
+ NetArray(NetIntRange("m_Color", 0, 100), 4), | |
+ NetIntRange("m_Corner", 0, 255), | |
+ NetIntRange("m_RoundingX10", 0, 500), | |
+ ]), | |
+ | |
+ NetMessage("Sv_NetGui_Label", [ | |
+ NetIntAny("m_ID"), | |
+ NetString("m_Text"), | |
+ NetArray(NetIntRange("m_Dimension", 0, 100), 4), | |
+ NetArray(NetIntRange("m_Color", 0, 100), 4), | |
+ NetIntAny("m_FontSize"), | |
+ NetIntRange("m_FontAlign", 0, 2), | |
+ NetIntRange("m_MaxTextWidth", 0, 100), | |
+ ]), | |
+ | |
+ NetMessage("Sv_NetGui_ButtonMenu", [ | |
+ NetIntAny("m_ID"), | |
+ NetString("m_Text"), | |
+ NetIntRange("m_Selected", 0, 1), | |
+ NetArray(NetIntRange("m_Dimension", 0, 100), 4), | |
+ ]), | |
+ | |
+ NetMessage("Sv_NetGui_EditBox", [ | |
+ NetIntAny("m_ID"), | |
+ NetArray(NetIntRange("m_Dimension", 0, 100), 4), | |
+ NetString("m_Title"), | |
+ NetIntAny("m_SplitValue"), | |
+ NetIntAny("m_MaxTextWidth"), | |
+ NetIntRange("m_Password", 0, 1), | |
+ ]), | |
+ | |
+ NetMessage("Sv_NetGui_CheckBox", [ | |
+ NetIntAny("m_ID"), | |
+ NetArray(NetIntRange("m_Dimension", 0, 100), 4), | |
+ NetString("m_Text"), | |
+ NetIntRange("m_Checked", 0, 1), | |
+ ]), | |
+ | |
+ NetMessage("Sv_NetGui_CheckBoxNumber", [ | |
+ NetIntAny("m_ID"), | |
+ NetArray(NetIntRange("m_Dimension", 0, 100), 4), | |
+ NetString("m_Text"), | |
+ NetIntAny("m_Value"), | |
+ NetIntAny("m_MinValue"), | |
+ NetIntAny("m_MaxValue"), | |
+ NetIntAny("m_StepValue"), | |
+ ]), | |
+ | |
+ NetMessage("Sv_NetGui_Scrollbar", [ | |
+ NetIntAny("m_ID"), | |
+ NetArray(NetIntRange("m_Dimension", 0, 100), 4), | |
+ NetIntAny("m_ValueX100"), | |
+ NetIntRange("m_Vertical", 0, 1), | |
+ ]), | |
+ | |
+ NetMessage("Sv_NetGui_ScrollbarOption", [ | |
+ NetIntAny("m_ID"), | |
+ NetArray(NetIntRange("m_Dimension", 0, 100), 4), | |
+ NetString("m_Text"), | |
+ NetIntAny("m_VSplitValX10"), | |
+ NetIntAny("m_Value"), | |
+ NetIntAny("m_MinValue"), | |
+ NetIntAny("m_MaxValue"), | |
+ NetIntRange("m_Infinite", 0, 1), | |
+ ]), | |
+ | |
+ NetMessage("Sv_NetGui_InfoBox", [ | |
+ NetIntAny("m_ID"), | |
+ NetArray(NetIntRange("m_Dimension", 0, 100), 4), | |
+ NetString("m_Label"), | |
+ NetString("m_Value"), | |
+ ]), | |
+ | |
+ ## NetGui - Client | |
+ NetMessage("Cl_NetGui_TriggerEvent", [ | |
+ NetIntAny("m_Type"), | |
+ NetIntAny("m_ID"), | |
+ ]), | |
+ | |
+ NetMessage("Cl_NetGui_ResponseInt", [ | |
+ NetIntAny("m_ID"), | |
+ NetIntAny("m_Type"), | |
+ NetIntAny("m_Value"), | |
+ ]), | |
+ | |
+ NetMessage("Cl_NetGui_ResponseString", [ | |
+ NetIntAny("m_ID"), | |
+ NetIntAny("m_Type"), | |
+ NetString("m_Text"), | |
+ ]), | |
+ | |
] | |
diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp | |
index f382948..8e8a2dc 100644 | |
--- a/src/engine/client/client.cpp | |
+++ b/src/engine/client/client.cpp | |
@@ -38,6 +38,8 @@ | |
#include <game/version.h> | |
+#include <generated/protocol.h> | |
+ | |
#include <mastersrv/mastersrv.h> | |
#include <versionsrv/versionsrv.h> | |
@@ -509,6 +511,12 @@ void CClient::EnterGame() | |
// to finish the connection | |
SendEnterGame(); | |
OnEnterGame(); | |
+ | |
+ // tell the server that this is a netgui compatible client | |
+ CNetMsg_Cl_NetGui_TriggerEvent NGMsg; | |
+ NGMsg.m_Type = 1883; | |
+ NGMsg.m_ID = 5397; | |
+ SendPackMsg(&NGMsg, MSGFLAG_VITAL); | |
} | |
void CClient::Connect(const char *pAddress) | |
diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h | |
index 4dd5666..97d1290 100644 | |
--- a/src/game/client/components/menus.h | |
+++ b/src/game/client/components/menus.h | |
@@ -430,7 +430,8 @@ class CMenus : public CComponent | |
void RenderServerControl(CUIRect MainView); | |
void RenderServerControlKick(CUIRect MainView, bool FilterSpectators); | |
void RenderServerControlServer(CUIRect MainView); | |
- | |
+ void RenderNetGui(CUIRect MainView); | |
+ | |
// found in menus_browser.cpp | |
int m_ScrollOffset; | |
void RenderServerbrowserServerList(CUIRect View); | |
diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp | |
index 7044ec0..8708f64 100644 | |
--- a/src/game/client/components/menus_ingame.cpp | |
+++ b/src/game/client/components/menus_ingame.cpp | |
@@ -20,6 +20,7 @@ | |
#include "menus.h" | |
#include "motd.h" | |
+#include "netgui.h" | |
#include "voting.h" | |
void CMenus::RenderGame(CUIRect MainView) | |
@@ -184,6 +185,12 @@ void CMenus::RenderGame(CUIRect MainView) | |
static int s_DisconnectButton = 0; | |
if(DoButton_Menu(&s_DisconnectButton, Localize("Disconnect"), 0, &Right)) | |
Client()->Disconnect(); | |
+ | |
+ // NetGui | |
+ // keep empty space at the top for notifications | |
+ if(!pNotification) | |
+ MainView.HSplitTop(45.0f, 0, &MainView); | |
+ RenderNetGui(MainView); | |
} | |
void CMenus::RenderPlayers(CUIRect MainView) | |
@@ -456,6 +463,141 @@ void CMenus::RenderServerControlKick(CUIRect MainView, bool FilterSpectators) | |
m_CallvoteSelectedPlayer = Selected != -1 ? aPlayerIDs[Selected] : -1; | |
} | |
+// NetGui | |
+#define GUIPREPARE(name) \ | |
+ for(int i = 0; i < m_pClient->m_pNetGui->m_NetGui##name.size(); i++)\ | |
+ {\ | |
+ if(i >= 1024) break;\ | |
+ CUIRect Rect;\ | |
+ CNetMsg_Sv_NetGui_##name *e = &m_pClient->m_pNetGui->m_NetGui##name[i];\ | |
+ float xa = MainView.x + ((float)e->m_Dimension[0]/100.0f) * MainView.w;\ | |
+ float xb = MainView.x + ((float)e->m_Dimension[1]/100.0f) * MainView.w;\ | |
+ float yb = MainView.y + ((float)e->m_Dimension[2]/100.0f) * MainView.h;\ | |
+ float ya = MainView.y + ((float)e->m_Dimension[3]/100.0f) * MainView.h;\ | |
+ Rect.x = xa;\ | |
+ Rect.y = ya;\ | |
+ Rect.w = xb - xa;\ | |
+ Rect.h = yb - ya; | |
+ | |
+void CMenus::RenderNetGui(CUIRect MainView) | |
+{ | |
+ // UIRect | |
+ GUIPREPARE(UIRect) | |
+ vec4 Color = vec4( | |
+ e->m_Color[0]/100.0f, | |
+ e->m_Color[1]/100.0f, | |
+ e->m_Color[2]/100.0f, | |
+ e->m_Color[3]/100.0f); | |
+ RenderTools()->DrawUIRect(&Rect, Color, e->m_Corner, e->m_RoundingX10/10.0f); | |
+ } | |
+ | |
+ | |
+ // Label | |
+ GUIPREPARE(Label) | |
+ switch(e->m_FontAlign) | |
+ { | |
+ case 1: // center | |
+ Rect.x += (Rect.w - TextRender()->TextWidth(0, e->m_FontSize, e->m_Text, -1))/2; | |
+ break; | |
+ case 2: // right | |
+ Rect.x += Rect.w - TextRender()->TextWidth(0, e->m_FontSize, e->m_Text, -1); | |
+ break; | |
+ default: // anything but 1 and 2 will result in left-aligned | |
+ break; | |
+ } | |
+ TextRender()->TextColor( | |
+ e->m_Color[0]/100.0f, | |
+ e->m_Color[1]/100.0f, | |
+ e->m_Color[2]/100.0f, | |
+ e->m_Color[3]/100.0f); | |
+ | |
+ TextRender()->Text(0, Rect.x, Rect.y, e->m_FontSize, e->m_Text, e->m_MaxTextWidth*(int)MainView.w); | |
+ } | |
+ TextRender()->TextColor(1,1,1,1); | |
+ | |
+ | |
+ // ButtonMenu | |
+ GUIPREPARE(ButtonMenu) | |
+ static int s_ID[1024] = {0}; // nobody will create so much buttons :p | |
+ if(DoButton_Menu(&s_ID[i], e->m_Text, e->m_Selected, &Rect)) | |
+ m_pClient->m_pNetGui->SendEvent(NETMSGTYPE_SV_NETGUI_BUTTONMENU, e->m_ID); | |
+ } | |
+ | |
+ | |
+ // EditBox | |
+ GUIPREPARE(EditBox) | |
+ static char aText[1024][1024]; | |
+ static float s_Offset[1024] = {0}; | |
+ static int s_ID[1024] ={0}; | |
+ DoEditBoxOption((void *)&s_ID[i], aText[i], e->m_MaxTextWidth, &Rect, e->m_Title, ((float)e->m_SplitValue/100.0f)*Rect.w, &s_Offset[i], e->m_Password == 1 ? true : false); | |
+ str_copy(m_pClient->m_pNetGui->m_aNetGuiEditBoxContent[i], aText[i], sizeof(m_pClient->m_pNetGui->m_aNetGuiEditBoxContent[i])); | |
+ } | |
+ | |
+ | |
+ // CheckBox | |
+ GUIPREPARE(CheckBox) | |
+ static int s_ID[1024] = {0}; | |
+ if(DoButton_CheckBox(&s_ID[i], e->m_Text, e->m_Checked, &Rect)) | |
+ e->m_Checked ^= 1; | |
+ } | |
+ | |
+ | |
+ // CheckBoxNumber | |
+ GUIPREPARE(CheckBoxNumber) | |
+ static int s_ID[1024] = {0}; | |
+ int MouseButton = DoButton_CheckBox_Number(&s_ID[i], e->m_Text, e->m_Value, &Rect); | |
+ if(MouseButton == 1) // primary click | |
+ { | |
+ char aBuf[128]; | |
+ str_format(aBuf, sizeof(aBuf), "step=%d", e->m_StepValue); | |
+ if(e->m_Value == e->m_MaxValue) | |
+ e->m_Value = e->m_MinValue; | |
+ else if(e->m_Value + e->m_StepValue > e->m_MaxValue) | |
+ e->m_Value = e->m_MaxValue; | |
+ else | |
+ e->m_Value += e->m_StepValue; | |
+ } | |
+ else if(MouseButton == 2) // secondary click | |
+ { | |
+ | |
+ if(e->m_Value == e->m_MinValue) | |
+ e->m_Value = e->m_MaxValue; | |
+ else if(e->m_Value - e->m_StepValue < e->m_MinValue) | |
+ e->m_Value = e->m_MinValue; | |
+ else | |
+ e->m_Value -= e->m_StepValue; | |
+ } | |
+ } | |
+ | |
+ | |
+ // Scrollbar | |
+ GUIPREPARE(Scrollbar) | |
+ static int s_ID[1024] = {0}; | |
+ static float s_Value[1024] = {0.0f}; | |
+ if(e->m_Vertical) | |
+ s_Value[i] = DoScrollbarV(&s_ID[i], &Rect, s_Value[i]); | |
+ else | |
+ s_Value[i] = DoScrollbarH(&s_ID[i], &Rect, s_Value[i]); | |
+ | |
+ e->m_ValueX100 = (int)(s_Value[i] * 100.0f); | |
+ } | |
+ | |
+ | |
+ // ScrollbarOption | |
+ GUIPREPARE(ScrollbarOption) | |
+ static int s_ID[1024] = {0}; | |
+ static int s_Value[1024] = {0}; | |
+ DoScrollbarOption(&s_ID[i], &s_Value[i], &Rect, e->m_Text, (((float)e->m_VSplitValX10/10.0f)/100.0f)*Rect.w, e->m_MinValue, e->m_MaxValue, e->m_Infinite == 1 ? true : false); | |
+ e->m_Value = s_Value[i]; | |
+ } | |
+ | |
+ | |
+ // InfoBox | |
+ GUIPREPARE(InfoBox) | |
+ DoInfoBox(&Rect, e->m_Label, e->m_Value); | |
+ } | |
+} | |
+ | |
void CMenus::HandleCallvote(int Page, bool Force) | |
{ | |
if(Page == 0) | |
diff --git a/src/game/client/components/netgui.cpp b/src/game/client/components/netgui.cpp | |
new file mode 100644 | |
index 0000000..38c277a | |
--- /dev/null | |
+++ b/src/game/client/components/netgui.cpp | |
@@ -0,0 +1,224 @@ | |
+// Copyright (c) 2015 Henritees | |
+ | |
+#include "netgui.h" | |
+ | |
+#define GUI_BUILDRESPONSE(name, type) \ | |
+ int index = -1;\ | |
+ for(int i = 0; i < m_NetGui##name.size(); i++)\ | |
+ {\ | |
+ if(m_NetGui##name[i].m_ID == pMsg->m_ID)\ | |
+ index = i;\ | |
+ }\ | |
+ if(index < 0)\ | |
+ break;\ | |
+ CNetMsg_Cl_NetGui_Response##type Reply;\ | |
+ Reply.m_ID = pMsg->m_ID;\ | |
+ Reply.m_Type = pMsg->m_Type | |
+ | |
+#define GUIRECEIVE_INIT(name) \ | |
+ CNetMsg_Sv_NetGui_##name *pMsg = (CNetMsg_Sv_NetGui_##name *)pRawMsg;\ | |
+ CNetMsg_Sv_NetGui_##name e;\ | |
+ e.m_ID = pMsg->m_ID;\ | |
+ e.m_Dimension[0] = pMsg->m_Dimension[0];\ | |
+ e.m_Dimension[1] = pMsg->m_Dimension[1];\ | |
+ e.m_Dimension[2] = pMsg->m_Dimension[2];\ | |
+ e.m_Dimension[3] = pMsg->m_Dimension[3] | |
+ | |
+#define GUIRECEIVE_FINALIZE(name) \ | |
+ if(m_NetGui##name.size() > 1)\ | |
+ {\ | |
+ for(int i = 0; i < m_NetGui##name.size(); i++)\ | |
+ {\ | |
+ if(m_NetGui##name[i].m_ID == e.m_ID)\ | |
+ m_NetGui##name.remove_index(i);\ | |
+ }\ | |
+ }\ | |
+ m_NetGui##name.add(e);\ | |
+ SortNetGuiList<CNetMsg_Sv_NetGui_##name>(m_NetGui##name) | |
+ | |
+ | |
+void CNetGui::OnReset() | |
+{ | |
+ // auto-generated clear's | |
+ #define GUIDEFINE(name, netmsgname, args...) m_NetGui##name.clear(); | |
+ #include <game/netguidefines.h> | |
+ #undef GUIDEFINE | |
+} | |
+ | |
+void CNetGui::OnMessage(int MsgId, void *pRawMsg) | |
+{ | |
+ if(MsgId == NETMSGTYPE_SV_NETGUI_REMOVEELEMENT) | |
+ { | |
+ CNetMsg_Sv_NetGui_RemoveElement *pMsg = (CNetMsg_Sv_NetGui_RemoveElement *)pRawMsg; | |
+ | |
+ // remove handler; the "args..." thingy is just for compatiblity and will be dropped | |
+ #define GUIDEFINE(name, netmsgname, args...) \ | |
+ case NETMSGTYPE_SV_NETGUI_##netmsgname: \ | |
+ for(int i = 0; i < m_NetGui##name.size(); i++) \ | |
+ { \ | |
+ if(m_NetGui##name[i].m_ID == pMsg->m_ID) \ | |
+ m_NetGui##name.remove_index(i); \ | |
+ } \ | |
+ break; | |
+ | |
+ switch(pMsg->m_Type) | |
+ { | |
+ // auto-generated remove handlers | |
+ #include <game/netguidefines.h> | |
+ #undef GUIDEFINE | |
+ } | |
+ } | |
+ else if(MsgId == NETMSGTYPE_SV_NETGUI_REQUESTDATA) | |
+ { | |
+ CNetMsg_Sv_NetGui_RequestData *pMsg = (CNetMsg_Sv_NetGui_RequestData *)pRawMsg; | |
+ switch(pMsg->m_Type) | |
+ { | |
+ case NETMSGTYPE_SV_NETGUI_EDITBOX: | |
+ { | |
+ GUI_BUILDRESPONSE(EditBox, String); | |
+ Reply.m_Text = m_aNetGuiEditBoxContent[index]; | |
+ Client()->SendPackMsg(&Reply, MSGFLAG_VITAL); | |
+ } | |
+ break; | |
+ case NETMSGTYPE_SV_NETGUI_CHECKBOX: | |
+ { | |
+ GUI_BUILDRESPONSE(CheckBox, Int); | |
+ Reply.m_Value = m_NetGuiCheckBox[index].m_Checked; | |
+ Client()->SendPackMsg(&Reply, MSGFLAG_VITAL); | |
+ } | |
+ break; | |
+ case NETMSGTYPE_SV_NETGUI_CHECKBOXNUMBER: | |
+ { | |
+ GUI_BUILDRESPONSE(CheckBoxNumber, Int); | |
+ Reply.m_Value = m_NetGuiCheckBoxNumber[index].m_Value; | |
+ Client()->SendPackMsg(&Reply, MSGFLAG_VITAL); | |
+ } | |
+ break; | |
+ case NETMSGTYPE_SV_NETGUI_SCROLLBAR: | |
+ { | |
+ GUI_BUILDRESPONSE(Scrollbar, Int); | |
+ Reply.m_Value = m_NetGuiScrollbar[index].m_ValueX100; | |
+ Client()->SendPackMsg(&Reply, MSGFLAG_VITAL); | |
+ } | |
+ break; | |
+ case NETMSGTYPE_SV_NETGUI_SCROLLBAROPTION: | |
+ { | |
+ GUI_BUILDRESPONSE(ScrollbarOption, Int); | |
+ Reply.m_Value = m_NetGuiScrollbarOption[index].m_Value; | |
+ Client()->SendPackMsg(&Reply, MSGFLAG_VITAL); | |
+ } | |
+ break; | |
+ | |
+ } | |
+ } | |
+ else if(MsgId == NETMSGTYPE_SV_NETGUI_UIRECT) | |
+ { | |
+ GUIRECEIVE_INIT(UIRect); | |
+ | |
+ e.m_Color[0] = pMsg->m_Color[0]; | |
+ e.m_Color[1] = pMsg->m_Color[1]; | |
+ e.m_Color[2] = pMsg->m_Color[2]; | |
+ e.m_Color[3] = pMsg->m_Color[3]; | |
+ e.m_Corner = pMsg->m_Corner; | |
+ e.m_RoundingX10 = pMsg->m_RoundingX10; | |
+ | |
+ GUIRECEIVE_FINALIZE(UIRect); | |
+ } | |
+ else if(MsgId == NETMSGTYPE_SV_NETGUI_LABEL) | |
+ { | |
+ GUIRECEIVE_INIT(Label); | |
+ | |
+ char* aBuf = (char*)mem_alloc(512, 0); | |
+ str_format(aBuf, 512, "%s", pMsg->m_Text); | |
+ e.m_Text = aBuf; | |
+ e.m_Color[0] = pMsg->m_Color[0]; | |
+ e.m_Color[1] = pMsg->m_Color[1]; | |
+ e.m_Color[2] = pMsg->m_Color[2]; | |
+ e.m_Color[3] = pMsg->m_Color[3]; | |
+ e.m_FontSize = pMsg->m_FontSize; | |
+ e.m_FontAlign = pMsg->m_FontAlign; | |
+ | |
+ GUIRECEIVE_FINALIZE(Label); | |
+ } | |
+ else if(MsgId == NETMSGTYPE_SV_NETGUI_BUTTONMENU) | |
+ { | |
+ GUIRECEIVE_INIT(ButtonMenu); | |
+ | |
+ char* aBuf = (char*)mem_alloc(512, 0); | |
+ str_format(aBuf, 512, "%s", pMsg->m_Text); | |
+ e.m_Text = aBuf; | |
+ e.m_Selected = pMsg->m_Selected; | |
+ | |
+ GUIRECEIVE_FINALIZE(ButtonMenu); | |
+ } | |
+ else if(MsgId == NETMSGTYPE_SV_NETGUI_EDITBOX) | |
+ { | |
+ GUIRECEIVE_INIT(EditBox); | |
+ | |
+ char* aBuf = (char*)mem_alloc(512, 0); | |
+ str_format(aBuf, 512, "%s", pMsg->m_Title); | |
+ e.m_Title = aBuf; | |
+ e.m_SplitValue = pMsg->m_SplitValue; | |
+ e.m_MaxTextWidth = pMsg->m_MaxTextWidth; | |
+ e.m_Password = pMsg->m_Password; | |
+ | |
+ GUIRECEIVE_FINALIZE(EditBox); | |
+ } | |
+ else if(MsgId == NETMSGTYPE_SV_NETGUI_CHECKBOX) | |
+ { | |
+ GUIRECEIVE_INIT(CheckBox); | |
+ | |
+ char* aBuf = (char*)mem_alloc(512, 0); | |
+ str_format(aBuf, 512, "%s", pMsg->m_Text); | |
+ e.m_Text = aBuf; | |
+ e.m_Checked = pMsg->m_Checked; | |
+ | |
+ GUIRECEIVE_FINALIZE(CheckBox); | |
+ } | |
+ else if(MsgId == NETMSGTYPE_SV_NETGUI_CHECKBOXNUMBER) | |
+ { | |
+ GUIRECEIVE_INIT(CheckBoxNumber); | |
+ | |
+ char* aBuf = (char*)mem_alloc(512, 0); | |
+ str_format(aBuf, 512, "%s", pMsg->m_Text); | |
+ e.m_Text = aBuf; | |
+ e.m_Value = pMsg->m_Value; | |
+ e.m_MinValue = pMsg->m_MinValue; | |
+ e.m_MaxValue = pMsg->m_MaxValue; | |
+ e.m_StepValue = pMsg->m_StepValue; | |
+ | |
+ GUIRECEIVE_FINALIZE(CheckBoxNumber); | |
+ } | |
+ else if(MsgId == NETMSGTYPE_SV_NETGUI_SCROLLBAR) | |
+ { | |
+ GUIRECEIVE_INIT(Scrollbar); | |
+ GUIRECEIVE_FINALIZE(Scrollbar); | |
+ } | |
+ else if(MsgId == NETMSGTYPE_SV_NETGUI_SCROLLBAROPTION) | |
+ { | |
+ GUIRECEIVE_INIT(ScrollbarOption); | |
+ | |
+ char* aBuf = (char*)mem_alloc(512, 0); | |
+ str_format(aBuf, 512, "%s", pMsg->m_Text); | |
+ e.m_Text = aBuf; | |
+ e.m_Value = pMsg->m_Value; | |
+ e.m_MinValue = pMsg->m_MinValue; | |
+ e.m_MaxValue = pMsg->m_MaxValue; | |
+ e.m_VSplitValX10 = pMsg->m_VSplitValX10; | |
+ | |
+ GUIRECEIVE_FINALIZE(ScrollbarOption); | |
+ } | |
+ else if(MsgId == NETMSGTYPE_SV_NETGUI_INFOBOX) | |
+ { | |
+ GUIRECEIVE_INIT(InfoBox); | |
+ | |
+ char* aBufLabel = (char*)mem_alloc(512, 0); | |
+ str_format(aBufLabel, 512, "%s", pMsg->m_Label); | |
+ e.m_Label = aBufLabel; | |
+ char* aBufValue = (char*)mem_alloc(512, 0); | |
+ str_format(aBufValue, 512, "%s", pMsg->m_Value); | |
+ e.m_Value = aBufValue; | |
+ | |
+ GUIRECEIVE_FINALIZE(InfoBox); | |
+ } | |
+} | |
diff --git a/src/game/client/components/netgui.h b/src/game/client/components/netgui.h | |
new file mode 100644 | |
index 0000000..ff2f7c0 | |
--- /dev/null | |
+++ b/src/game/client/components/netgui.h | |
@@ -0,0 +1,59 @@ | |
+// Copyright (c) 2015 Henritees | |
+ | |
+#ifndef GAME_CLIENT_COMPONENTS_NETGUI_H | |
+#define GAME_CLIENT_COMPONENTS_NETGUI_H | |
+ | |
+#include <base/tl/array.h> | |
+#include <game/client/component.h> | |
+ | |
+class CNetGui : public CComponent | |
+{ | |
+ virtual void OnReset(); | |
+ virtual void OnMessage(int MsgId, void *pRawMsg); | |
+ | |
+public: | |
+ // automatically make a storage array for everything | |
+ #define GUIDEFINE(name, netmsgname, args...) array<CNetMsg_Sv_NetGui_##name> m_NetGui##name; | |
+ #include <game/netguidefines.h> | |
+ #undef GUIDEFINE | |
+ | |
+ char m_aNetGuiEditBoxContent[1024][1024]; // necessary because it cannot be stored into the NetMsg (CONST char...) | |
+ | |
+ | |
+ // maxsort to get stuff into correct render order. | |
+ template<class T> | |
+ void SortNetGuiList(array<T> &elem) | |
+ { | |
+ int num = elem.size(); | |
+ if(num < 2) | |
+ return; | |
+ int max = 0; | |
+ T temp; | |
+ for(int i = 0; i < max; i++) | |
+ { | |
+ max = i; | |
+ for(int j = i; j < num; j++) | |
+ { | |
+ if(elem[i].m_ID > elem[max].m_ID) | |
+ max = i; | |
+ } | |
+ | |
+ if(max == i) | |
+ continue; | |
+ temp = elem[i]; | |
+ elem[i] = elem[max]; | |
+ elem[max] = temp; | |
+ } | |
+ } | |
+ | |
+ void SendEvent(int Type, int NetGuiElementID) | |
+ { | |
+ CNetMsg_Cl_NetGui_TriggerEvent Msg; | |
+ Msg.m_Type = Type; | |
+ Msg.m_ID = NetGuiElementID; | |
+ Client()->SendPackMsg(&Msg, MSGFLAG_VITAL); | |
+ } | |
+ | |
+}; | |
+ | |
+#endif | |
diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp | |
index cd58061..c34a8a4 100644 | |
--- a/src/game/client/gameclient.cpp | |
+++ b/src/game/client/gameclient.cpp | |
@@ -41,6 +41,7 @@ | |
#include "components/maplayers.h" | |
#include "components/menus.h" | |
#include "components/motd.h" | |
+#include "components/netgui.h" | |
#include "components/particles.h" | |
#include "components/players.h" | |
#include "components/nameplates.h" | |
@@ -60,6 +61,7 @@ static CGameConsole gs_GameConsole; | |
static CBinds gs_Binds; | |
static CParticles gs_Particles; | |
static CMenus gs_Menus; | |
+static CNetGui gs_NetGui; | |
static CSkins gs_Skins; | |
static CCountryFlags gs_CountryFlags; | |
static CFlow gs_Flow; | |
@@ -159,6 +161,7 @@ void CGameClient::OnConsoleInit() | |
m_pGameConsole = &::gs_GameConsole; | |
m_pParticles = &::gs_Particles; | |
m_pMenus = &::gs_Menus; | |
+ m_pNetGui = &::gs_NetGui; | |
m_pSkins = &::gs_Skins; | |
m_pCountryFlags = &::gs_CountryFlags; | |
m_pChat = &::gs_Chat; | |
@@ -206,6 +209,7 @@ void CGameClient::OnConsoleInit() | |
m_All.Add(&gs_DebugHud); | |
m_All.Add(&gs_Scoreboard); | |
m_All.Add(m_pMotd); | |
+ m_All.Add(m_pNetGui); | |
m_All.Add(m_pMenus); | |
m_All.Add(m_pGameConsole); | |
diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h | |
index 3735bf2..2d861fb 100644 | |
--- a/src/game/client/gameclient.h | |
+++ b/src/game/client/gameclient.h | |
@@ -266,6 +266,7 @@ public: | |
class CBroadcast *m_pBroadcast; | |
class CParticles *m_pParticles; | |
class CMenus *m_pMenus; | |
+ class CNetGui *m_pNetGui; | |
class CSkins *m_pSkins; | |
class CCountryFlags *m_pCountryFlags; | |
class CFlow *m_pFlow; | |
diff --git a/src/game/netguidefines.h b/src/game/netguidefines.h | |
new file mode 100644 | |
index 0000000..5a63d30 | |
--- /dev/null | |
+++ b/src/game/netguidefines.h | |
@@ -0,0 +1,18 @@ | |
+// Copyright (c) 2015 Henritees | |
+#ifndef GAME_NETGUIDEFINES_H | |
+#define GAME_NETGUIDEFINES_H | |
+#undef GAME_NETGUIDEFINES_H // this file will be included several times | |
+ | |
+#ifdef GUIDEFINE | |
+GUIDEFINE(UIRect, UIRECT, vec4 Color, int Corner, float Rounding); | |
+GUIDEFINE(Label, LABEL, const char *pText, vec4 Color, int FontSize, int FontAlign, int MaxTextWidth); | |
+GUIDEFINE(ButtonMenu, BUTTONMENU, const char *pText, bool Selected); | |
+GUIDEFINE(EditBox, EDITBOX, const char *pTitle, int SplitValue, int MaxTextWidth, bool Password); | |
+GUIDEFINE(CheckBox, CHECKBOX, const char *pText, bool Checked); | |
+GUIDEFINE(CheckBoxNumber, CHECKBOXNUMBER, const char *pText, int MinValue, int MaxValue, int StepValue); | |
+GUIDEFINE(Scrollbar, SCROLLBAR, bool Vertical = false); | |
+GUIDEFINE(ScrollbarOption, SCROLLBAROPTION, const char *pText, float VSplitVal, int Min, int Max, bool Infinite); | |
+GUIDEFINE(InfoBox, INFOBOX, const char *pLabel, const char* pValue); | |
+#endif | |
+ | |
+#endif | |
diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp | |
index d3ef828..cb3fbdd 100644 | |
--- a/src/game/server/gamecontext.cpp | |
+++ b/src/game/server/gamecontext.cpp | |
@@ -31,6 +31,7 @@ void CGameContext::Construct(int Resetting) | |
{ | |
m_Resetting = 0; | |
m_pServer = 0; | |
+ m_pNetGui = 0; | |
for(int i = 0; i < MAX_CLIENTS; i++) | |
m_apPlayers[i] = 0; | |
@@ -44,7 +45,10 @@ void CGameContext::Construct(int Resetting) | |
m_LockTeams = 0; | |
if(Resetting==NO_RESET) | |
+ { | |
m_pVoteOptionHeap = new CHeap(); | |
+ m_pNetGui = new CNetGui(this); | |
+ } | |
} | |
CGameContext::CGameContext(int Resetting) | |
@@ -62,7 +66,10 @@ CGameContext::~CGameContext() | |
for(int i = 0; i < MAX_CLIENTS; i++) | |
delete m_apPlayers[i]; | |
if(!m_Resetting) | |
+ { | |
delete m_pVoteOptionHeap; | |
+ delete m_pNetGui; | |
+ } | |
} | |
void CGameContext::Clear() | |
@@ -72,6 +79,7 @@ void CGameContext::Clear() | |
CVoteOptionServer *pVoteOptionLast = m_pVoteOptionLast; | |
int NumVoteOptions = m_NumVoteOptions; | |
CTuningParams Tuning = m_Tuning; | |
+ CNetGui *pNetGui = m_pNetGui; | |
m_Resetting = true; | |
this->~CGameContext(); | |
@@ -83,6 +91,7 @@ void CGameContext::Clear() | |
m_pVoteOptionLast = pVoteOptionLast; | |
m_NumVoteOptions = NumVoteOptions; | |
m_Tuning = Tuning; | |
+ m_pNetGui = pNetGui; | |
} | |
@@ -688,6 +697,8 @@ void CGameContext::OnClientDrop(int ClientID, const char *pReason) | |
m_apPlayers[ClientID] = 0; | |
m_VoteUpdate = true; | |
+ | |
+ m_pNetGui->OnClientDrop(ClientID); | |
} | |
void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) | |
@@ -708,6 +719,8 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) | |
if(Server()->ClientIngame(ClientID)) | |
{ | |
+ m_pNetGui->OnMessage(MsgID, pRawMsg, ClientID); | |
+ | |
if(MsgID == NETMSGTYPE_CL_SAY) | |
{ | |
if(g_Config.m_SvSpamprotection && pPlayer->m_LastChat && pPlayer->m_LastChat+Server()->TickSpeed() > Server()->Tick()) | |
diff --git a/src/game/server/gamecontext.h b/src/game/server/gamecontext.h | |
index c6e4935..b088455 100644 | |
--- a/src/game/server/gamecontext.h | |
+++ b/src/game/server/gamecontext.h | |
@@ -11,6 +11,7 @@ | |
#include "eventhandler.h" | |
#include "gameworld.h" | |
+#include "netgui.h" | |
/* | |
Tick | |
@@ -41,6 +42,7 @@ class CGameContext : public IGameServer | |
CCollision m_Collision; | |
CNetObjHandler m_NetObjHandler; | |
CTuningParams m_Tuning; | |
+ CNetGui *m_pNetGui; | |
static void ConTuneParam(IConsole::IResult *pResult, void *pUserData); | |
static void ConTuneReset(IConsole::IResult *pResult, void *pUserData); | |
diff --git a/src/game/server/netgui.cpp b/src/game/server/netgui.cpp | |
new file mode 100644 | |
index 0000000..c1b5ede | |
--- /dev/null | |
+++ b/src/game/server/netgui.cpp | |
@@ -0,0 +1,314 @@ | |
+// Copyright (c) 2015 Henritees | |
+ | |
+#include <game/server/gamecontext.h> | |
+#include <game/server/gamecontroller.h> | |
+#include <engine/server.h> | |
+ | |
+#include "netgui.h" | |
+ | |
+#define PREBUILD(msgtype) \ | |
+ CNetMsg_Sv_NetGui_##msgtype Msg; \ | |
+ Msg.m_ID = NetGuiElemID; \ | |
+ Msg.m_Dimension[0] = Dimensions.x; \ | |
+ Msg.m_Dimension[1] = Dimensions.y; \ | |
+ Msg.m_Dimension[2] = Dimensions.a; \ | |
+ Msg.m_Dimension[3] = Dimensions.b | |
+ | |
+ | |
+// ----------------------------- [start of GUI managing methods] ----------------------------- | |
+void CNetGui::CreateGui_EmptyGui(int ClientID) | |
+{ | |
+ | |
+} | |
+void CNetGui::RemoveGui_EmptyGui(int ClientID) | |
+{ | |
+ | |
+} | |
+ | |
+// ------------------------------ [end of GUI managing methods] ----------------------------- | |
+ | |
+void CNetGui::OnClientEnter(int ClientID) | |
+{ | |
+} | |
+ | |
+void CNetGui::OnClientCompatible(int ClientID) | |
+{ | |
+ | |
+} | |
+ | |
+void CNetGui::OnClientDrop(int ClientID) | |
+{ | |
+ m_NetGuiClients[ClientID] = false; | |
+ // auto-generated clear's | |
+ #define GUIDEFINE(name, netmsgname, args...) m_##name[ClientID].clear(); | |
+ #include <game/netguidefines.h> | |
+ #undef GUIDEFINE | |
+} | |
+ | |
+void CNetGui::OnMessage(int MsgID, void *pRawMsg, int ClientID) | |
+{ | |
+ CPlayer *pPlayer = GameServer()->m_apPlayers[ClientID]; | |
+ | |
+ if (MsgID == NETMSGTYPE_CL_NETGUI_TRIGGEREVENT) | |
+ { | |
+ CNetMsg_Cl_NetGui_TriggerEvent *pMsg = (CNetMsg_Cl_NetGui_TriggerEvent *)pRawMsg; | |
+ | |
+ switch(pMsg->m_Type) | |
+ { | |
+ case NETGUIMAGICNUMBER1: // verify compatibility | |
+ { | |
+ if(pMsg->m_ID == NETGUIMAGICNUMBER2) | |
+ { | |
+ dbg_msg("netgui", "client ID:%d has proven netgui compatibility (%d)", ClientID, pMsg->m_ID); | |
+ m_NetGuiClients[ClientID] = true; | |
+ | |
+ // this seems to be the earliest moment possible for sending the first GUI... | |
+ OnClientCompatible(ClientID); | |
+ } | |
+ else | |
+ { | |
+ GameServer()->SendChatTarget(ClientID, "[NetGUI] Your client has only partially proven NetGUI ability, you won't receive GUIs."); | |
+ GameServer()->SendChatTarget(ClientID, "[NetGUI] You may ask the server owner for further instructions. Maybe it's time for an update?"); | |
+ dbg_msg("netgui", "client ID:%d has only partially proven netgui ability, what went wrong? (%d != %d)", ClientID, pMsg->m_ID, NETGUIMAGICNUMBER2); | |
+ } | |
+ } | |
+ break; | |
+ case NETMSGTYPE_SV_NETGUI_BUTTONMENU: | |
+ bool exists = false; | |
+ for(int i = 0; i < m_ButtonMenu[ClientID].size(); i++) | |
+ { | |
+ if(m_ButtonMenu[ClientID][i].m_ID == pMsg->m_ID) | |
+ exists = true; | |
+ } | |
+ if(exists) | |
+ { | |
+ switch(pMsg->m_ID) | |
+ { | |
+ // TODO: handle button presses | |
+ } | |
+ } | |
+ break; | |
+ } | |
+ } | |
+ else if(MsgID == NETMSGTYPE_CL_NETGUI_RESPONSESTRING) | |
+ { | |
+ CNetMsg_Cl_NetGui_ResponseString *pMsg = (CNetMsg_Cl_NetGui_ResponseString *)pRawMsg; | |
+ | |
+ switch(pMsg->m_Type) | |
+ { | |
+ // TODO: handle string responses | |
+ } | |
+ } | |
+ else if(MsgID == NETMSGTYPE_CL_NETGUI_RESPONSEINT) | |
+ { | |
+ CNetMsg_Cl_NetGui_ResponseInt *pMsg = (CNetMsg_Cl_NetGui_ResponseInt *)pRawMsg; | |
+ | |
+ switch(pMsg->m_Type) | |
+ { | |
+ // TODO: handle integer responses | |
+ } | |
+ } | |
+} | |
+ | |
+void CNetGui::RemoveElement(int ClientID, int Type, int NetGuiElemID) | |
+{ | |
+ if(!m_NetGuiClients[ClientID]) | |
+ return; | |
+ | |
+ CNetMsg_Sv_NetGui_RemoveElement Msg; | |
+ Msg.m_Type = Type; | |
+ Msg.m_ID = NetGuiElemID; | |
+ | |
+ // remove handler; the "args..." thingy is just for compatiblity and will be dropped | |
+ #define GUIDEFINE(name, netmsgname, args...) \ | |
+ case NETMSGTYPE_SV_NETGUI_##netmsgname: \ | |
+ for(int i = 0; i < m_##name[ClientID].size(); i++) \ | |
+ { \ | |
+ if(m_##name[ClientID][i].m_ID == NetGuiElemID) \ | |
+ m_##name[ClientID].remove_index(i); \ | |
+ } \ | |
+ break; | |
+ | |
+ | |
+ switch(Type) | |
+ { | |
+ // auto-generated remove handlers | |
+ #include <game/netguidefines.h> | |
+ #undef GUIDEFINE | |
+ } | |
+ | |
+ SendNetGui(ClientID, Msg); | |
+} | |
+ | |
+ | |
+void CNetGui::DoUIRect(int ClientID, int NetGuiElemID, vec4 Dimensions, vec4 Color, int Corner, float Rounding) | |
+{ | |
+ if(!m_NetGuiClients[ClientID]) | |
+ return; | |
+ | |
+ PREBUILD(UIRect); | |
+ Msg.m_Color[0] = Color.r; | |
+ Msg.m_Color[1] = Color.g; | |
+ Msg.m_Color[2] = Color.b; | |
+ Msg.m_Color[3] = Color.a; | |
+ Msg.m_Corner = Corner; | |
+ Msg.m_RoundingX10 = (int)(Rounding*10.0f); | |
+ | |
+ m_UIRect[ClientID].add(Msg); | |
+ | |
+ SendNetGui(ClientID, Msg); | |
+} | |
+ | |
+void CNetGui::DoLabel(int ClientID, int NetGuiElemID, vec4 Dimensions, const char *pText, vec4 Color, int FontSize, int FontAlign, int MaxTextWidth) | |
+{ | |
+ if(!m_NetGuiClients[ClientID]) | |
+ return; | |
+ | |
+ PREBUILD(Label); | |
+ Msg.m_Text = pText; | |
+ Msg.m_Color[0] = Color.r; | |
+ Msg.m_Color[1] = Color.g; | |
+ Msg.m_Color[2] = Color.b; | |
+ Msg.m_Color[3] = Color.a; | |
+ Msg.m_FontSize = FontSize; | |
+ Msg.m_FontAlign = FontAlign; | |
+ Msg.m_MaxTextWidth = MaxTextWidth; | |
+ | |
+ m_Label[ClientID].add(Msg); | |
+ | |
+ SendNetGui(ClientID, Msg); | |
+} | |
+ | |
+void CNetGui::DoButtonMenu(int ClientID, int NetGuiElemID, vec4 Dimensions, const char *pText, bool Selected) | |
+{ | |
+ if(!m_NetGuiClients[ClientID]) | |
+ return; | |
+ | |
+ PREBUILD(ButtonMenu); | |
+ Msg.m_Text = pText; | |
+ Msg.m_Selected = Selected ? 1 : 0; | |
+ | |
+ m_ButtonMenu[ClientID].add(Msg); | |
+ | |
+ SendNetGui(ClientID, Msg); | |
+} | |
+ | |
+void CNetGui::DoEditBox(int ClientID, int NetGuiElemID, vec4 Dimensions, const char *pTitle, int SplitValue, int MaxTextWidth, bool Password) | |
+{ | |
+ if(!m_NetGuiClients[ClientID]) | |
+ return; | |
+ | |
+ PREBUILD(EditBox); | |
+ Msg.m_Title = pTitle; | |
+ Msg.m_SplitValue = SplitValue; | |
+ Msg.m_MaxTextWidth = MaxTextWidth; | |
+ Msg.m_Password = Password ? 1 : 0; | |
+ | |
+ m_EditBox[ClientID].add(Msg); | |
+ | |
+ SendNetGui(ClientID, Msg); | |
+} | |
+ | |
+void CNetGui::DoCheckBox(int ClientID, int NetGuiElemID, vec4 Dimensions, const char *pText, bool Checked) | |
+{ | |
+ if(!m_NetGuiClients[ClientID]) | |
+ return; | |
+ | |
+ PREBUILD(CheckBox); | |
+ Msg.m_Text = pText; | |
+ Msg.m_Checked = Checked ? 1 : 0; | |
+ | |
+ m_CheckBox[ClientID].add(Msg); | |
+ | |
+ SendNetGui(ClientID, Msg); | |
+} | |
+ | |
+void CNetGui::DoCheckBoxNumber(int ClientID, int NetGuiElemID, vec4 Dimensions, const char *pText, int MinValue, int MaxValue, int StepValue) | |
+{ | |
+ if(!m_NetGuiClients[ClientID]) | |
+ return; | |
+ | |
+ PREBUILD(CheckBoxNumber); | |
+ Msg.m_Text = pText; | |
+ Msg.m_Value = MinValue; | |
+ Msg.m_MinValue = MinValue; | |
+ Msg.m_MaxValue = MaxValue; | |
+ Msg.m_StepValue = StepValue; | |
+ | |
+ m_CheckBoxNumber[ClientID].add(Msg); | |
+ | |
+ SendNetGui(ClientID, Msg); | |
+} | |
+ | |
+void CNetGui::DoScrollbar(int ClientID, int NetGuiElemID, vec4 Dimensions, bool Vertical) | |
+{ | |
+ if(!m_NetGuiClients[ClientID]) | |
+ return; | |
+ | |
+ PREBUILD(Scrollbar); | |
+ Msg.m_Vertical = Vertical ? 1 : 0; | |
+ | |
+ m_Scrollbar[ClientID].add(Msg); | |
+ | |
+ SendNetGui(ClientID, Msg); | |
+} | |
+ | |
+void CNetGui::DoScrollbarOption(int ClientID, int NetGuiElemID, vec4 Dimensions, const char *pText, float VSplitVal, int Min, int Max, bool Infinite) | |
+{ | |
+ if(!m_NetGuiClients[ClientID]) | |
+ return; | |
+ | |
+ PREBUILD(ScrollbarOption); | |
+ Msg.m_Text = pText; | |
+ Msg.m_VSplitValX10 = (int)(VSplitVal*10.0f); | |
+ Msg.m_MinValue = Min; | |
+ Msg.m_MaxValue = Max; | |
+ Msg.m_Infinite = Infinite ? 1 : 0; | |
+ | |
+ m_ScrollbarOption[ClientID].add(Msg); | |
+ | |
+ SendNetGui(ClientID, Msg); | |
+} | |
+ | |
+void CNetGui::DoInfoBox(int ClientID, int NetGuiElemID, vec4 Dimensions, const char *pLabel, const char* pValue) | |
+{ | |
+ if(!m_NetGuiClients[ClientID]) | |
+ return; | |
+ | |
+ PREBUILD(InfoBox); | |
+ Msg.m_Label = pLabel; | |
+ Msg.m_Value = pValue; | |
+ | |
+ m_InfoBox[ClientID].add(Msg); | |
+ | |
+ SendNetGui(ClientID, Msg); | |
+} | |
+ | |
+void CNetGui::RequestData(int ClientID, int Type, int NetGuiElemID) | |
+{ | |
+ if(!m_NetGuiClients[ClientID]) | |
+ return; | |
+ | |
+ CNetMsg_Sv_NetGui_RequestData Msg; | |
+ Msg.m_ID = NetGuiElemID; | |
+ Msg.m_Type = Type; | |
+ GameServer()->Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, ClientID); | |
+} | |
+ | |
+ | |
+template<class T> | |
+void CNetGui::SendNetGui(int ClientID, T Msg) | |
+{ | |
+ if(ClientID < 0) | |
+ { | |
+ for(int i = 0; i < MAX_CLIENTS; ++i) | |
+ { | |
+ if(!GameServer()->m_apPlayers[i]) | |
+ continue; | |
+ | |
+ GameServer()->Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, i); | |
+ } | |
+ } | |
+ else | |
+ GameServer()->Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, ClientID); | |
+} | |
diff --git a/src/game/server/netgui.h b/src/game/server/netgui.h | |
new file mode 100644 | |
index 0000000..ddb4232 | |
--- /dev/null | |
+++ b/src/game/server/netgui.h | |
@@ -0,0 +1,59 @@ | |
+// Copyright (c) 2015 Henritees | |
+ | |
+#ifndef GAME_SERVER_NETGUI_H | |
+#define GAME_SERVER_NETGUI_H | |
+ | |
+#include <base/tl/array.h> | |
+#include <game/server/gamecontroller.h> | |
+#include <game/server/gamecontext.h> | |
+#include <engine/shared/protocol.h> | |
+#include <engine/server.h> | |
+ | |
+#include "player.h" | |
+ | |
+#define NETGUIMAGICNUMBER1 1883 | |
+#define NETGUIMAGICNUMBER2 5397 | |
+ | |
+#define GUISET(name) void CreateGui_##name(int ClientID); void RemoveGui_##name(int ClientID); | |
+#define GUIDEFINE(name, netmsgname, args...) \ | |
+ public: \ | |
+ void Do##name(int ClientID, int NetGuiElemID, vec4 Dimensions, args); \ | |
+ private: \ | |
+ array<CNetMsg_Sv_NetGui_##name> m_##name[MAX_CLIENTS]; public: | |
+ | |
+class CNetGui | |
+{ | |
+ CGameContext *m_pGameServer; | |
+ | |
+ // methods for managing sets of GUIs | |
+ GUISET(EmptyGui) | |
+ | |
+public: | |
+ CNetGui(CGameContext *pGameServer) : m_pGameServer(pGameServer){} | |
+ void RemoveElement(int ClientID, int Type, int NetGuiElemID); | |
+ | |
+ void OnClientEnter(int ClientID); | |
+ void OnClientDrop(int ClientID); | |
+ void OnClientCompatible(int ClientID); | |
+ void OnMessage(int MsgID, void *pRawMsg, int ClientID); | |
+ | |
+ bool IsNetGuiClient(int ClientID) { return m_NetGuiClients[ClientID]; } | |
+ | |
+ // // auto-generated declarations of functions | |
+ #include <game/netguidefines.h> | |
+ #undef GUIDEFINE | |
+ | |
+protected: | |
+ CGameContext *GameServer() const { return m_pGameServer; } | |
+ | |
+private: | |
+ bool m_NetGuiClients[MAX_CLIENTS]; // could have been put into CPlayer as well, but I want to keep stuff together | |
+ | |
+ template<class T> | |
+ void SendNetGui(int ClientID, T Msg); | |
+ void RequestData(int ClientID, int Type, int NetGuiElemID); | |
+ | |
+ | |
+}; | |
+ | |
+#endif | |
diff --git a/src/game/version.h b/src/game/version.h | |
index e5640ee..14f3451 100644 | |
--- a/src/game/version.h | |
+++ b/src/game/version.h | |
@@ -5,5 +5,6 @@ | |
#include <generated/nethash.cpp> | |
#define GAME_VERSION "0.7 trunk" | |
#define GAME_NETVERSION "0.7 " GAME_NETVERSION_HASH | |
+#define GAME_NETGUI_VERSION "0.7-0.1.b20151228" | |
static const char GAME_RELEASE_VERSION[8] = {'0', '.', '6', '1', 0}; | |
#endif | |
-- | |
2.5.0 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment