mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 01:58:19 +00:00
Introduce ddnet-info.json
- Single json file containing all information for the client - Fetched from https://info.ddnet.tw/info?name=deen - Replaces versionsrv, news, ddnet-maps.json and ddnet-ranks.json - Servers are sorted by most popular ones for respective player - Always stays < 100 ms response time, compared to occasional 50 s for old ddnet-ranks.json
This commit is contained in:
parent
27b7549bba
commit
89ed22e8d8
|
@ -399,8 +399,6 @@ set_glob(ENGINE_SHARED GLOB src/engine/shared
|
||||||
linereader.cpp
|
linereader.cpp
|
||||||
linereader.h
|
linereader.h
|
||||||
map.cpp
|
map.cpp
|
||||||
mapchecker.cpp
|
|
||||||
mapchecker.h
|
|
||||||
masterserver.cpp
|
masterserver.cpp
|
||||||
memheap.cpp
|
memheap.cpp
|
||||||
memheap.h
|
memheap.h
|
||||||
|
@ -793,26 +791,21 @@ list(APPEND TARGETS_LINK ${TARGET_SERVER})
|
||||||
########################################################################
|
########################################################################
|
||||||
|
|
||||||
set_glob(MASTERSRV_SRC GLOB src/mastersrv mastersrv.cpp mastersrv.h)
|
set_glob(MASTERSRV_SRC GLOB src/mastersrv mastersrv.cpp mastersrv.h)
|
||||||
set_glob(VERSIONSRV_SRC GLOB src/versionsrv mapversions.h versionsrv.cpp versionsrv.h)
|
|
||||||
set_glob(TWPING_SRC GLOB src/twping twping.cpp)
|
set_glob(TWPING_SRC GLOB src/twping twping.cpp)
|
||||||
|
|
||||||
set(TARGET_MASTERSRV mastersrv)
|
set(TARGET_MASTERSRV mastersrv)
|
||||||
set(TARGET_VERSIONSRV versionsrv)
|
|
||||||
set(TARGET_TWPING twping)
|
set(TARGET_TWPING twping)
|
||||||
|
|
||||||
add_executable(${TARGET_MASTERSRV} EXCLUDE_FROM_ALL ${MASTERSRV_SRC} $<TARGET_OBJECTS:engine-shared> ${DEPS})
|
add_executable(${TARGET_MASTERSRV} EXCLUDE_FROM_ALL ${MASTERSRV_SRC} $<TARGET_OBJECTS:engine-shared> ${DEPS})
|
||||||
add_executable(${TARGET_VERSIONSRV} EXCLUDE_FROM_ALL ${VERSIONSRV_SRC} $<TARGET_OBJECTS:engine-shared> ${DEPS})
|
|
||||||
add_executable(${TARGET_TWPING} EXCLUDE_FROM_ALL ${TWPING_SRC} $<TARGET_OBJECTS:engine-shared> ${DEPS})
|
add_executable(${TARGET_TWPING} EXCLUDE_FROM_ALL ${TWPING_SRC} $<TARGET_OBJECTS:engine-shared> ${DEPS})
|
||||||
|
|
||||||
add_custom_target(generate_nethash DEPENDS src/game/generated/nethash.cpp)
|
add_custom_target(generate_nethash DEPENDS src/game/generated/nethash.cpp)
|
||||||
add_dependencies(${TARGET_VERSIONSRV} generate_nethash)
|
|
||||||
|
|
||||||
target_link_libraries(${TARGET_MASTERSRV} ${LIBS})
|
target_link_libraries(${TARGET_MASTERSRV} ${LIBS})
|
||||||
target_link_libraries(${TARGET_VERSIONSRV} ${LIBS})
|
|
||||||
target_link_libraries(${TARGET_TWPING} ${LIBS})
|
target_link_libraries(${TARGET_TWPING} ${LIBS})
|
||||||
|
|
||||||
list(APPEND TARGETS_OWN ${TARGET_MASTERSRV} ${TARGET_TWPING} ${TARGET_VERSIONSRV})
|
list(APPEND TARGETS_OWN ${TARGET_MASTERSRV} ${TARGET_TWPING})
|
||||||
list(APPEND TARGETS_LINK ${TARGET_MASTERSRV} ${TARGET_TWPING} ${TARGET_VERSIONSRV})
|
list(APPEND TARGETS_LINK ${TARGET_MASTERSRV} ${TARGET_TWPING})
|
||||||
|
|
||||||
set(TARGETS_TOOLS)
|
set(TARGETS_TOOLS)
|
||||||
set_glob(TOOLS GLOB src/tools
|
set_glob(TOOLS GLOB src/tools
|
||||||
|
|
4
bam.lua
4
bam.lua
|
@ -348,7 +348,6 @@ function build(settings)
|
||||||
client = Compile(client_settings, Collect("src/engine/client/*.cpp"))
|
client = Compile(client_settings, Collect("src/engine/client/*.cpp"))
|
||||||
server = Compile(server_settings, Collect("src/engine/server/*.cpp"))
|
server = Compile(server_settings, Collect("src/engine/server/*.cpp"))
|
||||||
|
|
||||||
versionserver = Compile(settings, Collect("src/versionsrv/*.cpp"))
|
|
||||||
masterserver = Compile(settings, Collect("src/mastersrv/*.cpp"))
|
masterserver = Compile(settings, Collect("src/mastersrv/*.cpp"))
|
||||||
twping = Compile(settings, Collect("src/twping/*.cpp"))
|
twping = Compile(settings, Collect("src/twping/*.cpp"))
|
||||||
game_shared = Compile(settings, Collect("src/game/*.cpp"), nethash, network_source)
|
game_shared = Compile(settings, Collect("src/game/*.cpp"), nethash, network_source)
|
||||||
|
@ -390,9 +389,6 @@ function build(settings)
|
||||||
serverlaunch = Link(launcher_settings, "serverlaunch", server_osxlaunch)
|
serverlaunch = Link(launcher_settings, "serverlaunch", server_osxlaunch)
|
||||||
end
|
end
|
||||||
|
|
||||||
versionserver_exe = Link(server_settings, "versionsrv", versionserver,
|
|
||||||
engine, zlib, libwebsockets, md5, game_shared)
|
|
||||||
|
|
||||||
masterserver_exe = Link(server_settings, "mastersrv", masterserver,
|
masterserver_exe = Link(server_settings, "mastersrv", masterserver,
|
||||||
engine, zlib, libwebsockets, md5, game_shared)
|
engine, zlib, libwebsockets, md5, game_shared)
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#include "message.h"
|
#include "message.h"
|
||||||
#include <engine/friends.h>
|
#include <engine/friends.h>
|
||||||
#include <engine/shared/config.h>
|
#include <engine/shared/config.h>
|
||||||
#include <versionsrv/versionsrv.h>
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -40,7 +39,7 @@ protected:
|
||||||
|
|
||||||
int m_GameTickSpeed;
|
int m_GameTickSpeed;
|
||||||
public:
|
public:
|
||||||
char m_aNews[NEWS_SIZE];
|
char m_aNews[3000];
|
||||||
int64 m_ReconnectTime;
|
int64 m_ReconnectTime;
|
||||||
|
|
||||||
class CSnapItem
|
class CSnapItem
|
||||||
|
@ -135,8 +134,6 @@ public:
|
||||||
// server info
|
// server info
|
||||||
virtual void GetServerInfo(class CServerInfo *pServerInfo) = 0;
|
virtual void GetServerInfo(class CServerInfo *pServerInfo) = 0;
|
||||||
|
|
||||||
virtual void CheckVersionUpdate() = 0;
|
|
||||||
|
|
||||||
virtual int GetPredictionTime() = 0;
|
virtual int GetPredictionTime() = 0;
|
||||||
|
|
||||||
// snapshot interface
|
// snapshot interface
|
||||||
|
@ -189,8 +186,7 @@ public:
|
||||||
virtual void DemoSliceEnd() = 0;
|
virtual void DemoSliceEnd() = 0;
|
||||||
virtual void DemoSlice(const char *pDstPath, CLIENTFUNC_FILTER pfnFilter, void *pUser) = 0;
|
virtual void DemoSlice(const char *pDstPath, CLIENTFUNC_FILTER pfnFilter, void *pUser) = 0;
|
||||||
|
|
||||||
virtual void RequestDDNetSrvList() = 0;
|
virtual void RequestDDNetInfo() = 0;
|
||||||
virtual void RequestDDNetRanks() = 0;
|
|
||||||
virtual bool EditorHasUnsavedData() = 0;
|
virtual bool EditorHasUnsavedData() = 0;
|
||||||
|
|
||||||
virtual void GenerateTimeoutSeed() = 0;
|
virtual void GenerateTimeoutSeed() = 0;
|
||||||
|
|
|
@ -41,7 +41,6 @@
|
||||||
#include <engine/shared/datafile.h>
|
#include <engine/shared/datafile.h>
|
||||||
#include <engine/shared/demo.h>
|
#include <engine/shared/demo.h>
|
||||||
#include <engine/shared/filecollection.h>
|
#include <engine/shared/filecollection.h>
|
||||||
#include <engine/shared/mapchecker.h>
|
|
||||||
#include <engine/shared/network.h>
|
#include <engine/shared/network.h>
|
||||||
#include <engine/shared/packer.h>
|
#include <engine/shared/packer.h>
|
||||||
#include <engine/shared/protocol.h>
|
#include <engine/shared/protocol.h>
|
||||||
|
@ -55,7 +54,6 @@
|
||||||
#include <game/version.h>
|
#include <game/version.h>
|
||||||
|
|
||||||
#include <mastersrv/mastersrv.h>
|
#include <mastersrv/mastersrv.h>
|
||||||
#include <versionsrv/versionsrv.h>
|
|
||||||
|
|
||||||
#include <engine/client/serverbrowser.h>
|
#include <engine/client/serverbrowser.h>
|
||||||
|
|
||||||
|
@ -302,7 +300,7 @@ CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta)
|
||||||
|
|
||||||
// version-checking
|
// version-checking
|
||||||
m_aVersionStr[0] = '0';
|
m_aVersionStr[0] = '0';
|
||||||
m_aVersionStr[1] = 0;
|
m_aVersionStr[1] = '\0';
|
||||||
|
|
||||||
// pinging
|
// pinging
|
||||||
m_PingStartTime = 0;
|
m_PingStartTime = 0;
|
||||||
|
@ -320,7 +318,9 @@ CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta)
|
||||||
m_MapdownloadCrc = 0;
|
m_MapdownloadCrc = 0;
|
||||||
m_MapdownloadAmount = -1;
|
m_MapdownloadAmount = -1;
|
||||||
m_MapdownloadTotalsize = -1;
|
m_MapdownloadTotalsize = -1;
|
||||||
m_pDDNetRanksTask = NULL;
|
|
||||||
|
m_pDDNetInfoTask = NULL;
|
||||||
|
m_aNews[0] = '\0';
|
||||||
|
|
||||||
m_CurrentServerInfoRequestTime = -1;
|
m_CurrentServerInfoRequestTime = -1;
|
||||||
|
|
||||||
|
@ -345,7 +345,6 @@ CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta)
|
||||||
if (g_Config.m_ClDummy == 0)
|
if (g_Config.m_ClDummy == 0)
|
||||||
m_LastDummyConnectTime = 0;
|
m_LastDummyConnectTime = 0;
|
||||||
|
|
||||||
m_DDNetSrvListTokenSet = false;
|
|
||||||
m_ReconnectTime = 0;
|
m_ReconnectTime = 0;
|
||||||
|
|
||||||
m_GenerateTimeoutSeed = true;
|
m_GenerateTimeoutSeed = true;
|
||||||
|
@ -1133,128 +1132,6 @@ int CClient::PlayerScoreNameComp(const void *a, const void *b)
|
||||||
|
|
||||||
void CClient::ProcessConnlessPacket(CNetChunk *pPacket)
|
void CClient::ProcessConnlessPacket(CNetChunk *pPacket)
|
||||||
{
|
{
|
||||||
// version server
|
|
||||||
if(m_VersionInfo.m_State == CVersionInfo::STATE_READY && net_addr_comp(&pPacket->m_Address, &m_VersionInfo.m_VersionServeraddr.m_Addr) == 0)
|
|
||||||
{
|
|
||||||
// version info
|
|
||||||
if(pPacket->m_DataSize == (int)(sizeof(VERSIONSRV_VERSION) + sizeof(GAME_RELEASE_VERSION)) &&
|
|
||||||
mem_comp(pPacket->m_pData, VERSIONSRV_VERSION, sizeof(VERSIONSRV_VERSION)) == 0)
|
|
||||||
{
|
|
||||||
char *pVersionData = (char*)pPacket->m_pData + sizeof(VERSIONSRV_VERSION);
|
|
||||||
int aCurVersion[] = {0,0,0}, aNewVersion[] = {0,0,0};
|
|
||||||
sscanf(pVersionData, "%d.%d.%d", aNewVersion, aNewVersion+1, aNewVersion+2);
|
|
||||||
sscanf(GAME_RELEASE_VERSION, "%d.%d.%d", aCurVersion, aCurVersion+1, aCurVersion+2);
|
|
||||||
bool VersionMatch = mem_comp(aCurVersion, aNewVersion, sizeof aCurVersion) >= 0;
|
|
||||||
|
|
||||||
char aVersion[sizeof(GAME_RELEASE_VERSION)];
|
|
||||||
str_copy(aVersion, pVersionData, sizeof(aVersion));
|
|
||||||
|
|
||||||
char aBuf[256];
|
|
||||||
str_format(aBuf, sizeof(aBuf), "version does %s (%s)",
|
|
||||||
VersionMatch ? "match" : "NOT match",
|
|
||||||
aVersion);
|
|
||||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/version", aBuf);
|
|
||||||
|
|
||||||
// assume version is out of date when version-data doesn't match
|
|
||||||
if(!VersionMatch)
|
|
||||||
str_copy(m_aVersionStr, aVersion, sizeof(m_aVersionStr));
|
|
||||||
|
|
||||||
// request the news
|
|
||||||
CNetChunk Packet;
|
|
||||||
mem_zero(&Packet, sizeof(Packet));
|
|
||||||
Packet.m_ClientID = -1;
|
|
||||||
Packet.m_Address = m_VersionInfo.m_VersionServeraddr.m_Addr;
|
|
||||||
Packet.m_pData = VERSIONSRV_GETNEWS;
|
|
||||||
Packet.m_DataSize = sizeof(VERSIONSRV_GETNEWS);
|
|
||||||
Packet.m_Flags = NETSENDFLAG_CONNLESS;
|
|
||||||
m_NetClient[g_Config.m_ClDummy].Send(&Packet);
|
|
||||||
|
|
||||||
// request the map version list now
|
|
||||||
mem_zero(&Packet, sizeof(Packet));
|
|
||||||
Packet.m_ClientID = -1;
|
|
||||||
Packet.m_Address = m_VersionInfo.m_VersionServeraddr.m_Addr;
|
|
||||||
Packet.m_pData = VERSIONSRV_GETMAPLIST;
|
|
||||||
Packet.m_DataSize = sizeof(VERSIONSRV_GETMAPLIST);
|
|
||||||
Packet.m_Flags = NETSENDFLAG_CONNLESS;
|
|
||||||
m_NetClient[g_Config.m_ClDummy].Send(&Packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
// news
|
|
||||||
if(pPacket->m_DataSize == (int)(sizeof(VERSIONSRV_NEWS) + NEWS_SIZE) &&
|
|
||||||
mem_comp(pPacket->m_pData, VERSIONSRV_NEWS, sizeof(VERSIONSRV_NEWS)) == 0)
|
|
||||||
{
|
|
||||||
if(mem_comp(m_aNews, (char*)pPacket->m_pData + sizeof(VERSIONSRV_NEWS), NEWS_SIZE))
|
|
||||||
g_Config.m_UiPage = CMenus::PAGE_NEWS;
|
|
||||||
|
|
||||||
mem_copy(m_aNews, (char*)pPacket->m_pData + sizeof(VERSIONSRV_NEWS), NEWS_SIZE);
|
|
||||||
|
|
||||||
IOHANDLE NewsFile = m_pStorage->OpenFile("ddnet-news.txt", IOFLAG_WRITE, IStorage::TYPE_SAVE);
|
|
||||||
if(NewsFile)
|
|
||||||
{
|
|
||||||
io_write(NewsFile, m_aNews, sizeof(m_aNews));
|
|
||||||
io_close(NewsFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ddnet server list
|
|
||||||
// Packet: VERSIONSRV_DDNETLIST + char[4] Token + int16 comp_length + int16 plain_length + char[comp_length]
|
|
||||||
if(pPacket->m_DataSize >= (int)(sizeof(VERSIONSRV_DDNETLIST) + 8) &&
|
|
||||||
mem_comp(pPacket->m_pData, VERSIONSRV_DDNETLIST, sizeof(VERSIONSRV_DDNETLIST)) == 0 &&
|
|
||||||
mem_comp((char*)pPacket->m_pData+sizeof(VERSIONSRV_DDNETLIST), m_aDDNetSrvListToken, 4) == 0)
|
|
||||||
{
|
|
||||||
// reset random token
|
|
||||||
m_DDNetSrvListTokenSet = false;
|
|
||||||
int CompLength = *(short*)((char*)pPacket->m_pData+(sizeof(VERSIONSRV_DDNETLIST)+4));
|
|
||||||
int PlainLength = *(short*)((char*)pPacket->m_pData+(sizeof(VERSIONSRV_DDNETLIST)+6));
|
|
||||||
|
|
||||||
if (pPacket->m_DataSize == (int)(sizeof(VERSIONSRV_DDNETLIST) + 8 + CompLength))
|
|
||||||
{
|
|
||||||
char aBuf[16384];
|
|
||||||
uLongf DstLen = sizeof(aBuf);
|
|
||||||
const char *pComp = (char*)pPacket->m_pData+sizeof(VERSIONSRV_DDNETLIST)+8;
|
|
||||||
|
|
||||||
// do decompression of serverlist
|
|
||||||
if(uncompress((Bytef*)aBuf, &DstLen, (Bytef*)pComp, CompLength) == Z_OK && (int)DstLen == PlainLength)
|
|
||||||
{
|
|
||||||
aBuf[DstLen] = '\0';
|
|
||||||
bool ListChanged = true;
|
|
||||||
|
|
||||||
IOHANDLE File = m_pStorage->OpenFile("ddnet-servers.json", IOFLAG_READ, IStorage::TYPE_SAVE);
|
|
||||||
if(File)
|
|
||||||
{
|
|
||||||
char aBuf2[16384];
|
|
||||||
io_read(File, aBuf2, sizeof(aBuf2));
|
|
||||||
io_close(File);
|
|
||||||
if (str_comp(aBuf, aBuf2) == 0)
|
|
||||||
ListChanged = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// decompression successful, write plain file
|
|
||||||
if(ListChanged)
|
|
||||||
{
|
|
||||||
IOHANDLE File = m_pStorage->OpenFile("ddnet-servers.json", IOFLAG_WRITE, IStorage::TYPE_SAVE);
|
|
||||||
if(File)
|
|
||||||
{
|
|
||||||
io_write(File, aBuf, PlainLength);
|
|
||||||
io_close(File);
|
|
||||||
}
|
|
||||||
if(g_Config.m_UiPage == CMenus::PAGE_DDNET)
|
|
||||||
m_ServerBrowser.Refresh(IServerBrowser::TYPE_DDNET);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// map version list
|
|
||||||
if(pPacket->m_DataSize >= (int)sizeof(VERSIONSRV_MAPLIST) &&
|
|
||||||
mem_comp(pPacket->m_pData, VERSIONSRV_MAPLIST, sizeof(VERSIONSRV_MAPLIST)) == 0)
|
|
||||||
{
|
|
||||||
int Size = pPacket->m_DataSize-sizeof(VERSIONSRV_MAPLIST);
|
|
||||||
int Num = Size/sizeof(CMapVersion);
|
|
||||||
m_MapChecker.AddMaplist((CMapVersion *)((char*)pPacket->m_pData+sizeof(VERSIONSRV_MAPLIST)), Num);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//server count from master server
|
//server count from master server
|
||||||
if(pPacket->m_DataSize == (int)sizeof(SERVERBROWSE_COUNT) + 2 && mem_comp(pPacket->m_pData, SERVERBROWSE_COUNT, sizeof(SERVERBROWSE_COUNT)) == 0)
|
if(pPacket->m_DataSize == (int)sizeof(SERVERBROWSE_COUNT) + 2 && mem_comp(pPacket->m_pData, SERVERBROWSE_COUNT, sizeof(SERVERBROWSE_COUNT)) == 0)
|
||||||
{
|
{
|
||||||
|
@ -1584,10 +1461,6 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
|
||||||
if(m_DummyConnected)
|
if(m_DummyConnected)
|
||||||
DummyDisconnect(0);
|
DummyDisconnect(0);
|
||||||
|
|
||||||
// check for valid standard map
|
|
||||||
if(!m_MapChecker.IsMapValid(pMap, MapCrc, MapSize))
|
|
||||||
pError = "invalid standard map";
|
|
||||||
|
|
||||||
for(int i = 0; pMap[i]; i++) // protect the player from nasty map names
|
for(int i = 0; pMap[i]; i++) // protect the player from nasty map names
|
||||||
{
|
{
|
||||||
if(pMap[i] == '/' || pMap[i] == '\\')
|
if(pMap[i] == '/' || pMap[i] == '\\')
|
||||||
|
@ -2257,21 +2130,55 @@ void CClient::FinishMapDownload()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CClient::ResetDDNetRanks()
|
void CClient::ResetDDNetInfo()
|
||||||
{
|
{
|
||||||
if(m_pDDNetRanksTask)
|
if(m_pDDNetInfoTask)
|
||||||
{
|
{
|
||||||
m_pDDNetRanksTask->Abort();
|
m_pDDNetInfoTask->Abort();
|
||||||
delete m_pDDNetRanksTask;
|
delete m_pDDNetInfoTask;
|
||||||
m_pDDNetRanksTask = NULL;
|
m_pDDNetInfoTask = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CClient::FinishDDNetRanks()
|
void CClient::FinishDDNetInfo()
|
||||||
{
|
{
|
||||||
ResetDDNetRanks();
|
ResetDDNetInfo();
|
||||||
m_pStorage->RenameFile("ddnet-ranks.json.tmp", "ddnet-ranks.json", IStorage::TYPE_SAVE);
|
m_pStorage->RenameFile("ddnet-info.json.tmp", "ddnet-info.json", IStorage::TYPE_SAVE);
|
||||||
m_ServerBrowser.LoadDDNetRanks();
|
LoadDDNetInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CClient::LoadDDNetInfo()
|
||||||
|
{
|
||||||
|
const json_value *pDDNetInfo = m_ServerBrowser.LoadDDNetInfo();
|
||||||
|
|
||||||
|
if(!pDDNetInfo)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const json_value *pVersion = json_object_get(pDDNetInfo, "version");
|
||||||
|
if(pVersion && pVersion->type == json_string)
|
||||||
|
{
|
||||||
|
const char *pVersionString = json_string_get(pVersion);
|
||||||
|
if(str_comp(pVersionString, GAME_RELEASE_VERSION))
|
||||||
|
{
|
||||||
|
str_copy(m_aVersionStr, pVersionString, sizeof(m_aVersionStr));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_aVersionStr[0] = '0';
|
||||||
|
m_aVersionStr[1] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const json_value *pNews = json_object_get(pDDNetInfo, "news");
|
||||||
|
if(pNews && pNews->type == json_string)
|
||||||
|
{
|
||||||
|
const char *pNewsString = json_string_get(pNews);
|
||||||
|
|
||||||
|
if(m_aNews[0] && str_comp(m_aNews, pNewsString))
|
||||||
|
g_Config.m_UiPage = CMenus::PAGE_NEWS;
|
||||||
|
|
||||||
|
str_copy(m_aNews, pNewsString, sizeof(m_aNews));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CClient::PumpNetwork()
|
void CClient::PumpNetwork()
|
||||||
|
@ -2584,19 +2491,19 @@ void CClient::Update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_pDDNetRanksTask)
|
if(m_pDDNetInfoTask)
|
||||||
{
|
{
|
||||||
if(m_pDDNetRanksTask->State() == CFetchTask::STATE_DONE)
|
if(m_pDDNetInfoTask->State() == CFetchTask::STATE_DONE)
|
||||||
FinishDDNetRanks();
|
FinishDDNetInfo();
|
||||||
else if(m_pDDNetRanksTask->State() == CFetchTask::STATE_ERROR)
|
else if(m_pDDNetInfoTask->State() == CFetchTask::STATE_ERROR)
|
||||||
{
|
{
|
||||||
dbg_msg("ddnet-ranks", "download failed");
|
dbg_msg("ddnet-info", "download failed");
|
||||||
ResetDDNetRanks();
|
ResetDDNetInfo();
|
||||||
}
|
}
|
||||||
else if(m_pDDNetRanksTask->State() == CFetchTask::STATE_ABORTED)
|
else if(m_pDDNetInfoTask->State() == CFetchTask::STATE_ABORTED)
|
||||||
{
|
{
|
||||||
delete m_pDDNetRanksTask;
|
delete m_pDDNetInfoTask;
|
||||||
m_pDDNetRanksTask = NULL;
|
m_pDDNetInfoTask = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2618,40 +2525,6 @@ void CClient::Update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CClient::VersionUpdate()
|
|
||||||
{
|
|
||||||
if(m_VersionInfo.m_State == CVersionInfo::STATE_INIT)
|
|
||||||
{
|
|
||||||
Engine()->HostLookup(&m_VersionInfo.m_VersionServeraddr, "version.ddnet.tw", m_NetClient[0].NetType());
|
|
||||||
m_VersionInfo.m_State = CVersionInfo::STATE_START;
|
|
||||||
}
|
|
||||||
else if(m_VersionInfo.m_State == CVersionInfo::STATE_START)
|
|
||||||
{
|
|
||||||
if(m_VersionInfo.m_VersionServeraddr.m_Job.Status() == CJob::STATE_DONE)
|
|
||||||
{
|
|
||||||
CNetChunk Packet;
|
|
||||||
|
|
||||||
mem_zero(&Packet, sizeof(Packet));
|
|
||||||
|
|
||||||
m_VersionInfo.m_VersionServeraddr.m_Addr.port = VERSIONSRV_PORT;
|
|
||||||
|
|
||||||
Packet.m_ClientID = -1;
|
|
||||||
Packet.m_Address = m_VersionInfo.m_VersionServeraddr.m_Addr;
|
|
||||||
Packet.m_pData = VERSIONSRV_GETVERSION;
|
|
||||||
Packet.m_DataSize = sizeof(VERSIONSRV_GETVERSION);
|
|
||||||
Packet.m_Flags = NETSENDFLAG_CONNLESS;
|
|
||||||
|
|
||||||
m_NetClient[0].Send(&Packet);
|
|
||||||
m_VersionInfo.m_State = CVersionInfo::STATE_READY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CClient::CheckVersionUpdate()
|
|
||||||
{
|
|
||||||
m_VersionInfo.m_State = CVersionInfo::STATE_START;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CClient::RegisterInterfaces()
|
void CClient::RegisterInterfaces()
|
||||||
{
|
{
|
||||||
Kernel()->RegisterInterface(static_cast<IDemoRecorder*>(&m_DemoRecorder[RECORDER_MANUAL]), false);
|
Kernel()->RegisterInterface(static_cast<IDemoRecorder*>(&m_DemoRecorder[RECORDER_MANUAL]), false);
|
||||||
|
@ -2694,13 +2567,6 @@ void CClient::InitInterfaces()
|
||||||
|
|
||||||
m_Friends.Init();
|
m_Friends.Init();
|
||||||
m_Foes.Init(true);
|
m_Foes.Init(true);
|
||||||
|
|
||||||
IOHANDLE newsFile = m_pStorage->OpenFile("ddnet-news.txt", IOFLAG_READ, IStorage::TYPE_SAVE);
|
|
||||||
if (newsFile)
|
|
||||||
{
|
|
||||||
io_read(newsFile, m_aNews, NEWS_SIZE);
|
|
||||||
io_close(newsFile);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CClient::Run()
|
void CClient::Run()
|
||||||
|
@ -2821,8 +2687,10 @@ void CClient::Run()
|
||||||
m_Fifo.Init(m_pConsole, g_Config.m_ClInputFifo, CFGFLAG_CLIENT);
|
m_Fifo.Init(m_pConsole, g_Config.m_ClInputFifo, CFGFLAG_CLIENT);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RequestDDNetSrvList();
|
// loads the existing ddnet-info.json file if it exists
|
||||||
RequestDDNetRanks();
|
LoadDDNetInfo();
|
||||||
|
// but still request the new one from server
|
||||||
|
RequestDDNetInfo();
|
||||||
|
|
||||||
bool LastD = false;
|
bool LastD = false;
|
||||||
bool LastQ = false;
|
bool LastQ = false;
|
||||||
|
@ -2835,9 +2703,6 @@ void CClient::Run()
|
||||||
{
|
{
|
||||||
set_new_tick();
|
set_new_tick();
|
||||||
|
|
||||||
//
|
|
||||||
VersionUpdate();
|
|
||||||
|
|
||||||
// handle pending connects
|
// handle pending connects
|
||||||
if(m_aCmdConnect[0])
|
if(m_aCmdConnect[0])
|
||||||
{
|
{
|
||||||
|
@ -3754,38 +3619,16 @@ bool CClient::RaceRecordIsRecording()
|
||||||
return m_DemoRecorder[RECORDER_RACE].IsRecording();
|
return m_DemoRecorder[RECORDER_RACE].IsRecording();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CClient::RequestDDNetSrvList()
|
void CClient::RequestDDNetInfo()
|
||||||
{
|
|
||||||
// request ddnet server list
|
|
||||||
// generate new token
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
m_aDDNetSrvListToken[i] = rand()&0xff;
|
|
||||||
m_DDNetSrvListTokenSet = true;
|
|
||||||
|
|
||||||
char aData[sizeof(VERSIONSRV_GETDDNETLIST)+4];
|
|
||||||
mem_copy(aData, VERSIONSRV_GETDDNETLIST, sizeof(VERSIONSRV_GETDDNETLIST));
|
|
||||||
mem_copy(aData+sizeof(VERSIONSRV_GETDDNETLIST), m_aDDNetSrvListToken, 4); // add token
|
|
||||||
|
|
||||||
CNetChunk Packet;
|
|
||||||
mem_zero(&Packet, sizeof(Packet));
|
|
||||||
Packet.m_ClientID = -1;
|
|
||||||
Packet.m_Address = m_VersionInfo.m_VersionServeraddr.m_Addr;
|
|
||||||
Packet.m_pData = aData;
|
|
||||||
Packet.m_DataSize = sizeof(VERSIONSRV_GETDDNETLIST)+4;
|
|
||||||
Packet.m_Flags = NETSENDFLAG_CONNLESS;
|
|
||||||
m_NetClient[g_Config.m_ClDummy].Send(&Packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CClient::RequestDDNetRanks()
|
|
||||||
{
|
{
|
||||||
char aUrl[256];
|
char aUrl[256];
|
||||||
char aEscaped[128];
|
char aEscaped[128];
|
||||||
|
|
||||||
Fetcher()->Escape(aEscaped, sizeof(aEscaped), g_Config.m_PlayerName);
|
Fetcher()->Escape(aEscaped, sizeof(aEscaped), g_Config.m_PlayerName);
|
||||||
str_format(aUrl, sizeof(aUrl), "https://ddnet.tw/players/?json=%s", aEscaped);
|
str_format(aUrl, sizeof(aUrl), "https://info.ddnet.tw/info?name=%s", aEscaped);
|
||||||
|
|
||||||
m_pDDNetRanksTask = new CFetchTask(true, /*UseDDNetCA*/ true);
|
m_pDDNetInfoTask = new CFetchTask(true, /*UseDDNetCA*/ true);
|
||||||
Fetcher()->QueueAdd(m_pDDNetRanksTask, aUrl, "ddnet-ranks.json.tmp", IStorage::TYPE_SAVE);
|
Fetcher()->QueueAdd(m_pDDNetInfoTask, aUrl, "ddnet-info.json.tmp", IStorage::TYPE_SAVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CClient::GetPredictionTime()
|
int CClient::GetPredictionTime()
|
||||||
|
|
|
@ -80,7 +80,6 @@ class CClient : public IClient, public CDemoPlayer::IListener
|
||||||
class CUpdater m_Updater;
|
class CUpdater m_Updater;
|
||||||
class CFriends m_Friends;
|
class CFriends m_Friends;
|
||||||
class CFriends m_Foes;
|
class CFriends m_Foes;
|
||||||
class CMapChecker m_MapChecker;
|
|
||||||
|
|
||||||
char m_aServerAddressStr[256];
|
char m_aServerAddressStr[256];
|
||||||
|
|
||||||
|
@ -135,7 +134,8 @@ class CClient : public IClient, public CDemoPlayer::IListener
|
||||||
int m_MapdownloadCrc;
|
int m_MapdownloadCrc;
|
||||||
int m_MapdownloadAmount;
|
int m_MapdownloadAmount;
|
||||||
int m_MapdownloadTotalsize;
|
int m_MapdownloadTotalsize;
|
||||||
CFetchTask *m_pDDNetRanksTask;
|
|
||||||
|
CFetchTask *m_pDDNetInfoTask;
|
||||||
|
|
||||||
// time
|
// time
|
||||||
CSmoothTime m_GameTime[2];
|
CSmoothTime m_GameTime[2];
|
||||||
|
@ -195,9 +195,6 @@ class CClient : public IClient, public CDemoPlayer::IListener
|
||||||
void GraphicsThread();
|
void GraphicsThread();
|
||||||
vec3 GetColorV3(int v);
|
vec3 GetColorV3(int v);
|
||||||
|
|
||||||
char m_aDDNetSrvListToken[4];
|
|
||||||
bool m_DDNetSrvListTokenSet;
|
|
||||||
|
|
||||||
#if defined(CONF_FAMILY_UNIX)
|
#if defined(CONF_FAMILY_UNIX)
|
||||||
CFifo m_Fifo;
|
CFifo m_Fifo;
|
||||||
#endif
|
#endif
|
||||||
|
@ -244,8 +241,6 @@ public:
|
||||||
virtual bool InputExists(int Tick);
|
virtual bool InputExists(int Tick);
|
||||||
|
|
||||||
const char *LatestVersion();
|
const char *LatestVersion();
|
||||||
void VersionUpdate();
|
|
||||||
void CheckVersionUpdate();
|
|
||||||
|
|
||||||
// ------ state handling -----
|
// ------ state handling -----
|
||||||
void SetState(int s);
|
void SetState(int s);
|
||||||
|
@ -299,8 +294,11 @@ public:
|
||||||
|
|
||||||
void ResetMapDownload();
|
void ResetMapDownload();
|
||||||
void FinishMapDownload();
|
void FinishMapDownload();
|
||||||
void ResetDDNetRanks();
|
|
||||||
void FinishDDNetRanks();
|
void RequestDDNetInfo();
|
||||||
|
void ResetDDNetInfo();
|
||||||
|
void FinishDDNetInfo();
|
||||||
|
void LoadDDNetInfo();
|
||||||
|
|
||||||
virtual CFetchTask *MapDownloadTask() { return m_pMapdownloadTask; }
|
virtual CFetchTask *MapDownloadTask() { return m_pMapdownloadTask; }
|
||||||
virtual const char *MapDownloadName() { return m_aMapdownloadName; }
|
virtual const char *MapDownloadName() { return m_aMapdownloadName; }
|
||||||
|
@ -394,8 +392,6 @@ public:
|
||||||
virtual void DemoSliceEnd();
|
virtual void DemoSliceEnd();
|
||||||
virtual void DemoSlice(const char *pDstPath, CLIENTFUNC_FILTER pfnFilter, void *pUser);
|
virtual void DemoSlice(const char *pDstPath, CLIENTFUNC_FILTER pfnFilter, void *pUser);
|
||||||
|
|
||||||
void RequestDDNetSrvList();
|
|
||||||
void RequestDDNetRanks();
|
|
||||||
bool EditorHasUnsavedData() { return m_pEditor->HasUnsavedData(); }
|
bool EditorHasUnsavedData() { return m_pEditor->HasUnsavedData(); }
|
||||||
|
|
||||||
virtual IFriends* Foes() {return &m_Foes; }
|
virtual IFriends* Foes() {return &m_Foes; }
|
||||||
|
|
|
@ -63,7 +63,13 @@ CServerBrowser::CServerBrowser()
|
||||||
m_BroadcastTime = 0;
|
m_BroadcastTime = 0;
|
||||||
m_BroadcastExtraToken = -1;
|
m_BroadcastExtraToken = -1;
|
||||||
|
|
||||||
m_pDDNetRanks = 0;
|
m_pDDNetInfo = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CServerBrowser::~CServerBrowser()
|
||||||
|
{
|
||||||
|
if(m_pDDNetInfo)
|
||||||
|
json_value_free(m_pDDNetInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CServerBrowser::SetBaseInfo(class CNetClient *pClient, const char *pNetVersion)
|
void CServerBrowser::SetBaseInfo(class CNetClient *pClient, const char *pNetVersion)
|
||||||
|
@ -550,7 +556,6 @@ void CServerBrowser::Refresh(int Type)
|
||||||
// next token
|
// next token
|
||||||
m_CurrentToken = (m_CurrentToken+1)&0xff;
|
m_CurrentToken = (m_CurrentToken+1)&0xff;
|
||||||
|
|
||||||
//
|
|
||||||
m_ServerlistType = Type;
|
m_ServerlistType = Type;
|
||||||
|
|
||||||
if(Type == IServerBrowser::TYPE_LAN)
|
if(Type == IServerBrowser::TYPE_LAN)
|
||||||
|
@ -593,9 +598,6 @@ void CServerBrowser::Refresh(int Type)
|
||||||
}
|
}
|
||||||
else if(Type == IServerBrowser::TYPE_DDNET)
|
else if(Type == IServerBrowser::TYPE_DDNET)
|
||||||
{
|
{
|
||||||
LoadDDNetServers();
|
|
||||||
LoadDDNetRanks();
|
|
||||||
|
|
||||||
// remove unknown elements of exclude list
|
// remove unknown elements of exclude list
|
||||||
DDNetCountryFilterClean();
|
DDNetCountryFilterClean();
|
||||||
DDNetTypeFilterClean();
|
DDNetTypeFilterClean();
|
||||||
|
@ -926,31 +928,23 @@ void CServerBrowser::RemoveFavorite(const NETADDR &Addr)
|
||||||
|
|
||||||
void CServerBrowser::LoadDDNetServers()
|
void CServerBrowser::LoadDDNetServers()
|
||||||
{
|
{
|
||||||
|
if (!m_pDDNetInfo)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// parse JSON
|
||||||
|
const json_value *pServers = json_object_get(m_pDDNetInfo, "servers");
|
||||||
|
|
||||||
|
if (!pServers || pServers->type != json_array)
|
||||||
|
return;
|
||||||
|
|
||||||
// reset servers / countries
|
// reset servers / countries
|
||||||
m_NumDDNetCountries = 0;
|
m_NumDDNetCountries = 0;
|
||||||
m_NumDDNetTypes = 0;
|
m_NumDDNetTypes = 0;
|
||||||
|
|
||||||
// load ddnet server list
|
for (int i = 0; i < json_array_length(pServers) && m_NumDDNetCountries < MAX_DDNET_COUNTRIES; i++)
|
||||||
IStorage *pStorage = Kernel()->RequestInterface<IStorage>();
|
|
||||||
IOHANDLE File = pStorage->OpenFile("ddnet-servers.json", IOFLAG_READ, IStorage::TYPE_ALL);
|
|
||||||
|
|
||||||
if(!File)
|
|
||||||
return;
|
|
||||||
|
|
||||||
char aBuf[4096*4];
|
|
||||||
mem_zero(aBuf, sizeof(aBuf));
|
|
||||||
io_read(File, aBuf, sizeof(aBuf));
|
|
||||||
io_close(File);
|
|
||||||
|
|
||||||
// parse JSON
|
|
||||||
json_value *pCountries = json_parse(aBuf, sizeof(aBuf));
|
|
||||||
|
|
||||||
if (pCountries && pCountries->type == json_array)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < json_array_length(pCountries) && m_NumDDNetCountries < MAX_DDNET_COUNTRIES; i++)
|
|
||||||
{
|
{
|
||||||
// pSrv - { name, flagId, servers }
|
// pSrv - { name, flagId, servers }
|
||||||
const json_value *pSrv = json_array_get(pCountries, i);
|
const json_value *pSrv = json_array_get(pServers, i);
|
||||||
const json_value *pTypes = json_object_get(pSrv, "servers");
|
const json_value *pTypes = json_object_get(pSrv, "servers");
|
||||||
const json_value *pName = json_object_get(pSrv, "name");
|
const json_value *pName = json_object_get(pSrv, "name");
|
||||||
const json_value *pFlagID = json_object_get(pSrv, "flagId");
|
const json_value *pFlagID = json_object_get(pSrv, "flagId");
|
||||||
|
@ -975,6 +969,12 @@ void CServerBrowser::LoadDDNetServers()
|
||||||
const char *pType = pTypes->u.object.values[t].name;
|
const char *pType = pTypes->u.object.values[t].name;
|
||||||
const json_value *pAddrs = pTypes->u.object.values[t].value;
|
const json_value *pAddrs = pTypes->u.object.values[t].value;
|
||||||
|
|
||||||
|
if (pAddrs->type != json_array)
|
||||||
|
{
|
||||||
|
dbg_msg("client_srvbrowse", "invalid attributes");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// add type
|
// add type
|
||||||
if(json_array_length(pAddrs) > 0 && m_NumDDNetTypes < MAX_DDNET_TYPES)
|
if(json_array_length(pAddrs) > 0 && m_NumDDNetTypes < MAX_DDNET_TYPES)
|
||||||
{
|
{
|
||||||
|
@ -995,6 +995,11 @@ void CServerBrowser::LoadDDNetServers()
|
||||||
for (int g = 0; g < json_array_length(pAddrs); g++, pCntr->m_NumServers++)
|
for (int g = 0; g < json_array_length(pAddrs); g++, pCntr->m_NumServers++)
|
||||||
{
|
{
|
||||||
const json_value *pAddr = json_array_get(pAddrs, g);
|
const json_value *pAddr = json_array_get(pAddrs, g);
|
||||||
|
if (pAddr->type != json_string)
|
||||||
|
{
|
||||||
|
dbg_msg("client_srvbrowse", "invalid attributes");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const char *pStr = json_string_get(pAddr);
|
const char *pStr = json_string_get(pAddr);
|
||||||
net_addr_from_str(&pCntr->m_aServers[pCntr->m_NumServers], pStr);
|
net_addr_from_str(&pCntr->m_aServers[pCntr->m_NumServers], pStr);
|
||||||
str_copy(pCntr->m_aTypes[pCntr->m_NumServers], pType, sizeof(pCntr->m_aTypes[pCntr->m_NumServers]));
|
str_copy(pCntr->m_aTypes[pCntr->m_NumServers], pType, sizeof(pCntr->m_aTypes[pCntr->m_NumServers]));
|
||||||
|
@ -1003,17 +1008,46 @@ void CServerBrowser::LoadDDNetServers()
|
||||||
|
|
||||||
m_NumDDNetCountries++;
|
m_NumDDNetCountries++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (pCountries)
|
|
||||||
json_value_free(pCountries);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CServerBrowser::LoadDDNetRanks()
|
void CServerBrowser::LoadDDNetRanks()
|
||||||
{
|
{
|
||||||
// load ddnet ranks list
|
for(int i = 0; i < m_NumServers; i++)
|
||||||
|
{
|
||||||
|
if(m_ppServerlist[i]->m_Info.m_aMap[0])
|
||||||
|
m_ppServerlist[i]->m_Info.m_HasRank = HasRank(m_ppServerlist[i]->m_Info.m_aMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int CServerBrowser::HasRank(const char *pMap)
|
||||||
|
{
|
||||||
|
if(m_ServerlistType != IServerBrowser::TYPE_DDNET || !m_pDDNetInfo)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
const json_value *pDDNetRanks = json_object_get(m_pDDNetInfo, "maps");
|
||||||
|
|
||||||
|
if(!pDDNetRanks || pDDNetRanks->type != json_array)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < json_array_length(pDDNetRanks); i++)
|
||||||
|
{
|
||||||
|
const json_value *pJson = json_array_get(pDDNetRanks, i);
|
||||||
|
if(!pJson || pJson->type != json_string)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const char *pStr = json_string_get(pJson);
|
||||||
|
|
||||||
|
if(str_comp(pMap, pStr) == 0)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CServerBrowser::LoadDDNetInfoJson()
|
||||||
|
{
|
||||||
IStorage *pStorage = Kernel()->RequestInterface<IStorage>();
|
IStorage *pStorage = Kernel()->RequestInterface<IStorage>();
|
||||||
IOHANDLE File = pStorage->OpenFile("ddnet-ranks.json", IOFLAG_READ, IStorage::TYPE_ALL);
|
IOHANDLE File = pStorage->OpenFile("ddnet-info.json", IOFLAG_READ, IStorage::TYPE_ALL);
|
||||||
|
|
||||||
if(!File)
|
if(!File)
|
||||||
return;
|
return;
|
||||||
|
@ -1031,34 +1065,31 @@ void CServerBrowser::LoadDDNetRanks()
|
||||||
io_read(File, pBuf, Length);
|
io_read(File, pBuf, Length);
|
||||||
io_close(File);
|
io_close(File);
|
||||||
|
|
||||||
m_pDDNetRanks = json_parse(pBuf, Length);
|
if(m_pDDNetInfo)
|
||||||
|
json_value_free(m_pDDNetInfo);
|
||||||
|
|
||||||
|
m_pDDNetInfo = json_parse(pBuf, Length);
|
||||||
|
|
||||||
mem_free(pBuf);
|
mem_free(pBuf);
|
||||||
|
|
||||||
for(int i = 0; i < m_NumServers; i++)
|
if(m_pDDNetInfo->type != json_object)
|
||||||
{
|
{
|
||||||
if(m_ppServerlist[i]->m_Info.m_aMap[0])
|
json_value_free(m_pDDNetInfo);
|
||||||
m_ppServerlist[i]->m_Info.m_HasRank = HasRank(m_ppServerlist[i]->m_Info.m_aMap);
|
m_pDDNetInfo = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int CServerBrowser::HasRank(const char *pMap)
|
const json_value *CServerBrowser::LoadDDNetInfo()
|
||||||
{
|
{
|
||||||
if(m_ServerlistType != IServerBrowser::TYPE_DDNET)
|
LoadDDNetInfoJson();
|
||||||
return -1;
|
LoadDDNetServers();
|
||||||
|
|
||||||
if(!m_pDDNetRanks)
|
if(m_NumServers == 0)
|
||||||
return -1;
|
Refresh(m_ServerlistType);
|
||||||
|
else
|
||||||
|
LoadDDNetRanks();
|
||||||
|
|
||||||
for (int i = 0; i < json_array_length(m_pDDNetRanks); i++)
|
return m_pDDNetInfo;
|
||||||
{
|
|
||||||
const json_value *pJson = json_array_get(m_pDDNetRanks, i);
|
|
||||||
const char *pStr = json_string_get(pJson);
|
|
||||||
if(str_comp(pMap, pStr) == 0)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CServerBrowser::IsRefreshing() const
|
bool CServerBrowser::IsRefreshing() const
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#define ENGINE_CLIENT_SERVERBROWSER_H
|
#define ENGINE_CLIENT_SERVERBROWSER_H
|
||||||
|
|
||||||
#include <engine/serverbrowser.h>
|
#include <engine/serverbrowser.h>
|
||||||
|
#include <engine/shared/memheap.h>
|
||||||
#include <engine/external/json-parser/json.h>
|
#include <engine/external/json-parser/json.h>
|
||||||
|
|
||||||
class CServerBrowser : public IServerBrowser
|
class CServerBrowser : public IServerBrowser
|
||||||
|
@ -58,6 +59,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
CServerBrowser();
|
CServerBrowser();
|
||||||
|
virtual ~CServerBrowser();
|
||||||
|
|
||||||
// interface functions
|
// interface functions
|
||||||
void Refresh(int Type);
|
void Refresh(int Type);
|
||||||
|
@ -74,8 +76,10 @@ public:
|
||||||
void AddFavorite(const NETADDR &Addr);
|
void AddFavorite(const NETADDR &Addr);
|
||||||
void RemoveFavorite(const NETADDR &Addr);
|
void RemoveFavorite(const NETADDR &Addr);
|
||||||
|
|
||||||
void LoadDDNetServers();
|
|
||||||
void LoadDDNetRanks();
|
void LoadDDNetRanks();
|
||||||
|
void LoadDDNetServers();
|
||||||
|
void LoadDDNetInfoJson();
|
||||||
|
const json_value *LoadDDNetInfo();
|
||||||
int HasRank(const char *pMap);
|
int HasRank(const char *pMap);
|
||||||
int NumDDNetCountries() { return m_NumDDNetCountries; };
|
int NumDDNetCountries() { return m_NumDDNetCountries; };
|
||||||
int GetDDNetCountryFlag(int Index) { return m_aDDNetCountries[Index].m_FlagID; };
|
int GetDDNetCountryFlag(int Index) { return m_aDDNetCountries[Index].m_FlagID; };
|
||||||
|
@ -121,7 +125,8 @@ private:
|
||||||
|
|
||||||
char m_aDDNetTypes[MAX_DDNET_TYPES][32];
|
char m_aDDNetTypes[MAX_DDNET_TYPES][32];
|
||||||
int m_NumDDNetTypes;
|
int m_NumDDNetTypes;
|
||||||
json_value *m_pDDNetRanks;
|
|
||||||
|
json_value *m_pDDNetInfo;
|
||||||
|
|
||||||
CServerEntry *m_aServerlistIp[256]; // ip hash list
|
CServerEntry *m_aServerlistIp[256]; // ip hash list
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
#include <engine/shared/demo.h>
|
#include <engine/shared/demo.h>
|
||||||
#include <engine/shared/econ.h>
|
#include <engine/shared/econ.h>
|
||||||
#include <engine/shared/filecollection.h>
|
#include <engine/shared/filecollection.h>
|
||||||
#include <engine/shared/mapchecker.h>
|
|
||||||
#include <engine/shared/netban.h>
|
#include <engine/shared/netban.h>
|
||||||
#include <engine/shared/network.h>
|
#include <engine/shared/network.h>
|
||||||
#include <engine/shared/packer.h>
|
#include <engine/shared/packer.h>
|
||||||
|
@ -1628,22 +1627,10 @@ char *CServer::GetMapName()
|
||||||
|
|
||||||
int CServer::LoadMap(const char *pMapName)
|
int CServer::LoadMap(const char *pMapName)
|
||||||
{
|
{
|
||||||
//DATAFILE *df;
|
|
||||||
char aBuf[512];
|
char aBuf[512];
|
||||||
str_format(aBuf, sizeof(aBuf), "maps/%s.map", pMapName);
|
str_format(aBuf, sizeof(aBuf), "maps/%s.map", pMapName);
|
||||||
GameServer()->OnMapChange(aBuf, sizeof(aBuf));
|
GameServer()->OnMapChange(aBuf, sizeof(aBuf));
|
||||||
|
|
||||||
/*df = datafile_load(buf);
|
|
||||||
if(!df)
|
|
||||||
return 0;*/
|
|
||||||
|
|
||||||
// check for valid standard map
|
|
||||||
if(!m_MapChecker.ReadAndValidateMap(Storage(), aBuf, IStorage::TYPE_ALL))
|
|
||||||
{
|
|
||||||
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "mapchecker", "invalid standard map");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!m_pMap->Load(aBuf))
|
if(!m_pMap->Load(aBuf))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -1671,7 +1658,6 @@ int CServer::LoadMap(const char *pMapName)
|
||||||
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aBufMsg);
|
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aBufMsg);
|
||||||
|
|
||||||
str_copy(m_aCurrentMap, pMapName, sizeof(m_aCurrentMap));
|
str_copy(m_aCurrentMap, pMapName, sizeof(m_aCurrentMap));
|
||||||
//map_set(df);
|
|
||||||
|
|
||||||
// load complete map into memory for download
|
// load complete map into memory for download
|
||||||
{
|
{
|
||||||
|
@ -1704,7 +1690,6 @@ int CServer::Run()
|
||||||
g_UuidManager.DebugDump();
|
g_UuidManager.DebugDump();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
m_PrintCBIndex = Console()->RegisterPrintCallback(g_Config.m_ConsoleOutputLevel, SendRconLineAuthed, this);
|
m_PrintCBIndex = Console()->RegisterPrintCallback(g_Config.m_ConsoleOutputLevel, SendRconLineAuthed, this);
|
||||||
|
|
||||||
// load map
|
// load map
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
#include <engine/server/register.h>
|
#include <engine/server/register.h>
|
||||||
#include <engine/shared/console.h>
|
#include <engine/shared/console.h>
|
||||||
#include <base/math.h>
|
#include <base/math.h>
|
||||||
#include <engine/shared/mapchecker.h>
|
|
||||||
#include <engine/shared/econ.h>
|
#include <engine/shared/econ.h>
|
||||||
#include <engine/shared/fifo.h>
|
#include <engine/shared/fifo.h>
|
||||||
#include <engine/shared/netban.h>
|
#include <engine/shared/netban.h>
|
||||||
|
@ -202,7 +201,6 @@ public:
|
||||||
|
|
||||||
CDemoRecorder m_aDemoRecorder[MAX_CLIENTS+1];
|
CDemoRecorder m_aDemoRecorder[MAX_CLIENTS+1];
|
||||||
CRegister m_Register;
|
CRegister m_Register;
|
||||||
CMapChecker m_MapChecker;
|
|
||||||
CAuthManager m_AuthManager;
|
CAuthManager m_AuthManager;
|
||||||
|
|
||||||
int m_RconRestrict;
|
int m_RconRestrict;
|
||||||
|
|
|
@ -1,107 +0,0 @@
|
||||||
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
|
||||||
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
|
||||||
#include <base/math.h>
|
|
||||||
#include <base/system.h>
|
|
||||||
|
|
||||||
#include <engine/storage.h>
|
|
||||||
|
|
||||||
#include <versionsrv/versionsrv.h>
|
|
||||||
#include <versionsrv/mapversions.h>
|
|
||||||
|
|
||||||
#include "datafile.h"
|
|
||||||
#include "memheap.h"
|
|
||||||
#include "mapchecker.h"
|
|
||||||
|
|
||||||
CMapChecker::CMapChecker()
|
|
||||||
{
|
|
||||||
Init();
|
|
||||||
SetDefaults();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMapChecker::Init()
|
|
||||||
{
|
|
||||||
m_Whitelist.Reset();
|
|
||||||
m_pFirst = 0;
|
|
||||||
m_RemoveDefaultList = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMapChecker::SetDefaults()
|
|
||||||
{
|
|
||||||
AddMaplist(s_aMapVersionList, s_NumMapVersionItems);
|
|
||||||
m_RemoveDefaultList = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMapChecker::AddMaplist(CMapVersion *pMaplist, int Num)
|
|
||||||
{
|
|
||||||
if(m_RemoveDefaultList)
|
|
||||||
Init();
|
|
||||||
|
|
||||||
for(int i = 0; i < Num; ++i)
|
|
||||||
{
|
|
||||||
CWhitelistEntry *pEntry = (CWhitelistEntry *)m_Whitelist.Allocate(sizeof(CWhitelistEntry));
|
|
||||||
pEntry->m_pNext = m_pFirst;
|
|
||||||
m_pFirst = pEntry;
|
|
||||||
|
|
||||||
str_copy(pEntry->m_aMapName, pMaplist[i].m_aName, sizeof(pEntry->m_aMapName));
|
|
||||||
pEntry->m_MapCrc = (pMaplist[i].m_aCrc[0]<<24) | (pMaplist[i].m_aCrc[1]<<16) | (pMaplist[i].m_aCrc[2]<<8) | pMaplist[i].m_aCrc[3];
|
|
||||||
pEntry->m_MapSize = (pMaplist[i].m_aSize[0]<<24) | (pMaplist[i].m_aSize[1]<<16) | (pMaplist[i].m_aSize[2]<<8) | pMaplist[i].m_aSize[3];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CMapChecker::IsMapValid(const char *pMapName, unsigned MapCrc, unsigned MapSize)
|
|
||||||
{
|
|
||||||
bool StandardMap = false;
|
|
||||||
for(CWhitelistEntry *pCurrent = m_pFirst; pCurrent; pCurrent = pCurrent->m_pNext)
|
|
||||||
{
|
|
||||||
if(str_comp(pCurrent->m_aMapName, pMapName) == 0)
|
|
||||||
{
|
|
||||||
StandardMap = true;
|
|
||||||
if(pCurrent->m_MapCrc == MapCrc && pCurrent->m_MapSize == MapSize)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return StandardMap?false:true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CMapChecker::ReadAndValidateMap(IStorage *pStorage, const char *pFilename, int StorageType)
|
|
||||||
{
|
|
||||||
bool LoadedMapInfo = false;
|
|
||||||
bool StandardMap = false;
|
|
||||||
unsigned MapCrc = 0;
|
|
||||||
unsigned MapSize = 0;
|
|
||||||
|
|
||||||
// extract map name
|
|
||||||
char aMapName[MAX_MAP_LENGTH];
|
|
||||||
const char *pExtractedName = pFilename;
|
|
||||||
const char *pEnd = 0;
|
|
||||||
for(const char *pSrc = pFilename; *pSrc; ++pSrc)
|
|
||||||
{
|
|
||||||
if(*pSrc == '/' || *pSrc == '\\')
|
|
||||||
pExtractedName = pSrc+1;
|
|
||||||
else if(*pSrc == '.')
|
|
||||||
pEnd = pSrc;
|
|
||||||
}
|
|
||||||
int Length = (int)(pEnd - pExtractedName);
|
|
||||||
if(Length <= 0 || Length >= MAX_MAP_LENGTH)
|
|
||||||
return true;
|
|
||||||
str_copy(aMapName, pExtractedName, min((int)MAX_MAP_LENGTH, (int)(pEnd-pExtractedName+1)));
|
|
||||||
|
|
||||||
// check for valid map
|
|
||||||
for(CWhitelistEntry *pCurrent = m_pFirst; pCurrent; pCurrent = pCurrent->m_pNext)
|
|
||||||
{
|
|
||||||
if(str_comp(pCurrent->m_aMapName, aMapName) == 0)
|
|
||||||
{
|
|
||||||
StandardMap = true;
|
|
||||||
if(!LoadedMapInfo)
|
|
||||||
{
|
|
||||||
if(!CDataFileReader::GetCrcSize(pStorage, pFilename, StorageType, &MapCrc, &MapSize))
|
|
||||||
return true;
|
|
||||||
LoadedMapInfo = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(pCurrent->m_MapCrc == MapCrc && pCurrent->m_MapSize == MapSize)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return StandardMap?false:true;
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
|
||||||
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
|
||||||
#ifndef ENGINE_SHARED_MAPCHECKER_H
|
|
||||||
#define ENGINE_SHARED_MAPCHECKER_H
|
|
||||||
|
|
||||||
#include "memheap.h"
|
|
||||||
|
|
||||||
class CMapChecker
|
|
||||||
{
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
MAX_MAP_LENGTH=8,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CWhitelistEntry
|
|
||||||
{
|
|
||||||
char m_aMapName[MAX_MAP_LENGTH];
|
|
||||||
unsigned m_MapCrc;
|
|
||||||
unsigned m_MapSize;
|
|
||||||
CWhitelistEntry *m_pNext;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CHeap m_Whitelist;
|
|
||||||
CWhitelistEntry *m_pFirst;
|
|
||||||
|
|
||||||
bool m_RemoveDefaultList;
|
|
||||||
|
|
||||||
void Init();
|
|
||||||
void SetDefaults();
|
|
||||||
|
|
||||||
public:
|
|
||||||
CMapChecker();
|
|
||||||
void AddMaplist(struct CMapVersion *pMaplist, int Num);
|
|
||||||
bool IsMapValid(const char *pMapName, unsigned MapCrc, unsigned MapSize);
|
|
||||||
bool ReadAndValidateMap(class IStorage *pStorage, const char *pFilename, int StorageType);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -31,7 +31,6 @@
|
||||||
#include <game/client/lineinput.h>
|
#include <game/client/lineinput.h>
|
||||||
#include <game/localization.h>
|
#include <game/localization.h>
|
||||||
#include <mastersrv/mastersrv.h>
|
#include <mastersrv/mastersrv.h>
|
||||||
#include <versionsrv/versionsrv.h>
|
|
||||||
|
|
||||||
#include "countryflags.h"
|
#include "countryflags.h"
|
||||||
#include "menus.h"
|
#include "menus.h"
|
||||||
|
@ -696,7 +695,10 @@ int CMenus::RenderMenubar(CUIRect r)
|
||||||
if(DoButton_MenuTab(&s_DDNetButton, Localize("DDNet"), m_ActivePage==PAGE_DDNET, &Button, CUI::CORNER_TR))
|
if(DoButton_MenuTab(&s_DDNetButton, Localize("DDNet"), m_ActivePage==PAGE_DDNET, &Button, CUI::CORNER_TR))
|
||||||
{
|
{
|
||||||
if(ServerBrowser()->GetCurrentType() != IServerBrowser::TYPE_DDNET)
|
if(ServerBrowser()->GetCurrentType() != IServerBrowser::TYPE_DDNET)
|
||||||
|
{
|
||||||
|
Client()->RequestDDNetInfo();
|
||||||
ServerBrowser()->Refresh(IServerBrowser::TYPE_DDNET);
|
ServerBrowser()->Refresh(IServerBrowser::TYPE_DDNET);
|
||||||
|
}
|
||||||
NewPage = PAGE_DDNET;
|
NewPage = PAGE_DDNET;
|
||||||
m_DoubleClickIndex = -1;
|
m_DoubleClickIndex = -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1397,8 +1397,7 @@ void CMenus::RenderServerbrowser(CUIRect MainView)
|
||||||
else if(g_Config.m_UiPage == PAGE_DDNET)
|
else if(g_Config.m_UiPage == PAGE_DDNET)
|
||||||
{
|
{
|
||||||
// start a new serverlist request
|
// start a new serverlist request
|
||||||
Client()->RequestDDNetSrvList();
|
Client()->RequestDDNetInfo();
|
||||||
Client()->RequestDDNetRanks();
|
|
||||||
ServerBrowser()->Refresh(IServerBrowser::TYPE_DDNET);
|
ServerBrowser()->Refresh(IServerBrowser::TYPE_DDNET);
|
||||||
}
|
}
|
||||||
m_DoubleClickIndex = -1;
|
m_DoubleClickIndex = -1;
|
||||||
|
|
|
@ -2155,7 +2155,7 @@ void CMenus::RenderSettingsDDNet(CUIRect MainView)
|
||||||
g_Config.m_ClHttpMapDownload ^= 1;
|
g_Config.m_ClHttpMapDownload ^= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Updater
|
// Updater
|
||||||
#if defined(CONF_FAMILY_WINDOWS) || (defined(CONF_PLATFORM_LINUX) && !defined(__ANDROID__))
|
#if defined(CONF_FAMILY_WINDOWS) || (defined(CONF_PLATFORM_LINUX) && !defined(__ANDROID__))
|
||||||
{
|
{
|
||||||
Left.HSplitTop(20.0f, &Label, &Left);
|
Left.HSplitTop(20.0f, &Label, &Left);
|
||||||
|
@ -2163,7 +2163,7 @@ void CMenus::RenderSettingsDDNet(CUIRect MainView)
|
||||||
char aBuf[256];
|
char aBuf[256];
|
||||||
int State = Updater()->GetCurrentState();
|
int State = Updater()->GetCurrentState();
|
||||||
|
|
||||||
//Update Button
|
// Update Button
|
||||||
if(NeedUpdate && State <= IUpdater::CLEAN)
|
if(NeedUpdate && State <= IUpdater::CLEAN)
|
||||||
{
|
{
|
||||||
str_format(aBuf, sizeof(aBuf), Localize("DDNet %s is available:"), Client()->LatestVersion());
|
str_format(aBuf, sizeof(aBuf), Localize("DDNet %s is available:"), Client()->LatestVersion());
|
||||||
|
@ -2188,7 +2188,7 @@ void CMenus::RenderSettingsDDNet(CUIRect MainView)
|
||||||
static int s_ButtonUpdate = 0;
|
static int s_ButtonUpdate = 0;
|
||||||
if(DoButton_Menu(&s_ButtonUpdate, Localize("Check now"), 0, &Button))
|
if(DoButton_Menu(&s_ButtonUpdate, Localize("Check now"), 0, &Button))
|
||||||
{
|
{
|
||||||
Client()->CheckVersionUpdate();
|
Client()->RequestDDNetInfo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UI()->DoLabelScaled(&Label, aBuf, 14.0f, -1);
|
UI()->DoLabelScaled(&Label, aBuf, 14.0f, -1);
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
|
||||||
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
|
||||||
#ifndef VERSIONSRV_MAPVERSIONS_H
|
|
||||||
#define VERSIONSRV_MAPVERSIONS_H
|
|
||||||
|
|
||||||
static CMapVersion s_aMapVersionList[] = {
|
|
||||||
{"ctf1", {0x06, 0xb5, 0xf1, 0x17}, {0x00, 0x00, 0x12, 0x38}},
|
|
||||||
{"ctf2", {0x27, 0xbc, 0x5e, 0xac}, {0x00, 0x00, 0x64, 0x1a}},
|
|
||||||
{"ctf3", {0xa3, 0x73, 0x9d, 0x41}, {0x00, 0x00, 0x17, 0x0f}},
|
|
||||||
{"ctf4", {0xbe, 0x7c, 0x4d, 0xb9}, {0x00, 0x00, 0x2e, 0xfe}},
|
|
||||||
{"ctf5", {0xd9, 0x21, 0x29, 0xa0}, {0x00, 0x00, 0x2f, 0x4c}},
|
|
||||||
{"ctf6", {0x28, 0xc8, 0x43, 0x51}, {0x00, 0x00, 0x69, 0x2f}},
|
|
||||||
{"ctf7", {0x1d, 0x35, 0x98, 0x72}, {0x00, 0x00, 0x15, 0x87}},
|
|
||||||
{"dm1", {0xf2, 0x15, 0x9e, 0x6e}, {0x00, 0x00, 0x16, 0xad}},
|
|
||||||
{"dm2", {0x71, 0x83, 0x98, 0x78}, {0x00, 0x00, 0x21, 0xdf}},
|
|
||||||
{"dm6", {0x47, 0x4d, 0xa2, 0x35}, {0x00, 0x00, 0x1e, 0x95}},
|
|
||||||
{"dm7", {0x42, 0x6d, 0xa1, 0x67}, {0x00, 0x00, 0x27, 0x2a}},
|
|
||||||
{"dm8", {0x85, 0xf1, 0x1e, 0xd6}, {0x00, 0x00, 0x9e, 0xbd}},
|
|
||||||
{"dm9", {0x42, 0xd4, 0x77, 0x7e}, {0x00, 0x00, 0x20, 0x11}},
|
|
||||||
};
|
|
||||||
static const int s_NumMapVersionItems = sizeof(s_aMapVersionList)/sizeof(CMapVersion);
|
|
||||||
#endif
|
|
|
@ -1,240 +0,0 @@
|
||||||
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
|
||||||
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
|
||||||
#include <base/system.h>
|
|
||||||
|
|
||||||
#include <engine/shared/network.h>
|
|
||||||
|
|
||||||
#include <game/version.h>
|
|
||||||
|
|
||||||
#include "versionsrv.h"
|
|
||||||
#include "mapversions.h"
|
|
||||||
|
|
||||||
#include <zlib.h>
|
|
||||||
|
|
||||||
enum {
|
|
||||||
MAX_MAPS_PER_PACKET=48,
|
|
||||||
MAX_PACKETS=16,
|
|
||||||
MAX_MAPS=MAX_MAPS_PER_PACKET*MAX_PACKETS,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CPacketData
|
|
||||||
{
|
|
||||||
int m_Size;
|
|
||||||
struct {
|
|
||||||
unsigned char m_aHeader[sizeof(VERSIONSRV_MAPLIST)];
|
|
||||||
CMapVersion m_aMaplist[MAX_MAPS_PER_PACKET];
|
|
||||||
} m_Data;
|
|
||||||
};
|
|
||||||
|
|
||||||
CPacketData m_aPackets[MAX_PACKETS];
|
|
||||||
static int m_NumPackets = 0;
|
|
||||||
unsigned char m_aNews[NEWS_SIZE];
|
|
||||||
|
|
||||||
unsigned char m_aServerList[DDNETLIST_SIZE];
|
|
||||||
int m_ServerListPlainLength = 0;
|
|
||||||
int m_ServerListCompLength = 0;
|
|
||||||
bool m_ServerListLoaded = false;
|
|
||||||
|
|
||||||
static CNetClient g_NetOp; // main
|
|
||||||
|
|
||||||
void BuildPackets()
|
|
||||||
{
|
|
||||||
CMapVersion *pCurrent = &s_aMapVersionList[0];
|
|
||||||
int ServersLeft = s_NumMapVersionItems;
|
|
||||||
m_NumPackets = 0;
|
|
||||||
while(ServersLeft && m_NumPackets < MAX_PACKETS)
|
|
||||||
{
|
|
||||||
int Chunk = ServersLeft;
|
|
||||||
if(Chunk > MAX_MAPS_PER_PACKET)
|
|
||||||
Chunk = MAX_MAPS_PER_PACKET;
|
|
||||||
ServersLeft -= Chunk;
|
|
||||||
|
|
||||||
// copy header
|
|
||||||
mem_copy(m_aPackets[m_NumPackets].m_Data.m_aHeader, VERSIONSRV_MAPLIST, sizeof(VERSIONSRV_MAPLIST));
|
|
||||||
|
|
||||||
// copy map versions
|
|
||||||
for(int i = 0; i < Chunk; i++)
|
|
||||||
{
|
|
||||||
m_aPackets[m_NumPackets].m_Data.m_aMaplist[i] = *pCurrent;
|
|
||||||
pCurrent++;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_aPackets[m_NumPackets].m_Size = sizeof(VERSIONSRV_MAPLIST) + sizeof(CMapVersion)*Chunk;
|
|
||||||
|
|
||||||
m_NumPackets++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReadNews()
|
|
||||||
{
|
|
||||||
IOHANDLE NewsFile = io_open("news", IOFLAG_READ);
|
|
||||||
if (!NewsFile)
|
|
||||||
return;
|
|
||||||
|
|
||||||
io_read(NewsFile, m_aNews, NEWS_SIZE);
|
|
||||||
|
|
||||||
io_close(NewsFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReadServerList()
|
|
||||||
{
|
|
||||||
mem_zero(m_aServerList, sizeof(m_aServerList));
|
|
||||||
|
|
||||||
IOHANDLE File = io_open("serverlist.json", IOFLAG_READ);
|
|
||||||
if (!File)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int PlainLength = io_length(File);
|
|
||||||
char aPlain[16384];
|
|
||||||
|
|
||||||
io_read(File, aPlain, sizeof(aPlain));
|
|
||||||
io_close(File);
|
|
||||||
|
|
||||||
// compress
|
|
||||||
uLongf DstLen = DDNETLIST_SIZE;
|
|
||||||
|
|
||||||
if (compress((Bytef*)m_aServerList, &DstLen, (Bytef*)aPlain, PlainLength) == Z_OK)
|
|
||||||
{
|
|
||||||
m_ServerListLoaded = true;
|
|
||||||
m_ServerListPlainLength = PlainLength;
|
|
||||||
m_ServerListCompLength = DstLen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SendVer(NETADDR *pAddr)
|
|
||||||
{
|
|
||||||
CNetChunk p;
|
|
||||||
unsigned char aData[sizeof(VERSIONSRV_VERSION) + sizeof(GAME_RELEASE_VERSION)];
|
|
||||||
|
|
||||||
mem_copy(aData, VERSIONSRV_VERSION, sizeof(VERSIONSRV_VERSION));
|
|
||||||
mem_copy(aData + sizeof(VERSIONSRV_VERSION), GAME_RELEASE_VERSION, sizeof(GAME_RELEASE_VERSION));
|
|
||||||
|
|
||||||
p.m_ClientID = -1;
|
|
||||||
p.m_Address = *pAddr;
|
|
||||||
p.m_Flags = NETSENDFLAG_CONNLESS;
|
|
||||||
p.m_pData = aData;
|
|
||||||
p.m_DataSize = sizeof(aData);
|
|
||||||
|
|
||||||
g_NetOp.Send(&p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SendNews(NETADDR *pAddr)
|
|
||||||
{
|
|
||||||
CNetChunk p;
|
|
||||||
unsigned char aData[NEWS_SIZE + sizeof(VERSIONSRV_NEWS)];
|
|
||||||
|
|
||||||
mem_copy(aData, VERSIONSRV_NEWS, sizeof(VERSIONSRV_NEWS));
|
|
||||||
mem_copy(aData + sizeof(VERSIONSRV_NEWS), m_aNews, NEWS_SIZE);
|
|
||||||
|
|
||||||
p.m_ClientID = -1;
|
|
||||||
p.m_Address = *pAddr;
|
|
||||||
p.m_Flags = NETSENDFLAG_CONNLESS;
|
|
||||||
p.m_pData = aData;
|
|
||||||
p.m_DataSize = sizeof(aData);
|
|
||||||
|
|
||||||
g_NetOp.Send(&p);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Packet: VERSIONSRV_DDNETLIST + char[4] Token + int16 comp_length + int16 plain_length + char[comp_length]
|
|
||||||
void SendServerList(NETADDR *pAddr, const char *Token)
|
|
||||||
{
|
|
||||||
CNetChunk p;
|
|
||||||
unsigned char aData[16384];
|
|
||||||
short WordCompLength = m_ServerListCompLength;
|
|
||||||
short WordPlainLength = m_ServerListPlainLength;
|
|
||||||
|
|
||||||
mem_copy(aData, VERSIONSRV_DDNETLIST, sizeof(VERSIONSRV_DDNETLIST));
|
|
||||||
mem_copy(aData + sizeof(VERSIONSRV_DDNETLIST), Token, 4); // send back token
|
|
||||||
mem_copy(aData + sizeof(VERSIONSRV_DDNETLIST)+4, &WordCompLength, 2); // compressed length
|
|
||||||
mem_copy(aData + sizeof(VERSIONSRV_DDNETLIST)+6, &WordPlainLength, 2); // plain length
|
|
||||||
mem_copy(aData + sizeof(VERSIONSRV_DDNETLIST)+8, m_aServerList, m_ServerListCompLength);
|
|
||||||
|
|
||||||
p.m_ClientID = -1;
|
|
||||||
p.m_Address = *pAddr;
|
|
||||||
p.m_Flags = NETSENDFLAG_CONNLESS;
|
|
||||||
p.m_pData = aData;
|
|
||||||
p.m_DataSize = sizeof(VERSIONSRV_DDNETLIST) + 4 + 2 + 2 + m_ServerListCompLength;
|
|
||||||
|
|
||||||
g_NetOp.Send(&p);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv) // ignore_convention
|
|
||||||
{
|
|
||||||
NETADDR BindAddr;
|
|
||||||
|
|
||||||
dbg_logger_stdout();
|
|
||||||
net_init();
|
|
||||||
|
|
||||||
mem_zero(&BindAddr, sizeof(BindAddr));
|
|
||||||
BindAddr.type = NETTYPE_ALL;
|
|
||||||
BindAddr.port = VERSIONSRV_PORT;
|
|
||||||
if(!g_NetOp.Open(BindAddr, 0))
|
|
||||||
{
|
|
||||||
dbg_msg("mastersrv", "couldn't start network");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
BuildPackets();
|
|
||||||
|
|
||||||
ReadNews();
|
|
||||||
ReadServerList();
|
|
||||||
|
|
||||||
dbg_msg("versionsrv", "started");
|
|
||||||
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
g_NetOp.Update();
|
|
||||||
|
|
||||||
// process packets
|
|
||||||
CNetChunk Packet;
|
|
||||||
while(g_NetOp.Recv(&Packet))
|
|
||||||
{
|
|
||||||
if(Packet.m_DataSize == sizeof(VERSIONSRV_GETVERSION) &&
|
|
||||||
mem_comp(Packet.m_pData, VERSIONSRV_GETVERSION, sizeof(VERSIONSRV_GETVERSION)) == 0)
|
|
||||||
{
|
|
||||||
SendVer(&Packet.m_Address);
|
|
||||||
|
|
||||||
char aAddrStr[NETADDR_MAXSTRSIZE];
|
|
||||||
net_addr_str(&Packet.m_Address, aAddrStr, sizeof(aAddrStr), false);
|
|
||||||
dbg_msg("versionsrv", "version request by %s", aAddrStr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Packet.m_DataSize == sizeof(VERSIONSRV_GETNEWS) &&
|
|
||||||
mem_comp(Packet.m_pData, VERSIONSRV_GETNEWS, sizeof(VERSIONSRV_GETNEWS)) == 0)
|
|
||||||
{
|
|
||||||
SendNews(&Packet.m_Address);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Packet.m_DataSize == sizeof(VERSIONSRV_GETMAPLIST) &&
|
|
||||||
mem_comp(Packet.m_pData, VERSIONSRV_GETMAPLIST, sizeof(VERSIONSRV_GETMAPLIST)) == 0)
|
|
||||||
{
|
|
||||||
CNetChunk p;
|
|
||||||
p.m_ClientID = -1;
|
|
||||||
p.m_Address = Packet.m_Address;
|
|
||||||
p.m_Flags = NETSENDFLAG_CONNLESS;
|
|
||||||
|
|
||||||
for(int i = 0; i < m_NumPackets; i++)
|
|
||||||
{
|
|
||||||
p.m_DataSize = m_aPackets[i].m_Size;
|
|
||||||
p.m_pData = &m_aPackets[i].m_Data;
|
|
||||||
g_NetOp.Send(&p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_ServerListLoaded &&
|
|
||||||
Packet.m_DataSize == sizeof(VERSIONSRV_GETDDNETLIST) + 4 &&
|
|
||||||
mem_comp(Packet.m_pData, VERSIONSRV_GETDDNETLIST, sizeof(VERSIONSRV_GETDDNETLIST)) == 0)
|
|
||||||
{
|
|
||||||
char aToken[4];
|
|
||||||
mem_copy(aToken, (char*)Packet.m_pData+sizeof(VERSIONSRV_GETDDNETLIST), 4);
|
|
||||||
|
|
||||||
SendServerList(&Packet.m_Address, aToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// wait for input
|
|
||||||
net_socket_read_wait(g_NetOp.m_Socket, 1000000);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
|
||||||
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
|
||||||
#ifndef VERSIONSRV_VERSIONSRV_H
|
|
||||||
#define VERSIONSRV_VERSIONSRV_H
|
|
||||||
static const int VERSIONSRV_PORT = 8302;
|
|
||||||
static const int NEWS_SIZE = 1380;
|
|
||||||
static const int DDNETLIST_SIZE = 1380;
|
|
||||||
|
|
||||||
struct CMapVersion
|
|
||||||
{
|
|
||||||
char m_aName[8];
|
|
||||||
unsigned char m_aCrc[4];
|
|
||||||
unsigned char m_aSize[4];
|
|
||||||
};
|
|
||||||
|
|
||||||
static const unsigned char VERSIONSRV_GETVERSION[] = {255, 255, 255, 255, 'v', 'e', 'r', 'g'};
|
|
||||||
static const unsigned char VERSIONSRV_VERSION[] = {255, 255, 255, 255, 'v', 'e', 'r', 's'};
|
|
||||||
|
|
||||||
static const unsigned char VERSIONSRV_GETMAPLIST[] = {255, 255, 255, 255, 'v', 'm', 'l', 'g'};
|
|
||||||
static const unsigned char VERSIONSRV_MAPLIST[] = {255, 255, 255, 255, 'v', 'm', 'l', 's'};
|
|
||||||
|
|
||||||
static const unsigned char VERSIONSRV_GETNEWS[] = {255, 255, 255, 255, 'n', 'e', 'w', 'g'};
|
|
||||||
static const unsigned char VERSIONSRV_NEWS[] = {255, 255, 255, 255, 'n', 'e', 'w', 's'};
|
|
||||||
|
|
||||||
static const unsigned char VERSIONSRV_GETDDNETLIST[] = {255, 255, 255, 255, 'e', 'a', 's', 't'};
|
|
||||||
static const unsigned char VERSIONSRV_DDNETLIST[] = {255, 255, 255, 255, 't', 's', 'a', 'e'};
|
|
||||||
#endif
|
|
Loading…
Reference in a new issue