Skip to content

Commit d4a149c

Browse files
committed
discord integration. config file. gplv3 license
1 parent d8ad46f commit d4a149c

13 files changed

+24659
-22
lines changed

.github/workflows/build.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
- name: Install dependencies
1313
run: |
1414
apt-get update
15-
apt-get -y install build-essential git libcurl4-gnutls-dev libasio-dev libicu-dev
15+
apt-get -y install build-essential git libcurl4-gnutls-dev libasio-dev libicu-dev libcurl4-gnutls-dev
1616
1717
- uses: actions/checkout@v4
1818
with:

LICENSE

+674
Large diffs are not rendered by default.

Makefile

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
#
2-
# dependencies: libasio-dev libicu-dev
2+
# dependencies: libasio-dev libicu-dev libcurl-dev
33
#
44
CXXFLAGS=-std=c++17 -O3 -Wall # -fsanitize=address -static-libasan
5-
DEPS=asio.h database.h models.h lobby_server.h gate_server.h common.h vms.h sega_crypto.h
5+
DEPS=asio.h database.h models.h lobby_server.h gate_server.h common.h vms.h sega_crypto.h json.hpp discord.h
66
INSTALL_DIR=/usr/local
77
USER=dcnet
88

99
all: iwango_server keycutter keycutter.cgi
1010

11-
iwango_server: lobby_server.o models.o packet_processor.o gate_server.o
12-
$(CXX) $(CXXFLAGS) -o $@ lobby_server.o models.o packet_processor.o gate_server.o -lpthread -licuuc
11+
iwango_server: lobby_server.o models.o packet_processor.o gate_server.o discord.o
12+
$(CXX) $(CXXFLAGS) -o $@ lobby_server.o models.o packet_processor.o gate_server.o discord.o -lpthread -licuuc -lcurl
1313

