diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a7859c..9a97df8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -563,12 +563,7 @@ if(UNIX) endif() find_package(Threads) find_package(Wavpack) -if(WEBSOCKETS) find_package(Websockets) -else() - set(WEBSOCKETS_LIBRARIES) - set(WEBSOCKETS_INCLUDE_DIRS) -endif() if(EXCEPTION_HANDLING) find_package(ExceptionHandling) @@ -647,10 +642,7 @@ show_dependency_status("Zlib" ZLIB) if(DISCORD) show_dependency_status("DiscordSdk" DiscordSdk) endif() -if(WEBSOCKETS) show_dependency_status("Websockets" WEBSOCKETS) -endif() - if(CLIENT AND VULKAN) show_dependency_status("Vulkan" VULKAN) endif() @@ -2467,6 +2459,7 @@ if(SERVER) name_ban.h register.cpp register.h + ddncq.cpp server.cpp server.h server_logger.cpp @@ -3307,10 +3300,6 @@ foreach(target ${TARGETS_OWN}) target_compile_definitions(${target} PRIVATE CONF_OPENSSL) target_include_directories(${target} SYSTEM PRIVATE ${CRYPTO_INCLUDE_DIRS}) endif() - if(WEBSOCKETS) - target_compile_definitions(${target} PRIVATE CONF_WEBSOCKETS) - target_include_directories(${target} SYSTEM PRIVATE ${WEBSOCKETS_INCLUDE_DIRS}) - endif() if(UPNP) target_compile_definitions(${target} PRIVATE CONF_UPNP) target_include_directories(${target} SYSTEM PRIVATE ${MINIUPNPC_INCLUDE_DIRS}) diff --git a/src/engine/server/ddncq.cpp b/src/engine/server/ddncq.cpp new file mode 100644 index 0000000..eb4ed10 --- /dev/null +++ b/src/engine/server/ddncq.cpp @@ -0,0 +1,85 @@ +#include "ddncq.h" + +std::vector 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); + } +} \ No newline at end of file diff --git a/src/engine/server/ddncq.h b/src/engine/server/ddncq.h new file mode 100644 index 0000000..b92de5b --- /dev/null +++ b/src/engine/server/ddncq.h @@ -0,0 +1,27 @@ +#include +#include +#include +#include +#include +#include +#include +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); +}; \ No newline at end of file diff --git a/src/engine/server/main.cpp b/src/engine/server/main.cpp index 5389da5..9530138 100644 --- a/src/engine/server/main.cpp +++ b/src/engine/server/main.cpp @@ -20,7 +20,8 @@ #include #include - +#include "ddncq.h" +#include #include #if defined(CONF_FAMILY_WINDOWS) @@ -29,7 +30,6 @@ #endif #include - volatile sig_atomic_t InterruptSignaled = 0; bool IsInterrupted() @@ -186,12 +186,14 @@ int main(int argc, const char **argv) } } pEngine->SetAdditionalLogger(std::make_unique(pServer)); - + dbg_msg("websocket","正在初始化WebScoket..."); + pthread_t thread; + pthread_create(&thread,nullptr,DDNetCQ::InitWebSocket,nullptr); + MysqlUninit(); // run the server dbg_msg("server", "正在启动服务器..."); int Ret = pServer->Run(); - - MysqlUninit(); + secure_random_uninit(); // free diff --git a/src/engine/server/register.cpp b/src/engine/server/register.cpp index 8f1b628..13262b1 100755 --- a/src/engine/server/register.cpp +++ b/src/engine/server/register.cpp @@ -675,7 +675,7 @@ bool CRegister::OnPacket(const CNetChunk *pPacket) 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) { return; diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index a7e46d0..e98514c 100755 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -2503,7 +2503,7 @@ int CServer::LoadMap(const char *pMapName) { 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", "disabling 0.7 compatibility"); } diff --git a/src/game/server/ddracechat.cpp b/src/game/server/ddracechat.cpp old mode 100755 new mode 100644 index e63535c..5cf987e --- a/src/game/server/ddracechat.cpp +++ b/src/game/server/ddracechat.cpp @@ -662,13 +662,13 @@ void CGameContext::ConPractice(IConsole::IResult *pResult, void *pUserData) int NumRequiredVotes = TeamSize / 2 + 1; 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); if(NumCurrentVotes >= NumRequiredVotes) { 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(); if(pController->m_Teams.IsPractice(Team)) - pSelf->SendChatTarget(pPlayer->GetCID(), "Practice mode enabled for your team, happy practicing!"); + pSelf->SendChatTarget(pPlayer->GetCID(), "你的队伍正处于训练模式,祝你好运!"); } } } diff --git a/src/game/server/ddracecommands.cpp b/src/game/server/ddracecommands.cpp old mode 100755 new mode 100644 index 377258a..866770a --- a/src/game/server/ddracecommands.cpp +++ b/src/game/server/ddracecommands.cpp @@ -496,9 +496,9 @@ void CGameContext::Mute(const NETADDR *pAddr, int Secs, const char *pDisplayName char aBuf[128]; 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 - 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); } @@ -539,7 +539,7 @@ void CGameContext::ConVoteUnmute(IConsole::IResult *pResult, void *pUserData) if(Found) { 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->SendChat(-1, 0, aBuf); } diff --git a/src/game/server/entities/character.cpp b/src/game/server/entities/character.cpp old mode 100755 new mode 100644 index 909c136..e8cfbba --- a/src/game/server/entities/character.cpp +++ b/src/game/server/entities/character.cpp @@ -1515,7 +1515,7 @@ void CCharacter::HandleTiles(int Index) // unlimited air jumps 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; 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) { - GameServer()->SendChatTarget(GetPlayer()->GetCID(), "你没有无限空中跳跃"); + GameServer()->SendChatTarget(GetPlayer()->GetCID(), "你失去了无限跳跃"); m_Core.m_EndlessJump = false; if(m_Core.m_Jumps == 0) { diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 825f980..ad1ffad 100755 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -33,6 +33,7 @@ #include "player.h" #include "score.h" +#include // Not thread-safe! class CClientChatLogger : public ILogger { @@ -513,8 +514,9 @@ void CGameContext::SendChat(int ChatterClientID, int Team, const char *pText, in char aBuf[256], aText[256]; 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); + } else if(ChatterClientID == -2) { 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); + if(ChatterClientID!=-1) + DDNetCQ::OnChatMsg(ChatterClientID,Server()->ClientName(ChatterClientID),aText); LogEvent(aBuf, ChatterClientID); } else diff --git a/src/game/server/gamemodes/DDRace.cpp b/src/game/server/gamemodes/DDRace.cpp index 14d5d77..8b5bf39 100755 --- a/src/game/server/gamemodes/DDRace.cpp +++ b/src/game/server/gamemodes/DDRace.cpp @@ -10,12 +10,12 @@ #include #include #include - +#include CGameControllerDDRace::CGameControllerDDRace(class CGameContext *pGameServer) : IGameController(pGameServer), m_Teams(pGameServer), m_pLoadBestTimeResult(nullptr) { m_pGameType = g_Config.m_SvModeName; - + DDNetCQ::GetInstance()->gamectx=pGameServer; InitTeleporter(); } @@ -136,6 +136,7 @@ void CGameControllerDDRace::OnPlayerConnect(CPlayer *pPlayer) char aBuf[512]; str_format(aBuf, sizeof(aBuf), "'%s' 已加入游戏", Server()->ClientName(ClientID)); 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); IGameController::OnPlayerDisconnect(pPlayer, pReason); + DDNetCQ::OnDisconnectMsg(ClientID,Server()->ClientName(ClientID),pReason); if(!GameServer()->PlayerModerating() && WasModerator) GameServer()->SendChat(-1, CGameContext::CHAT_ALL, "Server kick/spec votes are no longer actively moderated.");