mirror of
https://github.com/Tha14/toxic.git
synced 2024-12-22 18:43:25 +01:00
Add ability to compile without game support
This commit is contained in:
parent
7aeb1a0aac
commit
7abf6388f8
@ -58,6 +58,7 @@ Run `make doc` in the build directory after editing the asciidoc files to regene
|
||||
* `DISABLE_QRCODE` → Disable QR exporting support
|
||||
* `DISABLE_QRPNG` → Disable support for exporting QR as PNG
|
||||
* `DISABLE_DESKTOP_NOTIFY=1` → Disable desktop notifications support
|
||||
* `DISABLE_GAMES=1` → Disable support for games
|
||||
* `ENABLE_PYTHON=1` → Build toxic with Python scripting support
|
||||
* `ENABLE_RELEASE=1` → Build toxic without debug symbols and with full compiler optimizations
|
||||
* `ENABLE_ASAN=1` → Build toxic with LLVM Address Sanitizer enabled
|
||||
|
6
Makefile
6
Makefile
@ -13,9 +13,9 @@ LDFLAGS ?=
|
||||
LDFLAGS += ${USER_LDFLAGS}
|
||||
|
||||
OBJ = autocomplete.o avatars.o bootstrap.o chat.o chat_commands.o configdir.o curl_util.o execute.o
|
||||
OBJ += file_transfers.o friendlist.o game_base.o game_centipede.o game_chess.o game_util.o game_snake.o
|
||||
OBJ += global_commands.o conference_commands.o conference.o help.o input.o line_info.o log.o message_queue.o
|
||||
OBJ += misc_tools.o name_lookup.o notify.o prompt.o qr_code.o settings.o term_mplex.o toxic.o toxic_strings.o windows.o
|
||||
OBJ += file_transfers.o friendlist.o global_commands.o conference_commands.o conference.o help.o input.o line_info.o
|
||||
OBJ += log.o message_queue.o misc_tools.o name_lookup.o notify.o prompt.o qr_code.o settings.o
|
||||
OBJ += term_mplex.o toxic.o toxic_strings.o windows.o
|
||||
|
||||
# Check if debug build is enabled
|
||||
RELEASE := $(shell if [ -z "$(ENABLE_RELEASE)" ] || [ "$(ENABLE_RELEASE)" = "0" ] ; then echo disabled ; else echo enabled ; fi)
|
||||
|
@ -19,6 +19,13 @@ ifneq ($(AUDIO), disabled)
|
||||
ifneq ($(VIDEO), disabled)
|
||||
-include $(CHECKS_DIR)/video.mk
|
||||
endif
|
||||
|
||||
#check if we want to build with game support
|
||||
GAMES := $(shell if [ -z "$(DISABLE_GAMES)" ] || [ "$(DISABLE_GAMES)" = "0" ] ; then echo enabled ; else echo disabled ; fi)
|
||||
ifneq ($(GAMES), disabled)
|
||||
-include $(CHECKS_DIR)/games.mk
|
||||
endif
|
||||
|
||||
endif
|
||||
endif
|
||||
|
||||
|
5
cfg/checks/games.mk
Normal file
5
cfg/checks/games.mk
Normal file
@ -0,0 +1,5 @@
|
||||
# Variables for game support
|
||||
GAMES_CFLAGS = -DGAMES
|
||||
GAMES_OBJ = game_base.o game_centipede.o game_chess.o game_util.o game_snake.o
|
||||
CFLAGS += $(GAMES_CFLAGS)
|
||||
OBJ += $(GAMES_OBJ)
|
@ -16,6 +16,7 @@ help:
|
||||
@echo " DISABLE_DESKTOP_NOTIFY: Set to \"1\" to force building without desktop notifications support"
|
||||
@echo " DISABLE_QRCODE: Set to \"1\" to force building without QR export support"
|
||||
@echo " DISABLE_QRPNG: Set to \"1\" to force building without QR exported as PNG support"
|
||||
@echo " DISABLE_GAMES: Set to \"1\" to force building without game support"
|
||||
@echo " ENABLE_PYTHON: Set to \"1\" to enable building with Python scripting support"
|
||||
@echo " ENABLE_RELEASE: Set to \"1\" to build without debug symbols and with full compiler optimizations"
|
||||
@echo " ENABLE_ASAN: Set to \"1\" to build with LLVM address sanitizer enabled.
|
||||
|
15
src/chat.c
15
src/chat.c
@ -35,7 +35,6 @@
|
||||
#include "execute.h"
|
||||
#include "file_transfers.h"
|
||||
#include "friendlist.h"
|
||||
#include "game_base.h"
|
||||
#include "help.h"
|
||||
#include "input.h"
|
||||
#include "line_info.h"
|
||||
@ -48,6 +47,10 @@
|
||||
#include "toxic_strings.h"
|
||||
#include "windows.h"
|
||||
|
||||
#ifdef GAMES
|
||||
#include "game_base.h"
|
||||
#endif
|
||||
|
||||
#ifdef AUDIO
|
||||
#include "audio_call.h"
|
||||
#ifdef VIDEO
|
||||
@ -77,7 +80,9 @@ static const char *chat_cmd_list[] = {
|
||||
"/connect",
|
||||
"/exit",
|
||||
"/conference",
|
||||
#ifdef GAMES
|
||||
"/game",
|
||||
#endif
|
||||
"/help",
|
||||
"/invite",
|
||||
"/join",
|
||||
@ -759,6 +764,7 @@ static void chat_onConferenceInvite(ToxWindow *self, Tox *m, int32_t friendnumbe
|
||||
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Type \"/join\" to join the chat.");
|
||||
}
|
||||
|
||||
#ifdef GAMES
|
||||
void chat_onGameInvite(ToxWindow *self, Tox *m, uint32_t friend_number, const uint8_t *data, size_t length)
|
||||
{
|
||||
if (!self || self->num != friend_number) {
|
||||
@ -828,6 +834,8 @@ void chat_onGameInvite(ToxWindow *self, Tox *m, uint32_t friend_number, const ui
|
||||
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Type \"/play\" to join the game.");
|
||||
}
|
||||
|
||||
#endif // GAMES
|
||||
|
||||
/* AV Stuff */
|
||||
#ifdef AUDIO
|
||||
|
||||
@ -1546,7 +1554,6 @@ ToxWindow *new_chat(Tox *m, uint32_t friendnum)
|
||||
ret->onFileControl = &chat_onFileControl;
|
||||
ret->onFileRecv = &chat_onFileRecv;
|
||||
ret->onReadReceipt = &chat_onReadReceipt;
|
||||
ret->onGameInvite = &chat_onGameInvite;
|
||||
|
||||
#ifdef AUDIO
|
||||
ret->onInvite = &chat_onInvite;
|
||||
@ -1563,6 +1570,10 @@ ToxWindow *new_chat(Tox *m, uint32_t friendnum)
|
||||
ret->ringing_sound = -1;
|
||||
#endif /* AUDIO */
|
||||
|
||||
#ifdef GAMES
|
||||
ret->onGameInvite = &chat_onGameInvite;
|
||||
#endif /* GAMES */
|
||||
|
||||
ret->active_box = -1;
|
||||
|
||||
char nick[TOX_MAX_NAME_LENGTH];
|
||||
|
@ -172,6 +172,8 @@ void cmd_conference_join(WINDOW *window, ToxWindow *self, Tox *m, int argc, char
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef GAMES
|
||||
|
||||
void cmd_game_join(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
@ -225,6 +227,8 @@ void cmd_game_join(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GAMES
|
||||
|
||||
void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
|
@ -88,7 +88,9 @@ static const char *conference_cmd_list[] = {
|
||||
"/decline",
|
||||
"/exit",
|
||||
"/conference",
|
||||
#ifdef GAME
|
||||
"/game",
|
||||
#endif
|
||||
"/help",
|
||||
"/log",
|
||||
#ifdef AUDIO
|
||||
|
@ -49,7 +49,9 @@ static struct cmd_func global_commands[] = {
|
||||
{ "/decline", cmd_decline },
|
||||
{ "/exit", cmd_quit },
|
||||
{ "/conference", cmd_conference },
|
||||
#ifdef GAMES
|
||||
{ "/game", cmd_game },
|
||||
#endif
|
||||
{ "/help", cmd_prompt_help },
|
||||
{ "/log", cmd_log },
|
||||
{ "/myid", cmd_myid },
|
||||
@ -81,7 +83,9 @@ static struct cmd_func chat_commands[] = {
|
||||
{ "/cancel", cmd_cancelfile },
|
||||
{ "/invite", cmd_conference_invite },
|
||||
{ "/join", cmd_conference_join },
|
||||
#ifdef GAMES
|
||||
{ "/play", cmd_game_join },
|
||||
#endif
|
||||
{ "/savefile", cmd_savefile },
|
||||
{ "/sendfile", cmd_sendfile },
|
||||
#ifdef AUDIO
|
||||
|
@ -118,7 +118,9 @@ void kill_friendlist(ToxWindow *self)
|
||||
for (size_t i = 0; i < Friends.max_idx; ++i) {
|
||||
if (Friends.list[i].active) {
|
||||
free(Friends.list[i].conference_invite.key);
|
||||
#ifdef GAMES
|
||||
free(Friends.list[i].game_invite.data);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -583,6 +585,8 @@ static void friendlist_add_blocked(uint32_t fnum, uint32_t bnum)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef GAMES
|
||||
|
||||
static void friendlist_onGameInvite(ToxWindow *self, Tox *m, uint32_t friend_number, const uint8_t *data, size_t length)
|
||||
{
|
||||
UNUSED_VAR(self);
|
||||
@ -611,6 +615,8 @@ static void friendlist_onGameInvite(ToxWindow *self, Tox *m, uint32_t friend_num
|
||||
sound_notify(prompt, notif_error, NT_WNDALERT_1, NULL);
|
||||
}
|
||||
|
||||
#endif // GAMES
|
||||
|
||||
static void friendlist_onFileRecv(ToxWindow *self, Tox *m, uint32_t num, uint32_t filenum,
|
||||
uint64_t file_size, const char *filename, size_t name_length)
|
||||
{
|
||||
@ -1397,7 +1403,6 @@ ToxWindow *new_friendlist(void)
|
||||
ret->onStatusMessageChange = &friendlist_onStatusMessageChange;
|
||||
ret->onFileRecv = &friendlist_onFileRecv;
|
||||
ret->onConferenceInvite = &friendlist_onConferenceInvite;
|
||||
ret->onGameInvite = &friendlist_onGameInvite;
|
||||
|
||||
#ifdef AUDIO
|
||||
ret->onInvite = &friendlist_onAV;
|
||||
@ -1413,6 +1418,10 @@ ToxWindow *new_friendlist(void)
|
||||
ret->is_call = false;
|
||||
#endif /* AUDIO */
|
||||
|
||||
#ifdef GAMES
|
||||
ret->onGameInvite = &friendlist_onGameInvite;
|
||||
#endif
|
||||
|
||||
ret->num = -1;
|
||||
ret->active_box = -1;
|
||||
|
||||
|
@ -26,10 +26,13 @@
|
||||
#include <time.h>
|
||||
|
||||
#include "file_transfers.h"
|
||||
#include "game_base.h"
|
||||
#include "toxic.h"
|
||||
#include "windows.h"
|
||||
|
||||
#ifdef GAMES
|
||||
#include "game_base.h"
|
||||
#endif
|
||||
|
||||
struct LastOnline {
|
||||
uint64_t last_on;
|
||||
struct tm tm;
|
||||
@ -43,6 +46,8 @@ struct ConferenceInvite {
|
||||
bool pending;
|
||||
};
|
||||
|
||||
#ifdef GAMES
|
||||
|
||||
struct GameInvite {
|
||||
uint8_t *data;
|
||||
size_t data_length;
|
||||
@ -51,6 +56,8 @@ struct GameInvite {
|
||||
bool pending;
|
||||
};
|
||||
|
||||
#endif // GAMES
|
||||
|
||||
typedef struct {
|
||||
char name[TOXIC_MAX_NAME_LENGTH + 1];
|
||||
uint16_t namelength;
|
||||
@ -67,7 +74,10 @@ typedef struct {
|
||||
|
||||
struct LastOnline last_online;
|
||||
struct ConferenceInvite conference_invite;
|
||||
|
||||
#ifdef GAMES
|
||||
struct GameInvite game_invite;
|
||||
#endif
|
||||
|
||||
struct FileTransfer file_receiver[MAX_FILES];
|
||||
struct FileTransfer file_sender[MAX_FILES];
|
||||
|
@ -1065,4 +1065,3 @@ int game_send_packet(const GameData *game, const uint8_t *data, size_t length, G
|
||||
|
||||
return -0;
|
||||
}
|
||||
|
||||
|
@ -171,7 +171,6 @@ struct GameData {
|
||||
void *cb_game_on_packet_data;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Sets the callback for game state updates.
|
||||
*/
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include "avatars.h"
|
||||
#include "conference.h"
|
||||
#include "friendlist.h"
|
||||
#include "game_base.h"
|
||||
#include "help.h"
|
||||
#include "line_info.h"
|
||||
#include "log.h"
|
||||
@ -39,6 +38,10 @@
|
||||
#include "toxic_strings.h"
|
||||
#include "windows.h"
|
||||
|
||||
#ifdef GAMES
|
||||
#include "game_base.h"
|
||||
#endif
|
||||
|
||||
extern char *DATA_FILE;
|
||||
extern ToxWindow *prompt;
|
||||
extern FriendsList Friends;
|
||||
@ -341,6 +344,8 @@ void cmd_decline(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)
|
||||
--FrndRequests.num_requests;
|
||||
}
|
||||
|
||||
#ifdef GAMES
|
||||
|
||||
void cmd_game(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
@ -406,6 +411,8 @@ void cmd_game(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GAMES
|
||||
|
||||
void cmd_conference(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
|
@ -33,7 +33,6 @@ void cmd_clear(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE
|
||||
void cmd_connect(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||
void cmd_decline(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||
void cmd_conference(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||
void cmd_game(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||
void cmd_log(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||
void cmd_myid(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||
#ifdef QRCODE
|
||||
@ -63,4 +62,8 @@ void cmd_change_video_device(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv
|
||||
void cmd_run(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||
#endif /* PYTHON */
|
||||
|
||||
#ifdef GAMES
|
||||
void cmd_game(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||
#endif /* GAMES */
|
||||
|
||||
#endif /* GLOBAL_COMMANDS_H */
|
||||
|
17
src/help.c
17
src/help.c
@ -181,6 +181,10 @@ static void help_draw_global(ToxWindow *self)
|
||||
wprintw(win, " /log <on> or <off> : Enable/disable logging\n");
|
||||
wprintw(win, " /conference <type> : Create a conference where type: text | audio\n");
|
||||
wprintw(win, " /myid : Print your Tox ID\n");
|
||||
#ifdef GAMES
|
||||
wprintw(win, " /game : Play a game\n");
|
||||
#endif /* GAMES */
|
||||
|
||||
#ifdef QRCODE
|
||||
#ifdef QRPNG
|
||||
wprintw(win, " /myqr <txt> or <png> : Print your Tox ID's QR code to a file.\n");
|
||||
@ -264,6 +268,10 @@ static void help_draw_chat(ToxWindow *self)
|
||||
wprintw(win, " /video : Toggle video in call\n");
|
||||
#endif /* VIDEO */
|
||||
|
||||
#ifdef GAMES
|
||||
wprintw(win, " /game : Play a game with contact\n");
|
||||
#endif /* GAMES */
|
||||
|
||||
help_draw_bottom_menu(win);
|
||||
|
||||
box(win, ACS_VLINE, ACS_HLINE);
|
||||
@ -378,11 +386,11 @@ void help_onKey(ToxWindow *self, wint_t key)
|
||||
|
||||
case L'c':
|
||||
#ifdef VIDEO
|
||||
help_init_window(self, 25, 80);
|
||||
help_init_window(self, 26, 80);
|
||||
#elif AUDIO
|
||||
help_init_window(self, 20, 80);
|
||||
help_init_window(self, 21, 80);
|
||||
#else
|
||||
help_init_window(self, 10, 80);
|
||||
help_init_window(self, 11, 80);
|
||||
#endif
|
||||
self->help->type = HELP_CHAT;
|
||||
break;
|
||||
@ -396,6 +404,9 @@ void help_onKey(ToxWindow *self, wint_t key)
|
||||
#endif
|
||||
#ifdef PYTHON
|
||||
height += 2;
|
||||
#endif
|
||||
#ifdef GAMES
|
||||
height += 1;
|
||||
#endif
|
||||
help_init_window(self, height, 80);
|
||||
self->help->type = HELP_GLOBAL;
|
||||
|
@ -60,7 +60,9 @@ static const char *glob_cmd_list[] = {
|
||||
"/decline",
|
||||
"/exit",
|
||||
"/conference",
|
||||
#ifdef GAME
|
||||
"/game",
|
||||
#endif
|
||||
"/help",
|
||||
"/log",
|
||||
"/myid",
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include "conference.h"
|
||||
#include "file_transfers.h"
|
||||
#include "friendlist.h"
|
||||
#include "game_base.h"
|
||||
#include "line_info.h"
|
||||
#include "misc_tools.h"
|
||||
#include "prompt.h"
|
||||
@ -38,6 +37,10 @@
|
||||
#include "toxic.h"
|
||||
#include "windows.h"
|
||||
|
||||
#ifdef GAMES
|
||||
#include "game_base.h"
|
||||
#endif
|
||||
|
||||
extern char *DATA_FILE;
|
||||
extern struct Winthread Winthread;
|
||||
|
||||
@ -335,6 +338,8 @@ void on_lossless_custom_packet(Tox *m, uint32_t friendnumber, const uint8_t *dat
|
||||
uint8_t type = data[0];
|
||||
|
||||
switch (type) {
|
||||
#ifdef GAMES
|
||||
|
||||
case CUSTOM_PACKET_GAME_INVITE: {
|
||||
for (size_t i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||
ToxWindow *window = windows[i];
|
||||
@ -359,6 +364,8 @@ void on_lossless_custom_packet(Tox *m, uint32_t friendnumber, const uint8_t *dat
|
||||
break;
|
||||
}
|
||||
|
||||
#endif // GAMES
|
||||
|
||||
default: {
|
||||
fprintf(stderr, "Got unknown custom packet of type: %u\n", type);
|
||||
return;
|
||||
@ -502,6 +509,8 @@ void on_window_resize(void)
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef GAMES
|
||||
|
||||
if (w->type == WINDOW_TYPE_GAME) {
|
||||
delwin(w->window_bar);
|
||||
delwin(w->window);
|
||||
@ -515,6 +524,8 @@ void on_window_resize(void)
|
||||
continue;
|
||||
}
|
||||
|
||||
#endif // GAMES
|
||||
|
||||
if (w->help->active) {
|
||||
wclear(w->help->win);
|
||||
}
|
||||
@ -768,6 +779,8 @@ void draw_active_window(Tox *m)
|
||||
a->onDraw(a, m);
|
||||
wrefresh(a->window);
|
||||
|
||||
#ifdef GAMES
|
||||
|
||||
if (a->type == WINDOW_TYPE_GAME) {
|
||||
int ch = getch();
|
||||
|
||||
@ -785,6 +798,8 @@ void draw_active_window(Tox *m)
|
||||
return;
|
||||
}
|
||||
|
||||
#endif // GAMES
|
||||
|
||||
wint_t ch = 0;
|
||||
int printable = get_current_char(&ch);
|
||||
|
||||
@ -881,9 +896,14 @@ void kill_all_windows(Tox *m)
|
||||
kill_chat_window(w, m);
|
||||
} else if (w->type == WINDOW_TYPE_CONFERENCE) {
|
||||
free_conference(w, w->num);
|
||||
} else if (w->type == WINDOW_TYPE_GAME) {
|
||||
}
|
||||
|
||||
#ifdef GAMES
|
||||
else if (w->type == WINDOW_TYPE_GAME) {
|
||||
game_kill(w);
|
||||
}
|
||||
|
||||
#endif // GAMES
|
||||
}
|
||||
|
||||
/* TODO: use enum instead of magic indices */
|
||||
|
@ -87,7 +87,10 @@ typedef enum {
|
||||
WINDOW_TYPE_CHAT,
|
||||
WINDOW_TYPE_CONFERENCE,
|
||||
WINDOW_TYPE_FRIEND_LIST,
|
||||
|
||||
#ifdef GAMES
|
||||
WINDOW_TYPE_GAME,
|
||||
#endif
|
||||
} WINDOW_TYPE;
|
||||
|
||||
/* Fixes text color problem on some terminals.
|
||||
@ -139,7 +142,10 @@ typedef struct StatusBar StatusBar;
|
||||
typedef struct PromptBuf PromptBuf;
|
||||
typedef struct ChatContext ChatContext;
|
||||
typedef struct Help Help;
|
||||
|
||||
#ifdef GAMES
|
||||
typedef struct GameData GameData;
|
||||
#endif
|
||||
|
||||
struct ToxWindow {
|
||||
/* ncurses */
|
||||
@ -167,9 +173,10 @@ struct ToxWindow {
|
||||
void(*onTypingChange)(ToxWindow *, Tox *, uint32_t, bool);
|
||||
void(*onReadReceipt)(ToxWindow *, Tox *, uint32_t, uint32_t);
|
||||
|
||||
/* custom packets/games */
|
||||
#ifdef GAMES
|
||||
void(*onGameInvite)(ToxWindow *, Tox *, uint32_t, const uint8_t *, size_t);
|
||||
void(*onGameData)(ToxWindow *, Tox *, uint32_t, const uint8_t *, size_t);
|
||||
#endif // GAMES
|
||||
|
||||
#ifdef AUDIO
|
||||
|
||||
@ -208,7 +215,9 @@ struct ToxWindow {
|
||||
StatusBar *stb;
|
||||
Help *help;
|
||||
|
||||
#ifdef GAMES
|
||||
GameData *game;
|
||||
#endif
|
||||
|
||||
WINDOW *window;
|
||||
WINDOW *window_bar;
|
||||
|
Loading…
Reference in New Issue
Block a user