1
0

add websocket

This commit is contained in:
Your Name 2023-07-05 12:26:43 +08:00
parent a6ef7126be
commit 10b8c48493
11 changed files with 139 additions and 30 deletions

View File

@ -563,12 +563,7 @@ if(UNIX)
endif() endif()
find_package(Threads) find_package(Threads)
find_package(Wavpack) find_package(Wavpack)
if(WEBSOCKETS)
find_package(Websockets) find_package(Websockets)
else()
set(WEBSOCKETS_LIBRARIES)
set(WEBSOCKETS_INCLUDE_DIRS)
endif()
if(EXCEPTION_HANDLING) if(EXCEPTION_HANDLING)
find_package(ExceptionHandling) find_package(ExceptionHandling)
@ -647,10 +642,7 @@ show_dependency_status("Zlib" ZLIB)
if(DISCORD) if(DISCORD)
show_dependency_status("DiscordSdk" DiscordSdk) show_dependency_status("DiscordSdk" DiscordSdk)
endif() endif()
if(WEBSOCKETS)
show_dependency_status("Websockets" WEBSOCKETS) show_dependency_status("Websockets" WEBSOCKETS)
endif()
if(CLIENT AND VULKAN) if(CLIENT AND VULKAN)
show_dependency_status("Vulkan" VULKAN) show_dependency_status("Vulkan" VULKAN)
endif() endif()
@ -2467,6 +2459,7 @@ if(SERVER)
name_ban.h name_ban.h
register.cpp register.cpp
register.h register.h
ddncq.cpp
server.cpp server.cpp
server.h server.h
server_logger.cpp server_logger.cpp
@ -3307,10 +3300,6 @@ foreach(target ${TARGETS_OWN})
target_compile_definitions(${target} PRIVATE CONF_OPENSSL) target_compile_definitions(${target} PRIVATE CONF_OPENSSL)
target_include_directories(${target} SYSTEM PRIVATE ${CRYPTO_INCLUDE_DIRS}) target_include_directories(${target} SYSTEM PRIVATE ${CRYPTO_INCLUDE_DIRS})
endif() endif()
if(WEBSOCKETS)
target_compile_definitions(${target} PRIVATE CONF_WEBSOCKETS)
target_include_directories(${target} SYSTEM PRIVATE ${WEBSOCKETS_INCLUDE_DIRS})
endif()
if(UPNP) if(UPNP)
target_compile_definitions(${target} PRIVATE CONF_UPNP) target_compile_definitions(${target} PRIVATE CONF_UPNP)
target_include_directories(${target} SYSTEM PRIVATE ${MINIUPNPC_INCLUDE_DIRS}) target_include_directories(${target} SYSTEM PRIVATE ${MINIUPNPC_INCLUDE_DIRS})

View File

@ -0,0 +1,85 @@
#include "ddncq.h"
std::vector<struct lws*> websockets;
DDNetCQ* DDNetCQ::instance=nullptr;
DDNetCQ* const ddncq=DDNetCQ::GetInstance();
#define MAX_PLAYLOAD_LEN 10*1024
int WebSocketListener( struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len ) {
switch (reason){
case LWS_CALLBACK_ESTABLISHED:
dbg_msg("ws","client connected!");
websockets.emplace_back(wsi);
break;
case LWS_CALLBACK_RECEIVE:
{
unsigned char* msg=new uint8_t[1024];
memcpy(msg,in,len);
ddncq->gamectx->SendChat(-1,CGameContext::CHAT_ALL,(const char*)msg);
delete[] msg;
}
break;
case LWS_CALLBACK_CLOSED:
websockets.erase(std::remove(websockets.begin(),websockets.end(),wsi));
dbg_msg("ws","client closed!");
break;
default: break;
}
return 0;
}
struct lws_protocols protocols[]={
{
"ws",
WebSocketListener,
MAX_PLAYLOAD_LEN/2,
MAX_PLAYLOAD_LEN
},
{
0,0,0
}
};
void* DDNetCQ::InitWebSocket(void* args){
struct lws_context_creation_info info;
memset(&info,0,sizeof(info));
info.port = 1111;
info.protocols = protocols;
info.gid = -1;
info.uid = -1;
struct lws_context *context = lws_create_context( &info );
while ( 1 ) {
lws_service( context, 1000 );
}
lws_context_destroy( context );
}
void DDNetCQ::OnJoinMsg(int clientID,const char* name){
for(struct lws* wsi:websockets){
if(!wsi){
continue;
}
unsigned char msgPack[1024]="";
sprintf((char*)msgPack,"{\"type\":\"join\",\"data\":{\"client_id\":%d,\"name\":\"%s\"}}",clientID,name);
lws_write(wsi,msgPack,strlen((char*)msgPack),LWS_WRITE_TEXT);
}
}
void DDNetCQ::OnDisconnectMsg(int clientID,const char* name,const char* reason){
for(struct lws* wsi:websockets){
if(!wsi){
continue;
}
unsigned char msgPack[1024]="";
sprintf((char*)msgPack,"{\"type\":\"leave\",\"data\":{\"client_id\":%d,\"name\":\"%s\",\"reason\":\"%s\"}}",clientID,name,reason);
lws_write(wsi,msgPack,strlen((char*)msgPack),LWS_WRITE_TEXT);
}
}
void DDNetCQ::OnChatMsg(int clientID,const char* name,const char* msg){
for(struct lws* wsi:websockets){
if(!wsi){
continue;
}
unsigned char msgPack[1024]="";
sprintf((char*)msgPack,"{\"type\":\"chat\",\"data\":{\"client_id\":%d,\"name\":\"%s\",\"message\":\"%s\"}}",clientID,name,msg);
lws_write(wsi,msgPack,strlen((char*)msgPack),LWS_WRITE_TEXT);
}
}

