COLOR_DIALOG_MAPINFO '1 1 1'
COLOR_DIALOG_USERBIND '1 1 1'
COLOR_DIALOG_SINGLEPLAYER '1 1 1'
+COLOR_DIALOG_SOCIAL '1 1 1'
COLOR_DIALOG_CREDITS '1 1 1'
COLOR_DIALOG_WEAPONS '1 1 1'
COLOR_DIALOG_VIEW '1 1 1'
POSITION_DIALOG_SINGLEPLAYER '0.15 0.4 0'
POSITION_DIALOG_SETTINGS '0.5 1 0'
POSITION_DIALOG_CREDITS '-0.05 1.2 0'
+POSITION_DIALOG_SOCIAL '0.5 1.2 0'
POSITION_DIALOG_QUIT '1.05 1.2 0'
// font
POSITION_DIALOG_SINGLEPLAYER '0.15 0.4 0'
POSITION_DIALOG_SETTINGS '0.5 1 0'
POSITION_DIALOG_CREDITS '-0.05 1.2 0'
+POSITION_DIALOG_SOCIAL '0.5 1.2 0'
POSITION_DIALOG_QUIT '1.05 1.2 0'
// tooltips
COLOR_DIALOG_MAPINFO '1 1 1'
COLOR_DIALOG_USERBIND '1 1 1'
COLOR_DIALOG_SINGLEPLAYER '1 1 1'
+COLOR_DIALOG_SOCIAL '1 1 1'
COLOR_DIALOG_CREDITS '1 1 1'
COLOR_DIALOG_WEAPONS '1 1 1'
COLOR_DIALOG_VIEW '1 1 1'
POSITION_DIALOG_SINGLEPLAYER '0.2 0.4 0'
POSITION_DIALOG_SETTINGS '0.5 0.95 0'
POSITION_DIALOG_CREDITS '-0.05 1.2 0'
+POSITION_DIALOG_SOCIAL '0.5 1.2 0'
POSITION_DIALOG_QUIT '1.05 1.2 0'
// tooltips
COLOR_DIALOG_MAPINFO '1 1 1'
COLOR_DIALOG_USERBIND '1 1 1'
COLOR_DIALOG_SINGLEPLAYER '1 1 1'
+COLOR_DIALOG_SOCIAL '1 1 1'
COLOR_DIALOG_CREDITS '1 1 1'
COLOR_DIALOG_WEAPONS '1 1 1'
COLOR_DIALOG_VIEW '1 1 1'
COLOR_DIALOG_MAPINFO '1 1 1'
COLOR_DIALOG_USERBIND '1 1 1'
COLOR_DIALOG_SINGLEPLAYER '1 1 1'
+COLOR_DIALOG_SOCIAL '1 1 1'
COLOR_DIALOG_CREDITS '1 1 1'
COLOR_DIALOG_WEAPONS '1 1 1'
COLOR_DIALOG_VIEW '1 1 1'
POSITION_DIALOG_SINGLEPLAYER '0.1 0.1 0'
POSITION_DIALOG_SETTINGS '0.1 0.9 0'
POSITION_DIALOG_CREDITS '0.3 1.2 0'
+POSITION_DIALOG_SOCIAL '0.6 1.2 0'
POSITION_DIALOG_QUIT '0.9 1.2 0'
// mouse
#ifdef MENUQC
+#include "social.qh"
REGISTER_MUTATOR(social, true);
void Social_send(int to, string msg);
string Social_invite_accept;
-int Social_db = -1;
-
STATIC_INIT(Social) {
Social_db = db_load("social.db");
}
int id = stoi(argv(1));
string nick = substring(cmd_string, argv_start_index(2), argv_end_index(-1) - argv_start_index(2));
db_put(Social_db, itos(id), nick);
+ MUTATOR_CALLHOOK(Social_Add, id, nick);
return true;
}
if (cmd_name == "sremove" && cmd_argc == 2) {
return true;
}
if (cmd_name == "slist") {
- FOREACH_DB(Social_db, LAMBDA(
+ FOREACH_DB(Social_db, true, LAMBDA(
printf("%s: %s\n", k, v);
));
return true;
--- /dev/null
+#ifdef MENUQC
+#ifndef SOCIAL_H
+#define SOCIAL_H
+#include "../base.qh"
+/** Called when a friend is added */
+#define EV_Social_Add(i, o) \
+ /**/ i(int, mutator_argv_int_0) \
+ /**/ i(string, mutator_argv_string_0) \
+ /**/
+MUTATOR_HOOKABLE(Social_Add, EV_Social_Add);
+
+int Social_db = -1;
+#endif
+#endif
if (fh < 0)
error(strcat("Can't dump DB to ", pFilename));
fputs(fh, "0\n");
- FOREACH_DB(db, LAMBDA(
+ FOREACH_DB(db, true, LAMBDA(
fputs(fh, strcat("\\", k, "\\", v, "\n"));
));
fclose(fh);
string db_get(int db, string key);
void db_put(int db, string key, string value);
void db_delete(float db, string pKey);
-#define FOREACH_INFO(s, f) do { \
+#define FOREACH_INFO(s, cond, f) do { \
string __s = s; \
int __m = tokenizebyseparator(__s, "\\"); \
for (int __j = 2; __j < __m; __j += 2) { \
- string k = argv(__j - 1), v = argv(__j); \
- f; \
+ noref string k = argv(__j - 1), v = uri_unescape(argv(__j)); \
+ if (cond) f; \
} \
} while (0)
-#define FOREACH_BUF(db, f) do { \
+#define FOREACH_BUF(db, cond, f) do { \
int __db = db; \
int __n = buf_getsize(__db); \
for (int __i = 0; __i < __n; ++__i) { \
- f; \
+ if (cond) f; \
} \
} while (0)
-#define FOREACH_DB(db, f) do { \
- FOREACH_BUF(db, FOREACH_INFO(bufstr_get(__db, __i), f)); \
+#define FOREACH_DB(db, cond, f) do { \
+ FOREACH_BUF(db, true, FOREACH_INFO(bufstr_get(__db, __i), cond, f)); \
} while (0)
// stringbuffer loading/saving
#include "xonotic/dialog_settings_video.qc"
#include "xonotic/dialog_singleplayer.qc"
#include "xonotic/dialog_singleplayer_winner.qc"
+#include "xonotic/dialog_social.qc"
#include "xonotic/dialog_teamselect.qc"
#include "xonotic/gametypelist.qc"
#include "xonotic/image.qc"
SKINVECTOR(COLOR_DIALOG_MAPINFO, '0.7 0.7 1');
SKINVECTOR(COLOR_DIALOG_USERBIND, '0.7 0.7 1');
SKINVECTOR(COLOR_DIALOG_SINGLEPLAYER, '1 1 0.7');
+ SKINVECTOR(COLOR_DIALOG_SOCIAL, '1 1 1');
SKINVECTOR(COLOR_DIALOG_CREDITS, '0.7 0.7 1');
SKINVECTOR(COLOR_DIALOG_WEAPONS, '1 0.7 0.7');
SKINVECTOR(COLOR_DIALOG_VIEW, '1 0.7 0.7');
SKINVECTOR(POSITION_DIALOG_SINGLEPLAYER, '0.1 0.1 0');
SKINVECTOR(POSITION_DIALOG_SETTINGS, '0.1 0.9 0');
SKINVECTOR(POSITION_DIALOG_CREDITS, '0.3 1.2 0');
+ SKINVECTOR(POSITION_DIALOG_SOCIAL, '0.5 1.2 0');
SKINVECTOR(POSITION_DIALOG_QUIT, '0.9 1.2 0');
// mouse
--- /dev/null
+#ifndef DIALOG_SOCIAL_H
+#define DIALOG_SOCIAL_H
+
+#include "../../common/mutators/mutator/social.qh"
+#include "datasource.qc"
+CLASS(FriendSource, DataSource)
+ METHOD(FriendSource, getEntry, entity(int i, void(string name, string icon) returns))
+ {
+ int idx = 0;
+ string name = string_null;
+ FOREACH_DB(Social_db, idx++ == i, LAMBDA(
+ name = v;
+ break;
+ ));
+ if (returns) returns(name, string_null);
+ return DataSource_true;
+ }
+ METHOD(FriendSource, reload, int(string filter)) {
+ int n = 0;
+ FOREACH_DB(Social_db, true, LAMBDA(++n));
+ return n;
+ }
+ENDCLASS(FriendSource)
+
+entity Social_inst;
+
+#include "listbox.qc"
+CLASS(XonoticFriendsList, XonoticListBox)
+ ATTRIB(XonoticFriendsList, alphaBG, float, 0)
+ ATTRIB(XonoticFriendsList, itemAbsSize, vector, '0 0 0')
+ ATTRIB(XonoticFriendsList, origin, vector, '0 0 0')
+ ATTRIB(XonoticFriendsList, realFontSize, vector, '0 0 0')
+ ATTRIB(XonoticFriendsList, realUpperMargin, float, 0)
+ ATTRIB(XonoticFriendsList, rowsPerItem, float, 2)
+ ATTRIB(XonoticFriendsList, stringFilterBox, entity, NULL)
+ ATTRIB(XonoticFriendsList, stringFilter, string, string_null)
+ ATTRIB(XonoticFriendsList, typeToSearchString, string, string_null)
+ ATTRIB(XonoticFriendsList, typeToSearchTime, float, 0)
+ ATTRIB(XonoticFriendsList, source, DataSource, NULL)
+ ATTRIB(XonoticFriendsList, onChange, void(entity, entity), func_null)
+ ATTRIB(XonoticFriendsList, onChangeEntity, entity, NULL)
+ string XonoticFriendsList_cb_name;
+ void XonoticFriendsList_cb(string _name, string _icon)
+ {
+ XonoticFriendsList_cb_name = _name;
+ }
+ METHOD(XonoticFriendsList, drawListBoxItem, void(entity this, int i, vector absSize, bool isSelected, bool isFocused))
+ {
+ if (!this.source) return;
+ if (!this.source.getEntry(i, XonoticFriendsList_cb)) return;
+ string name = XonoticFriendsList_cb_name;
+ if (isSelected) {
+ draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
+ } else if (isFocused) {
+ this.focusedItemAlpha = getFadedAlpha(this.focusedItemAlpha, SKINALPHA_LISTBOX_FOCUSED, SKINFADEALPHA_LISTBOX_FOCUSED);
+ draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_FOCUSED, this.focusedItemAlpha);
+ }
+ string s = draw_TextShortenToWidth(strdecolorize(name), 1, 0, this.realFontSize);
+ draw_Text(this.realUpperMargin * eY + (0.5 * this.realFontSize.x) * eX, s, this.realFontSize, '1 1 1', SKINALPHA_TEXT, 0);
+ }
+ METHOD(XonoticFriendsList, refilter, void(entity this))
+ {
+ if (!this.source) {
+ this.nItems = 0;
+ return;
+ }
+ this.nItems = this.source.reload(this.stringFilter);
+ }
+ METHOD(XonoticFriendsList, resizeNotify, void(entity this, vector relOrigin, vector relSize, vector absOrigin, vector absSize))
+ {
+ super.resizeNotify(this, relOrigin, relSize, absOrigin, absSize);
+
+ this.itemAbsSize = '0 0 0';
+ this.realFontSize_y = this.fontSize / (this.itemAbsSize_y = (absSize.y * this.itemHeight));
+ this.realFontSize_x = this.fontSize / (this.itemAbsSize_x = (absSize.x * (1 - this.controlWidth)));
+ this.realUpperMargin = 0.5 * (1 - this.realFontSize.y);
+ }
+ INIT(XonoticFriendsList) {
+ Social_inst = this;
+ }
+ CONSTRUCTOR(XonoticFriendsList, DataSource _source) {
+ CONSTRUCT(XonoticFriendsList);
+ this.source = _source;
+ this.configureXonoticListBox(this);
+ this.refilter(this);
+ }
+ENDCLASS(XonoticFriendsList)
+
+#include "dialog.qc"
+CLASS(XonoticSocialDialog, XonoticDialog)
+ METHOD(XonoticSocialDialog, fill, void(entity));
+ ATTRIB(XonoticSocialDialog, title, string, _("Social"))
+ ATTRIB(XonoticSocialDialog, color, vector, SKINCOLOR_DIALOG_SOCIAL)
+ ATTRIB(XonoticSocialDialog, intendedWidth, float, 0.5)
+ ATTRIB(XonoticSocialDialog, rows, float, 20)
+ ATTRIB(XonoticSocialDialog, columns, float, 2)
+ ATTRIB(XonoticSocialDialog, friendsList, XonoticFriendsList, NEW(XonoticFriendsList, NEW(FriendSource)))
+ENDCLASS(XonoticSocialDialog)
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+REGISTER_MUTATOR(social_refreshmenu, true);
+MUTATOR_HOOKFUNCTION(social_refreshmenu, Social_Add) {
+ Social_inst.refilter(Social_inst);
+}
+
+METHOD(XonoticSocialDialog, fill, void(entity this))
+{
+ int
+ col = 0, width = 2;
+ this.gotoRC(this, 0, col);
+ this.TD(this, this.rows, width, this.friendsList);
+}
+#endif
n.setNexposee(n, i, SKINPOSITION_DIALOG_CREDITS, SKINALPHAS_MAINMENU_x, SKINALPHAS_MAINMENU_y);
n.pullNexposee(n, i, eY * (SKINHEIGHT_TITLE * SKINFONTSIZE_TITLE / conheight));
+ i = NEW(XonoticSocialDialog);
+ i.configureDialog(i);
+ n.addItemCentered(n, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+ n.setNexposee(n, i, SKINPOSITION_DIALOG_SOCIAL, SKINALPHAS_MAINMENU_x, SKINALPHAS_MAINMENU_y);
+ n.pullNexposee(n, i, eY * (SKINHEIGHT_TITLE * SKINFONTSIZE_TITLE / conheight));
+
i = NEW(XonoticQuitDialog);
i.configureDialog(i);
n.addItemCentered(n, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);