1414
keycutter: keycutter.o sega_crypto.o
1515
$(CXX) $(CXXFLAGS) -o keycutter keycutter.o sega_crypto.o

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@ A server emulator for the IWANGO lobby suite for Dreamcast.
1313
* Rune Jade
1414
* Sega Tetris
1515
* Yakyuu Team de Asobou Net!
16+
17+
C++ rewrite of the original server by Ioncannon:
18+
[https://github.com/filipmaj1/IWANGO-Server-Emulator](https://github.com/filipmaj1/IWANGO-Server-Emulator)

common.h

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#include <iostream>
66
#include <unicode/unistr.h>
77

8+
std::string getConfig(const std::string& name, const std::string& default_value);
9+
810
enum class GameId
911
{
1012
Daytona,

discord.cpp

+126
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/*
2+
Copyright (C) 2025 Flyinghead
3+
4+
This program is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation, either version 3 of the License, or
7+
(at your option) any later version.
8+
9+
This program is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU General Public License for more details.
13+
14+
You should have received a copy of the GNU General Public License
15+
along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
*/
17+
#include "discord.h"
18+
#include <curl/curl.h>
19+
#include "json.hpp"
20+
21+
static std::string DiscordWebhook;
22+
23+
using namespace nlohmann;
24+
25+
struct {
26+
const char *name;
27+
const char *url;
28+
} Games[] = {
29+
{ "Daytona USA", "https://dcnet.flyca.st/gamepic/daytona.jpg" },
30+
{ "Daytona USA", "https://dcnet.flyca.st/gamepic/daytona.jpg" },
31+
{ "Sega Tetris", "https://dcnet.flyca.st/gamepic/segatetris.jpg" },
32+
{ "Golf Shiyou Yo 2", "https://dcnet.flyca.st/gamepic/golfshiyou2.jpg" },
33+
};
34+
35+
class Notif
36+
{
37+
public:
38+
Notif(GameId gameId) : gameId(gameId) {}
39+
40+
std::string to_json() const
41+
{
42+
json embeds;
43+
embeds.push_back({
44+
{ "author",
45+
{
46+
{ "name", Games[(int)gameId].name },
47+
{ "icon_url", Games[(int)gameId].url }
48+
},
49+
},
50+
{ "title", embed.title },
51+
{ "description", embed.text },
52+
{ "color", 9118205 },
53+
});
54+
55+
json j = {
56+
{ "content", content },
57+
{ "embeds", embeds },
58+
};
59+
return j.dump(4);
60+
}
61+
62+
GameId gameId;
63+
std::string content;
64+
struct {
65+
std::string title;
66+
std::string text;
67+
} embed;
68+
};
69+
70+
static void postWebhook(const Notif& notif)
71+
{
72+
if (DiscordWebhook.empty())
73+
return;
74+
CURL *curl = curl_easy_init();
75+
if (curl == nullptr) {
76+
fprintf(stderr, "Can't create curl handle\n");
77+
return;
78+
}
79+
CURLcode res;
80+
curl_easy_setopt(curl, CURLOPT_URL, DiscordWebhook.c_str());
81+
curl_easy_setopt(curl, CURLOPT_USERAGENT, "DCNet-DiscordWebhook");
82+
curl_slist *headers = curl_slist_append(NULL, "Content-Type: application/json");
83+
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
84+
85+
std::string json = notif.to_json();
86+
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json.c_str());
87+
88+
res = curl_easy_perform(curl);
89+
if (res != CURLE_OK) {
90+
fprintf(stderr, "curl error: %d", res);
91+
}
92+
else
93+
{
94+
long code;
95+
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
96+
if (code < 200 || code >= 300)
97+
fprintf(stderr, "Discord error: %ld", code);
98+
}
99+
curl_slist_free_all(headers);
100+
curl_easy_cleanup(curl);
101+
}
102+
103+
void setDiscordWebhook(const std::string& url) {
104+
DiscordWebhook = url;
105+
}
106+
107+
void discordLobbyJoined(GameId gameId, const std::string& username, const std::string& lobbyName, const std::vector<std::string>& playerList)
108+
{
109+
Notif notif(gameId);
110+
notif.content = "Player **" + username + "** joined lobby ***" + lobbyName + "***";
111+
notif.embed.title = "Lobby Players";
112+
for (const auto& player : playerList)
113+
notif.embed.text += player + "\n";
114+
postWebhook(notif);
115+
}
116+
117+
void discordGameCreated(GameId gameId, const std::string& username, const std::string& gameName, const std::vector<std::string>& playerList)
118+
{
119+
Notif notif(gameId);
120+
notif.content = "Player **" + username + "** created team ***" + gameName + "***";
121+
notif.embed.title = "Lobby Players";
122+
for (const auto& player : playerList)
123+
notif.embed.text += player + "\n";
124+
125+
postWebhook(notif);
126+
}

discord.h

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
Copyright (C) 2025 Flyinghead
3+
4+
This program is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation, either version 3 of the License, or
7+
(at your option) any later version.
8+
9+
This program is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU General Public License for more details.
13+
14+
You should have received a copy of the GNU General Public License
15+
along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
*/
17+
#pragma once
18+
#include "common.h"
19+
#include <string>
20+
#include <vector>
21+
22+
void setDiscordWebhook(const std::string& url);
23+
void discordLobbyJoined(GameId gameId, const std::string& username, const std::string& lobbyName, const std::vector<std::string>& playerList);
24+
void discordGameCreated(GameId gameId, const std::string& username, const std::string& gameName, const std::vector<std::string>& playerList);

iwango.cfg

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#DaytonaServerName=
2+
DaytonaMOTD=Welcome to DCNet Daytona USA server
3+
#TetrisServerName=
4+
TetrisMOTD=Welcome to DCNet Sega Tetris server
5+
#GolfShiyou2ServerName=
6+
GolfShiyou2MOTD=Welcome to DCNet Golf Shiyou Yo 2 server
7+
#DiscordWebhook=https://discord.com/api/webhooks/...

0 commit comments

Comments
 (0)