27
src/engine/server/ddncq.h Normal file
View File

@ -0,0 +1,27 @@
#include <base/system.h>
#include <stdio.h>
#include <engine/server.h>
#include <game/server/gamecontext.h>
#include <game/server/gamecontroller.h>
#include <engine/shared/json.h>
#include <libwebsockets.h>
class DDNetCQ{
private:
static DDNetCQ* instance;
DDNetCQ(){};
~DDNetCQ(){};
public:
static DDNetCQ* GetInstance(){
if(!instance){
instance=new DDNetCQ();
}
return instance;
}
////////////////
CGameContext* gamectx=nullptr;
/////////////functions///////////////
static void* InitWebSocket(void* args);
static void OnJoinMsg(int clientID,const char* name);
static void OnDisconnectMsg(int clientID,const char* name,const char* reason);
static void OnChatMsg(int clientID,const char* name,const char* msg);
};

View File

@ -20,7 +20,8 @@
#include <engine/shared/config.h> #include <engine/shared/config.h>
#include <game/version.h> #include <game/version.h>
#include "ddncq.h"
#include <pthread.h>
#include <vector> #include <vector>
#if defined(CONF_FAMILY_WINDOWS) #if defined(CONF_FAMILY_WINDOWS)
@ -29,7 +30,6 @@
#endif #endif
#include <csignal> #include <csignal>
volatile sig_atomic_t InterruptSignaled = 0; volatile sig_atomic_t InterruptSignaled = 0;
bool IsInterrupted() bool IsInterrupted()
@ -186,12 +186,14 @@ int main(int argc, const char **argv)
} }
} }
pEngine->SetAdditionalLogger(std::make_unique<CServerLogger>(pServer)); pEngine->SetAdditionalLogger(std::make_unique<CServerLogger>(pServer));
dbg_msg("websocket","正在初始化WebScoket...");
pthread_t thread;
pthread_create(&thread,nullptr,DDNetCQ::InitWebSocket,nullptr);
MysqlUninit();
// run the server // run the server
dbg_msg("server", "正在启动服务器..."); dbg_msg("server", "正在启动服务器...");
int Ret = pServer->Run(); int Ret = pServer->Run();
MysqlUninit();
secure_random_uninit(); secure_random_uninit();
// free // free

View File

@ -675,7 +675,7 @@ bool CRegister::OnPacket(const CNetChunk *pPacket)
void CRegister::OnNewInfo(const char *pInfo) void CRegister::OnNewInfo(const char *pInfo)
{ {
log_trace("register", "info: %s", pInfo); log_trace("register", "信息: %s", pInfo);
if(m_GotServerInfo && str_comp(m_aServerInfo, pInfo) == 0) if(m_GotServerInfo && str_comp(m_aServerInfo, pInfo) == 0)
{ {
return; return;

View File

@ -2503,7 +2503,7 @@ int CServer::LoadMap(const char *pMapName)
{ {
m_pRegister->OnConfigChange(); m_pRegister->OnConfigChange();
} }
str_format(aBufMsg, sizeof(aBufMsg), "couldn't load map %s", aBuf); str_format(aBufMsg, sizeof(aBufMsg), "无法加载地图 %s", aBuf);
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "sixup", aBufMsg); Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "sixup", aBufMsg);
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "sixup", "disabling 0.7 compatibility"); Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "sixup", "disabling 0.7 compatibility");
} }

6
src/game/server/ddracechat.cpp Executable file → Normal file
View File

@ -662,13 +662,13 @@ void CGameContext::ConPractice(IConsole::IResult *pResult, void *pUserData)
int NumRequiredVotes = TeamSize / 2 + 1; int NumRequiredVotes = TeamSize / 2 + 1;
char aBuf[512]; char aBuf[512];
str_format(aBuf, sizeof(aBuf), "'%s' voted to %s /practice mode for your team, which means you can use /r, but you can't earn a rank. Type /practice to vote (%d/%d required votes)", pSelf->Server()->ClientName(pResult->m_ClientID), VotedForPractice ? "enable" : "disable", NumCurrentVotes, NumRequiredVotes); str_format(aBuf, sizeof(aBuf), "%s 想通过投票为队伍%s训练模式这意味着你可以直接使用 /r 命令,但你无法获得排名 输入 /practice 来投票 (%d/%d 已投票)", pSelf->Server()->ClientName(pResult->m_ClientID), VotedForPractice ? "启用" : "禁用", NumCurrentVotes, NumRequiredVotes);
pSelf->SendChatTeam(Team, aBuf); pSelf->SendChatTeam(Team, aBuf);
if(NumCurrentVotes >= NumRequiredVotes) if(NumCurrentVotes >= NumRequiredVotes)
{ {
Teams.SetPractice(Team, true); Teams.SetPractice(Team, true);
pSelf->SendChatTeam(Team, "为你的队伍启用练习模式"); pSelf->SendChatTeam(Team, "为你的队伍启用练习模式");
} }
} }
@ -1067,7 +1067,7 @@ void CGameContext::ConJoinTeam(IConsole::IResult *pResult, void *pUserData)
pPlayer->m_Last_Team = pSelf->Server()->Tick(); pPlayer->m_Last_Team = pSelf->Server()->Tick();
if(pController->m_Teams.IsPractice(Team)) if(pController->m_Teams.IsPractice(Team))
pSelf->SendChatTarget(pPlayer->GetCID(), "Practice mode enabled for your team, happy practicing!"); pSelf->SendChatTarget(pPlayer->GetCID(), "你的队伍正处于训练模式,祝你好运!");
} }
} }
} }

6
src/game/server/ddracecommands.cpp Executable file → Normal file
View File

@ -496,9 +496,9 @@ void CGameContext::Mute(const NETADDR *pAddr, int Secs, const char *pDisplayName
char aBuf[128]; char aBuf[128];
if(pReason[0]) if(pReason[0])
str_format(aBuf, sizeof aBuf, "'%s' has been muted for %d seconds (%s)", pDisplayName, Secs, pReason); str_format(aBuf, sizeof aBuf, "'%s 被禁言 %d 秒 (%s)", pDisplayName, Secs, pReason);
else else
str_format(aBuf, sizeof aBuf, "'%s' has been muted for %d seconds", pDisplayName, Secs); str_format(aBuf, sizeof aBuf, "'%s' 被禁言 %d 秒", pDisplayName, Secs);
SendChat(-1, CHAT_ALL, aBuf); SendChat(-1, CHAT_ALL, aBuf);
} }
@ -539,7 +539,7 @@ void CGameContext::ConVoteUnmute(IConsole::IResult *pResult, void *pUserData)
if(Found) if(Found)
{ {
char aBuf[128]; char aBuf[128];
str_format(aBuf, sizeof aBuf, "'%s' unbanned '%s' from voting.", str_format(aBuf, sizeof aBuf, "'%s 投票解除%s的封禁",
pSelf->Server()->ClientName(pResult->m_ClientID), pSelf->Server()->ClientName(Victim)); pSelf->Server()->ClientName(pResult->m_ClientID), pSelf->Server()->ClientName(Victim));
pSelf->SendChat(-1, 0, aBuf); pSelf->SendChat(-1, 0, aBuf);
} }

4
src/game/server/entities/character.cpp Executable file → Normal file
View File

@ -1515,7 +1515,7 @@ void CCharacter::HandleTiles(int Index)
// unlimited air jumps // unlimited air jumps
if(((m_TileIndex == TILE_UNLIMITED_JUMPS_ENABLE) || (m_TileFIndex == TILE_UNLIMITED_JUMPS_ENABLE)) && !m_Core.m_EndlessJump) if(((m_TileIndex == TILE_UNLIMITED_JUMPS_ENABLE) || (m_TileFIndex == TILE_UNLIMITED_JUMPS_ENABLE)) && !m_Core.m_EndlessJump)
{ {
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "用有了无限空中跳跃"); GameServer()->SendChatTarget(GetPlayer()->GetCID(), "拥有了无限跳跃");
m_Core.m_EndlessJump = true; m_Core.m_EndlessJump = true;
if(m_Core.m_Jumps == 0) if(m_Core.m_Jumps == 0)
{ {
@ -1525,7 +1525,7 @@ void CCharacter::HandleTiles(int Index)
} }
else if(((m_TileIndex == TILE_UNLIMITED_JUMPS_DISABLE) || (m_TileFIndex == TILE_UNLIMITED_JUMPS_DISABLE)) && m_Core.m_EndlessJump) else if(((m_TileIndex == TILE_UNLIMITED_JUMPS_DISABLE) || (m_TileFIndex == TILE_UNLIMITED_JUMPS_DISABLE)) && m_Core.m_EndlessJump)
{ {
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "没有无限空中跳跃"); GameServer()->SendChatTarget(GetPlayer()->GetCID(), "失去了无限跳跃");
m_Core.m_EndlessJump = false; m_Core.m_EndlessJump = false;
if(m_Core.m_Jumps == 0) if(m_Core.m_Jumps == 0)
{ {

View File

@ -33,6 +33,7 @@
#include "player.h" #include "player.h"
#include "score.h" #include "score.h"
#include <engine/server/ddncq.h>
// Not thread-safe! // Not thread-safe!
class CClientChatLogger : public ILogger class CClientChatLogger : public ILogger
{ {
@ -513,8 +514,9 @@ void CGameContext::SendChat(int ChatterClientID, int Team, const char *pText, in
char aBuf[256], aText[256]; char aBuf[256], aText[256];
str_copy(aText, pText, sizeof(aText)); str_copy(aText, pText, sizeof(aText));
if(ChatterClientID >= 0 && ChatterClientID < MAX_CLIENTS) if(ChatterClientID >= 0 && ChatterClientID < MAX_CLIENTS){
str_format(aBuf, sizeof(aBuf), "[%d:%d:%s]: %s", ChatterClientID, Team, Server()->ClientName(ChatterClientID), aText); str_format(aBuf, sizeof(aBuf), "[%d:%d:%s]: %s", ChatterClientID, Team, Server()->ClientName(ChatterClientID), aText);
}
else if(ChatterClientID == -2) else if(ChatterClientID == -2)
{ {
str_format(aBuf, sizeof(aBuf), "### %s", aText); str_format(aBuf, sizeof(aBuf), "### %s", aText);
@ -549,6 +551,8 @@ void CGameContext::SendChat(int ChatterClientID, int Team, const char *pText, in
} }
str_format(aBuf, sizeof aBuf, "Chat: %s", aText); str_format(aBuf, sizeof aBuf, "Chat: %s", aText);
if(ChatterClientID!=-1)
DDNetCQ::OnChatMsg(ChatterClientID,Server()->ClientName(ChatterClientID),aText);
LogEvent(aBuf, ChatterClientID); LogEvent(aBuf, ChatterClientID);
} }
else else

View File

@ -10,12 +10,12 @@
#include <game/server/player.h> #include <game/server/player.h>
#include <game/server/score.h> #include <game/server/score.h>
#include <game/version.h> #include <game/version.h>
#include <engine/server/ddncq.h>
CGameControllerDDRace::CGameControllerDDRace(class CGameContext *pGameServer) : CGameControllerDDRace::CGameControllerDDRace(class CGameContext *pGameServer) :
IGameController(pGameServer), m_Teams(pGameServer), m_pLoadBestTimeResult(nullptr) IGameController(pGameServer), m_Teams(pGameServer), m_pLoadBestTimeResult(nullptr)
{ {
m_pGameType = g_Config.m_SvModeName; m_pGameType = g_Config.m_SvModeName;
DDNetCQ::GetInstance()->gamectx=pGameServer;
InitTeleporter(); InitTeleporter();
} }
@ -136,6 +136,7 @@ void CGameControllerDDRace::OnPlayerConnect(CPlayer *pPlayer)
char aBuf[512]; char aBuf[512];
str_format(aBuf, sizeof(aBuf), "'%s' 已加入游戏", Server()->ClientName(ClientID)); str_format(aBuf, sizeof(aBuf), "'%s' 已加入游戏", Server()->ClientName(ClientID));
GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf, -1, CGameContext::CHAT_SIX); GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf, -1, CGameContext::CHAT_SIX);
DDNetCQ::OnJoinMsg(ClientID,Server()->ClientName(ClientID));
} }
} }
@ -145,6 +146,7 @@ void CGameControllerDDRace::OnPlayerDisconnect(CPlayer *pPlayer, const char *pRe
bool WasModerator = pPlayer->m_Moderating && Server()->ClientIngame(ClientID); bool WasModerator = pPlayer->m_Moderating && Server()->ClientIngame(ClientID);
IGameController::OnPlayerDisconnect(pPlayer, pReason); IGameController::OnPlayerDisconnect(pPlayer, pReason);
DDNetCQ::OnDisconnectMsg(ClientID,Server()->ClientName(ClientID),pReason);
if(!GameServer()->PlayerModerating() && WasModerator) if(!GameServer()->PlayerModerating() && WasModerator)
GameServer()->SendChat(-1, CGameContext::CHAT_ALL, "Server kick/spec votes are no longer actively moderated."); GameServer()->SendChat(-1, CGameContext::CHAT_ALL, "Server kick/spec votes are no longer actively moderated.");