Compare commits

...

8 commits

Author SHA1 Message Date
furo fcc47407ee
Merge d0840e6458 into 3345bc9da0 2024-11-01 10:02:17 +00:00
Robert Müller 3345bc9da0
Merge pull request #9186 from def-/pr-transl-18.7
Update translations for upcoming 18.7
2024-11-01 09:06:00 +00:00
Dennis Felsing d6e31d35fe Update translations for upcoming 18.7 2024-11-01 09:12:18 +01:00
Dennis Felsing 19aa7fbb77 Version 18.8 2024-11-01 09:11:04 +01:00
Dennis Felsing 0f91b1287d
Merge pull request #9185 from Robyt3/Client-Font-Error
Improve error handling on invalid fonts and font index
2024-11-01 07:50:48 +00:00
Dennis Felsing 6bcf8ead49 Fix clang-tidy 2024-11-01 08:32:26 +01:00
Robert Müller 96eb49ad3f Improve error handling on invalid fonts and font index
Log more detailed error messages when fonts could not be loaded and when the font index is malformed. Show warning popup on client launch if any font failed to load, although this warning won't be readable if all fonts failed to be loaded.
2024-11-01 00:16:14 +01:00
furo d0840e6458 Add a "connection problems" icon to nameplate 2024-10-26 18:55:46 +02:00
55 changed files with 343 additions and 57 deletions

View file

@ -1486,6 +1486,7 @@ set(EXPECTED_DATA
languages/traditional_chinese.txt
languages/turkish.txt
languages/ukrainian.txt
license.txt
mapres/basic_freeze.png
mapres/bg_cloud1.png
mapres/bg_cloud2.png
@ -1569,6 +1570,7 @@ set(EXPECTED_DATA
menuimages/local_server.png
menuimages/play_game.png
menuimages/settings.png
network.png
particles.png
race_flag.png
shader/pipeline.frag

View file

@ -1125,6 +1125,9 @@ Loading map file from storage
Loading demo file from storage
==
Some fonts could not be loaded. Check the local console for details.
==
Initializing components
==

View file

@ -1939,3 +1939,6 @@ Feet
[skins]
Eyes
== Göz
Some fonts could not be loaded. Check the local console for details.
==

View file

@ -1876,6 +1876,9 @@ Connect address error
Could not connect dummy
==
Some fonts could not be loaded. Check the local console for details.
==
Save skin
==

View file

@ -987,6 +987,9 @@ Loading map file from storage
Loading demo file from storage
==
Some fonts could not be loaded. Check the local console for details.
==
Initializing components
==

View file

@ -1970,3 +1970,6 @@ Feet
[skins]
Eyes
== Olhos
Some fonts could not be loaded. Check the local console for details.
==

View file

@ -591,6 +591,9 @@ Loading map file from storage
Loading demo file from storage
==
Some fonts could not be loaded. Check the local console for details.
==
Loading DDNet Client
==

View file

@ -1227,6 +1227,9 @@ Loading map file from storage
Loading demo file from storage
==
Some fonts could not be loaded. Check the local console for details.
==
Initializing components
==

View file

@ -594,6 +594,9 @@ Loading map file from storage
Loading demo file from storage
==
Some fonts could not be loaded. Check the local console for details.
==
Loading DDNet Client
==

View file

@ -1943,3 +1943,6 @@ Feet
[skins]
Eyes
== Oči
Some fonts could not be loaded. Check the local console for details.
==

View file

@ -1136,6 +1136,9 @@ Loading map file from storage
Loading demo file from storage
==
Some fonts could not be loaded. Check the local console for details.
==
Initializing components
==

View file

@ -1273,6 +1273,9 @@ Loading map file from storage
Loading demo file from storage
==
Some fonts could not be loaded. Check the local console for details.
==
Initializing components
==

View file

@ -610,6 +610,9 @@ Preparing demo playback
Loading demo file from storage
==
Some fonts could not be loaded. Check the local console for details.
==
Initializing components
==

View file

@ -1872,6 +1872,9 @@ Connect address error
Could not connect dummy
==
Some fonts could not be loaded. Check the local console for details.
==
Save skin
==

View file

@ -1832,6 +1832,9 @@ Connect address error
Could not connect dummy
==
Some fonts could not be loaded. Check the local console for details.
==
[Spectating]
Following %s
==

View file

@ -1874,6 +1874,9 @@ Connect address error
Could not connect dummy
==
Some fonts could not be loaded. Check the local console for details.
==
[Spectating]
Following %s
==

View file

@ -1586,6 +1586,9 @@ Error saving settings
Loading demo file from storage
==
Some fonts could not be loaded. Check the local console for details.
==
Quitting. Please wait…
==

View file

@ -1956,3 +1956,6 @@ Eyes
https://wiki.ddnet.org/wiki/Mapping
== https://wiki.ddnet.org/wiki/Mapping
Some fonts could not be loaded. Check the local console for details.
== Einige Schriften konnten nicht geladen werden. Prüf die lokale Konsole für Details.

View file

@ -600,6 +600,9 @@ Loading map file from storage
Loading demo file from storage
==
Some fonts could not be loaded. Check the local console for details.
==
Loading DDNet Client
==

View file

@ -1566,6 +1566,9 @@ The width of texture %s is not divisible by %d, or the height is not divisible b
Loading demo file from storage
==
Some fonts could not be loaded. Check the local console for details.
==
Quitting. Please wait…
==

View file

@ -1435,6 +1435,9 @@ The format of texture %s is not RGBA which will cause visual bugs.
Loading demo file from storage
==
Some fonts could not be loaded. Check the local console for details.
==
Why are you slowmo replaying to read this?
==

View file

@ -1168,6 +1168,9 @@ Loading map file from storage
Loading demo file from storage
==
Some fonts could not be loaded. Check the local console for details.
==
Initializing components
==

View file

@ -1578,6 +1578,9 @@ The width of texture %s is not divisible by %d, or the height is not divisible b
Loading demo file from storage
==
Some fonts could not be loaded. Check the local console for details.
==
Quitting. Please wait…
==

View file

@ -591,6 +591,9 @@ Loading map file from storage
Loading demo file from storage
==
Some fonts could not be loaded. Check the local console for details.
==
Loading DDNet Client
==

View file

@ -1137,6 +1137,9 @@ Loading map file from storage
Loading demo file from storage
==
Some fonts could not be loaded. Check the local console for details.
==
Initializing components
==

View file

@ -1534,9 +1534,6 @@ Saving settings to '%s' failed
Error saving settings
== ﺕﺎﻤﯿﻈﻨﺗ ﻥﺩﺮﻛ ﻩﺮﯿﺧﺫ ﺭﺩ ﺎﻄﺧ
The width of texture %s is not divisible by %d, or the height is not divisible by %d, which might cause visual bugs.
==
The format of texture %s is not RGBA which will cause visual bugs.
== .ﺩﻮﺷ ﯽﻣ ىﺮﻫﺎﻇ ﻝﺎﻜﺷﺍ ﺩﺎﺠﯾﺍ ﺚﻋﺎﺑ ﻪﻛ ﺖﺴﯿﻧ %s RGBA ﯽﻜﯿﻓﺍﺮﮔ ﺖﻟﺎﺣ ﺖﻣﺮﻓ
@ -1938,3 +1935,9 @@ Moved ingame
https://wiki.ddnet.org/wiki/Mapping
== https://wiki.ddnet.org/wiki/Mapping
The width of texture %s is not divisible by %d, or the height is not divisible by %d, which might cause visual bugs.
==
Some fonts could not be loaded. Check the local console for details.
==

View file

@ -1945,3 +1945,6 @@ Moved ingame
https://wiki.ddnet.org/wiki/Mapping
== https://wiki.ddnet.org/wiki/Mapping
Some fonts could not be loaded. Check the local console for details.
==

View file

@ -932,6 +932,9 @@ Loading map file from storage
Loading demo file from storage
==
Some fonts could not be loaded. Check the local console for details.
==
Initializing components
==

View file

@ -606,6 +606,9 @@ Loading map file from storage
Loading demo file from storage
==
Some fonts could not be loaded. Check the local console for details.
==
Loading DDNet Client
==

View file

@ -1912,6 +1912,9 @@ Custom
Unable to delete skin
== Невозможно удалить скин
Some fonts could not be loaded. Check the local console for details.
==
Save skin
==

View file

@ -1664,6 +1664,9 @@ Error saving settings
Loading demo file from storage
==
Some fonts could not be loaded. Check the local console for details.
==
Searching
==

View file

@ -1440,6 +1440,9 @@ Error saving settings
Loading demo file from storage
==
Some fonts could not be loaded. Check the local console for details.
==
Initializing components
==

View file

@ -1983,3 +1983,6 @@ Feet
[skins]
Eyes
== 眼睛
Some fonts could not be loaded. Check the local console for details.
==

View file

@ -1940,3 +1940,6 @@ Feet
[skins]
Eyes
== Oči
Some fonts could not be loaded. Check the local console for details.
==

View file

@ -1958,3 +1958,6 @@ Feet
[skins]
Eyes
== Ojos
Some fonts could not be loaded. Check the local console for details.
==

View file

@ -1942,3 +1942,6 @@ Feet
[skins]
Eyes
== Ögon
Some fonts could not be loaded. Check the local console for details.
==

View file

@ -1972,3 +1972,6 @@ Feet
[skins]
Eyes
== 眼睛
Some fonts could not be loaded. Check the local console for details.
==

View file

@ -1952,3 +1952,6 @@ Feet
[skins]
Eyes
== Göz
Some fonts could not be loaded. Check the local console for details.
==

View file

@ -1939,3 +1939,6 @@ Zoom in
Zoom out
== Віддалити
Some fonts could not be loaded. Check the local console for details.
==

3
data/license.txt Normal file
View file

@ -0,0 +1,3 @@
network.png:
Copyright leovilok
CC BY-SA 3.0 license (https://creativecommons.org/licenses/by-sa/3.0/)

BIN
data/network.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View file

@ -238,6 +238,7 @@ image_audio_source = Image("audio_source", "editor/audio_source.png")
image_strongweak = Image("strongweak", "strong_weak.png")
image_hud = Image("hud", "hud.png")
image_extras = Image("extras", "extras.png")
image_networkicons = Image("networkicons", "network.png", 1)
container.images.Add(image_null)
container.images.Add(image_game)
@ -256,6 +257,7 @@ container.images.Add(image_strongweak)
container.images.Add(image_hud)
container.images.Add(image_extras)
container.images.Add(Image("raceflag", "race_flag.png"))
container.images.Add(image_networkicons)
container.pickups.Add(Pickup("health"))
container.pickups.Add(Pickup("armor"))
@ -277,6 +279,7 @@ set_audio_source = SpriteSet("audio_source", image_audio_source, 1, 1)
set_strongweak = SpriteSet("strongweak", image_strongweak, 2, 1)
set_hud = SpriteSet("hud", image_hud, 16, 16)
set_extras = SpriteSet("extras", image_extras, 16, 16)
set_networkicons = SpriteSet("networkicons", image_networkicons, 1, 2)
container.spritesets.Add(set_particles)
container.spritesets.Add(set_game)
@ -289,6 +292,7 @@ container.spritesets.Add(set_audio_source)
container.spritesets.Add(set_strongweak)
container.spritesets.Add(set_hud)
container.spritesets.Add(set_extras)
container.spritesets.Add(set_networkicons)
container.sprites.Add(Sprite("part_slice", set_particles, 0,0,1,1))
container.sprites.Add(Sprite("part_ball", set_particles, 1,0,1,1))
@ -454,6 +458,9 @@ container.sprites.Add(Sprite("hud_team0_mode", set_hud, 12,6,2,2))
container.sprites.Add(Sprite("part_snowflake", set_extras, 0,0,2,2))
container.sprites.Add(Sprite("part_sparkle", set_extras, 2,0,2,2))
container.sprites.Add(Sprite("network_good", set_networkicons, 0,0,1,1))
container.sprites.Add(Sprite("network_bad", set_networkicons, 0,1,1,1))
anim = Animation("base")
anim.body.frames.Add(AnimKeyframe(0, 0, -4, 0))

View file

@ -28,7 +28,7 @@ GameInfoFlags2 = [
"ALLOW_X_SKINS", "GAMETYPE_CITY", "GAMETYPE_FDDRACE", "ENTITIES_FDDRACE", "HUD_HEALTH_ARMOR", "HUD_AMMO",
"HUD_DDRACE", "NO_WEAK_HOOK", "NO_SKIN_CHANGE_FOR_FROZEN"
]
ExPlayerFlags = ["AFK", "PAUSED", "SPEC"]
ExPlayerFlags = ["AFK", "PAUSED", "SPEC", "CONNECTION_PROBLEMS"]
LegacyProjectileFlags = [f"CLIENTID_BIT{i}" for i in range(8)] + [
"NO_OWNER", "IS_DDNET", "BOUNCE_HORIZONTAL", "BOUNCE_VERTICAL",
"EXPLOSIVE", "FREEZE",

View file

@ -615,37 +615,65 @@ public:
void AddFace(FT_Face Face)
{
m_vFtFaces.push_back(Face);
if(!m_DefaultFace)
m_DefaultFace = Face;
}
void SetDefaultFaceByName(const char *pFamilyName)
bool SetDefaultFaceByName(const char *pFamilyName)
{
m_DefaultFace = GetFaceByName(pFamilyName);
if(!m_DefaultFace)
{
if(!m_vFtFaces.empty())
{
m_DefaultFace = m_vFtFaces.front();
}
log_error("textrender", "The default font face '%s' could not be found", pFamilyName);
return false;
}
return true;
}
void SetIconFaceByName(const char *pFamilyName)
bool SetIconFaceByName(const char *pFamilyName)
{
m_IconFace = GetFaceByName(pFamilyName);
if(!m_IconFace)
{
log_error("textrender", "The icon font face '%s' could not be found", pFamilyName);
return false;
}
return true;
}
void AddFallbackFaceByName(const char *pFamilyName)
bool AddFallbackFaceByName(const char *pFamilyName)
{
FT_Face Face = GetFaceByName(pFamilyName);
if(Face != nullptr && std::find(m_vFallbackFaces.begin(), m_vFallbackFaces.end(), Face) == m_vFallbackFaces.end())
if(!Face)
{
m_vFallbackFaces.push_back(Face);
log_error("textrender", "The fallback font face '%s' could not be found", pFamilyName);
return false;
}
if(std::find(m_vFallbackFaces.begin(), m_vFallbackFaces.end(), Face) != m_vFallbackFaces.end())
{
log_warn("textrender", "The fallback font face '%s' was specified multiple times", pFamilyName);
return true;
}
m_vFallbackFaces.push_back(Face);
return true;
}
void SetVariantFaceByName(const char *pFamilyName)
bool SetVariantFaceByName(const char *pFamilyName)
{
FT_Face Face = GetFaceByName(pFamilyName);
if(m_VariantFace != Face)
{
m_VariantFace = Face;
Clear(); // rebuild atlas after changing variant font
if(!Face && pFamilyName != nullptr)
{
log_error("textrender", "The variant font face '%s' could not be found", pFamilyName);
return false;
}
}
return true;
}
void SetFontPreset(EFontPreset FontPreset)
@ -1002,9 +1030,7 @@ class CTextRender : public IEngineTextRender
FT_Error CollectionLoadError = FT_New_Memory_Face(m_FTLibrary, pFontData, FontDataSize, -1, &FtFace);
if(CollectionLoadError)
{
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "Failed to load font file '%s': %s", pFontName, FT_Error_String(CollectionLoadError));
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "textrender", aBuf);
log_error("textrender", "Failed to load font file '%s': %s", pFontName, FT_Error_String(CollectionLoadError));
return false;
}
@ -1017,26 +1043,20 @@ class CTextRender : public IEngineTextRender
FT_Error FaceLoadError = FT_New_Memory_Face(m_FTLibrary, pFontData, FontDataSize, FaceIndex, &FtFace);
if(FaceLoadError)
{
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "Failed to load font face %ld from font file '%s': %s", FaceIndex, pFontName, FT_Error_String(FaceLoadError));
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "textrender", aBuf);
log_error("textrender", "Failed to load font face %ld from font file '%s': %s", FaceIndex, pFontName, FT_Error_String(FaceLoadError));
FT_Done_Face(FtFace);
continue;
}
m_pGlyphMap->AddFace(FtFace);
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "Loaded font face %ld '%s %s' from font file '%s'", FaceIndex, FtFace->family_name, FtFace->style_name, pFontName);
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "textrender", aBuf);
log_debug("textrender", "Loaded font face %ld '%s %s' from font file '%s'", FaceIndex, FtFace->family_name, FtFace->style_name, pFontName);
LoadedAny = true;
}
if(!LoadedAny)
{
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "Failed to load font file '%s': no font faces could be loaded", pFontName);
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "textrender", aBuf);
log_error("textrender", "Failed to load font file '%s': no font faces could be loaded", pFontName);
return false;
}
@ -1083,9 +1103,7 @@ public:
{
int LMajor, LMinor, LPatch;
FT_Library_Version(m_FTLibrary, &LMajor, &LMinor, &LPatch);
char aFreetypeVersion[128];
str_format(aFreetypeVersion, sizeof(aFreetypeVersion), "Freetype version %d.%d.%d (compiled = %d.%d.%d)", LMajor, LMinor, LPatch, FREETYPE_MAJOR, FREETYPE_MINOR, FREETYPE_PATCH);
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "textrender", aFreetypeVersion);
log_info("textrender", "Freetype version %d.%d.%d (compiled = %d.%d.%d)", LMajor, LMinor, LPatch, FREETYPE_MAJOR, FREETYPE_MINOR, FREETYPE_PATCH);
}
m_FirstFreeTextContainerIndex = -1;
@ -1142,7 +1160,7 @@ public:
m_pStorage = nullptr;
}
void LoadFonts() override
bool LoadFonts() override
{
// read file data into buffer
const char *pFilename = "fonts/index.json";
@ -1150,10 +1168,8 @@ public:
unsigned JsonFileSize;
if(!Storage()->ReadFile(pFilename, IStorage::TYPE_ALL, &pFileData, &JsonFileSize))
{
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "Failed to open/read font index file '%s'", pFilename);
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "textrender", aBuf);
return;
log_error("textrender", "Failed to open/read font index file '%s'", pFilename);
return false;
}
// parse json data
@ -1163,11 +1179,16 @@ public:
free(pFileData);
if(pJsonData == nullptr)
{
char aBuf[512];
str_format(aBuf, sizeof(aBuf), "Failed to parse font index file '%s': %s", pFilename, aError);
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "textrender", aBuf);
return;
log_error("textrender", "Failed to parse font index file '%s': %s", pFilename, aError);
return false;
}
if(pJsonData->type != json_object)
{
log_error("textrender", "Font index malformed: root must be an object", pFilename, aError);
return false;
}
bool Success = true;
// extract font file definitions
const json_value &FontFiles = (*pJsonData)["font files"];
@ -1176,7 +1197,11 @@ public:
for(unsigned FontFileIndex = 0; FontFileIndex < FontFiles.u.array.length; ++FontFileIndex)
{
if(FontFiles[FontFileIndex].type != json_string)
{
log_error("textrender", "Font index malformed: 'font files' must be an array of strings (error at index %d)", FontFileIndex);
Success = false;
continue;
}
char aFontName[IO_MAX_PATH_LENGTH];
str_format(aFontName, sizeof(aFontName), "fonts/%s", FontFiles[FontFileIndex].u.string.ptr);
@ -1193,32 +1218,60 @@ public:
free(pFontData);
}
}
else
{
log_error("textrender", "Failed to open/read font file '%s'", aFontName);
Success = false;
}
}
}
else
{
log_error("textrender", "Font index malformed: 'font files' must be an array");
Success = false;
}
// extract default family name
const json_value &DefaultFace = (*pJsonData)["default"];
if(DefaultFace.type == json_string)
{
m_pGlyphMap->SetDefaultFaceByName(DefaultFace.u.string.ptr);
if(!m_pGlyphMap->SetDefaultFaceByName(DefaultFace.u.string.ptr))
{
Success = false;
}
}
else
{
log_error("textrender", "Font index malformed: 'default' must be a string");
Success = false;
}
// extract language variant family names
const json_value &Variants = (*pJsonData)["language variants"];
if(Variants.type == json_object)
{
m_vVariants.resize(Variants.u.object.length);
m_vVariants.reserve(Variants.u.object.length);
for(size_t i = 0; i < Variants.u.object.length; ++i)
{
str_format(m_vVariants[i].m_aLanguageFile, sizeof(m_vVariants[i].m_aLanguageFile), "languages/%s.txt", Variants.u.object.values[i].name);
const json_value *pFamilyName = Variants.u.object.values[i].value;
if(pFamilyName->type == json_string)
str_copy(m_vVariants[i].m_aFamilyName, pFamilyName->u.string.ptr);
else
m_vVariants[i].m_aFamilyName[0] = '\0';
if(pFamilyName->type != json_string)
{
log_error("textrender", "Font index malformed: 'language variants' entries must have string values (error on entry '%s')", Variants.u.object.values[i].name);
Success = false;
continue;
}
SFontLanguageVariant Variant;
str_format(Variant.m_aLanguageFile, sizeof(Variant.m_aLanguageFile), "languages/%s.txt", Variants.u.object.values[i].name);
str_copy(Variant.m_aFamilyName, pFamilyName->u.string.ptr);
m_vVariants.emplace_back(Variant);
}
}
else
{
log_error("textrender", "Font index malformed: 'language variants' must be an array");
Success = false;
}
// extract fallback family names
const json_value &FallbackFaces = (*pJsonData)["fallbacks"];
@ -1226,21 +1279,41 @@ public:
{
for(unsigned i = 0; i < FallbackFaces.u.array.length; ++i)
{
if(FallbackFaces[i].type == json_string)
if(FallbackFaces[i].type != json_string)
{
m_pGlyphMap->AddFallbackFaceByName(FallbackFaces[i].u.string.ptr);
log_error("textrender", "Font index malformed: 'fallbacks' must be an array of strings (error at index %d)", i);
Success = false;
continue;
}
if(!m_pGlyphMap->AddFallbackFaceByName(FallbackFaces[i].u.string.ptr))
{
Success = false;
}
}
}
else
{
log_error("textrender", "Font index malformed: 'fallbacks' must be an array");
Success = false;
}
// extract icon font family name
const json_value &IconFace = (*pJsonData)["icon"];
if(IconFace.type == json_string)
{
m_pGlyphMap->SetIconFaceByName(IconFace.u.string.ptr);
if(!m_pGlyphMap->SetIconFaceByName(IconFace.u.string.ptr))
{
Success = false;
}
}
else
{
log_error("textrender", "Font index malformed: 'icon' must be a string");
Success = false;
}
json_value_free(pJsonData);
return Success;
}
void SetFontPreset(EFontPreset FontPreset) override

View file

@ -44,6 +44,7 @@ public:
int m_DDNetVersion;
const char *m_pDDNetVersionStr;
const CUuid *m_pConnectionId;
int m_LastPacketTick;
};
int Tick() const { return m_CurrentGameTick; }

View file

@ -214,6 +214,7 @@ void CServer::CClient::Reset()
m_Snapshots.PurgeAll();
m_LastAckedSnapshot = -1;
m_LastInputTick = -1;
m_LastPacketTick = -1;
m_SnapRate = CClient::SNAPRATE_INIT;
m_Score = -1;
m_NextMapChunk = 0;
@ -587,6 +588,7 @@ bool CServer::GetClientInfo(int ClientId, CClientInfo *pInfo) const
pInfo->m_Latency = m_aClients[ClientId].m_Latency;
pInfo->m_GotDDNetVersion = m_aClients[ClientId].m_DDNetVersionSettled;
pInfo->m_DDNetVersion = m_aClients[ClientId].m_DDNetVersion >= 0 ? m_aClients[ClientId].m_DDNetVersion : VERSION_VANILLA;
pInfo->m_LastPacketTick = m_aClients[ClientId].m_LastPacketTick;
if(m_aClients[ClientId].m_GotDDNetVersionPacket)
{
pInfo->m_pConnectionId = &m_aClients[ClientId].m_ConnectionId;
@ -1458,6 +1460,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
return;
}
m_aClients[ClientId].m_LastPacketTick = Tick();
if(Config()->m_SvNetlimit && Msg != NETMSG_REQUEST_MAP_DATA)
{
int64_t Now = time_get();

View file

@ -145,6 +145,7 @@ public:
int m_LastAckedSnapshot;
int m_LastInputTick;
int m_LastPacketTick;
CSnapshotStorage m_Snapshots;
CInput m_LatestInput;

View file

@ -34,6 +34,7 @@ MACRO_CONFIG_INT(ClNameplatesIds, cl_nameplates_ids, 0, 0, 1, CFGFLAG_CLIENT | C
MACRO_CONFIG_INT(ClNameplatesOwn, cl_nameplates_own, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show own name plate (useful for demo recording)")
MACRO_CONFIG_INT(ClNameplatesFriendMark, cl_nameplates_friendmark, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show friend mark (♥) in name plates")
MACRO_CONFIG_INT(ClNameplatesStrong, cl_nameplates_strong, 0, 0, 2, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show strong/weak in name plates (0 - off, 1 - icons, 2 - icons + numbers)")
MACRO_CONFIG_INT(ClNameplatesNetwork, cl_nameplates_network, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show a network icon if the player has connection problems")
MACRO_CONFIG_INT(ClTextEntities, cl_text_entities, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Render textual entity data")
MACRO_CONFIG_INT(ClTextEntitiesSize, cl_text_entities_size, 100, 1, 100, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Size of textual entity data from 1 to 100%")
MACRO_CONFIG_INT(ClStreamerMode, cl_streamer_mode, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Censor sensitive information such as /save password")

View file

@ -316,7 +316,7 @@ public:
virtual void MoveCursor(CTextCursor *pCursor, float x, float y) const = 0;
virtual void SetCursorPosition(CTextCursor *pCursor, float x, float y) const = 0;
virtual void LoadFonts() = 0;
virtual bool LoadFonts() = 0;
virtual void SetFontPreset(EFontPreset FontPreset) = 0;
virtual void SetFontLanguageVariant(const char *pLanguageFile) = 0;

View file

@ -2774,6 +2774,12 @@ void CMenus::RenderSettingsAppearance(CUIRect MainView)
g_Config.m_ClNameplatesStrong = g_Config.m_ClNameplatesStrong != 2 ? 2 : 1;
}
LeftView.HSplitTop(LineSize, &Button, &LeftView);
if(DoButton_CheckBox(&g_Config.m_ClNameplatesNetwork, Localize("Show connection problems icon"), g_Config.m_ClNameplatesNetwork, &Button))
{
g_Config.m_ClNameplatesNetwork = g_Config.m_ClNameplatesNetwork ^ 1;
}
LeftView.HSplitTop(LineSize, &Button, &LeftView);
if(DoButton_CheckBox(&g_Config.m_ClShowDirection, Localize("Show other players' key presses"), g_Config.m_ClShowDirection >= 1 && g_Config.m_ClShowDirection != 3, &Button))
{
@ -2863,6 +2869,8 @@ void CMenus::RenderSettingsAppearance(CUIRect MainView)
TextRender()->Text(TeeRenderPos.x - TextRender()->TextWidth(FontSize, "0") / 2.0f, YOffset, FontSize, "0");
}
float XOffset = TeeRenderPos.x;
bool ChangedOffset = false;
if(g_Config.m_ClNameplatesStrong)
{
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_STRONGWEAK].m_Id);
@ -2878,15 +2886,38 @@ void CMenus::RenderSettingsAppearance(CUIRect MainView)
const float StrongImgSize = 40.0f;
YOffset -= StrongImgSize * ScaleY;
RenderTools()->DrawSprite(TeeRenderPos.x, YOffset + (StrongImgSize / 2.0f) * ScaleY, StrongImgSize);
ChangedOffset = true;
if(g_Config.m_ClNameplatesNetwork)
XOffset = XOffset - (StrongImgSize / 2);
RenderTools()->DrawSprite(XOffset, YOffset + (StrongImgSize / 2.0f) * ScaleY, StrongImgSize);
Graphics()->QuadsEnd();
if(g_Config.m_ClNameplatesStrong == 2)
{
YOffset -= FontSize;
TextRender()->Text(TeeRenderPos.x - TextRender()->TextWidth(FontSize, "0") / 2.0f, YOffset, FontSize, "0");
TextRender()->Text(TeeRenderPos.x - TextRender()->TextWidth(FontSize, "0") / 2.0f, YOffset - FontSize, FontSize, "0");
}
}
if(g_Config.m_ClNameplatesNetwork)
{
ColorRGBA Color = ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f);
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_NETWORKICONS].m_Id);
Graphics()->QuadsBegin();
RenderTools()->SelectSprite(SPRITE_NETWORK_BAD);
float ScaleX, ScaleY;
RenderTools()->GetSpriteScale(SPRITE_NETWORK_BAD, ScaleX, ScaleY);
const float NetworkImgSize = 40.0f;
if(!ChangedOffset)
YOffset -= NetworkImgSize * ScaleY;
else
XOffset += NetworkImgSize;
Graphics()->SetColor(Color);
RenderTools()->DrawSprite(XOffset, YOffset + (NetworkImgSize / 2.0f) * ScaleY, NetworkImgSize);
Graphics()->QuadsEnd();
}
}
TextRender()->TextColor(TextRender()->DefaultTextColor());

View file

@ -204,6 +204,9 @@ void CNamePlates::RenderNameplate(vec2 Position, const CNetObj_PlayerInfo *pPlay
}
}
float XOffset = Position.x;
bool ChangedOffset = false;
bool ConnectionProblems = m_pClient->m_aClients[pPlayerInfo->m_ClientId].m_ConnectionProblems;
if((g_Config.m_Debug || g_Config.m_ClNameplatesStrong) && g_Config.m_ClNameplates)
{
const bool Following = (m_pClient->m_Snap.m_SpecInfo.m_Active && !GameClient()->m_MultiViewActivated && m_pClient->m_Snap.m_SpecInfo.m_SpectatorId != SPEC_FREEVIEW);
@ -251,20 +254,53 @@ void CNamePlates::RenderNameplate(vec2 Position, const CNetObj_PlayerInfo *pPlay
const float StrongWeakImgSize = 40.0f;
YOffset -= StrongWeakImgSize * ScaleY;
RenderTools()->DrawSprite(Position.x, YOffset + (StrongWeakImgSize / 2.0f) * ScaleY, StrongWeakImgSize);
ChangedOffset = true;
if(ConnectionProblems && g_Config.m_ClNameplatesNetwork)
XOffset = XOffset - (StrongWeakImgSize / 2);
RenderTools()->DrawSprite(XOffset, YOffset + (StrongWeakImgSize / 2.0f) * ScaleY, StrongWeakImgSize);
Graphics()->QuadsEnd();
}
if(g_Config.m_Debug || g_Config.m_ClNameplatesStrong == 2)
{
YOffset -= FontSize;
char aBuf[12];
str_format(aBuf, sizeof(aBuf), "%d", Other.m_ExtendedData.m_StrongWeakId);
TextRender()->Text(Position.x - TextRender()->TextWidth(FontSize, aBuf) / 2.0f, YOffset, FontSize, aBuf);
TextRender()->Text(Position.x - TextRender()->TextWidth(FontSize, aBuf) / 2.0f, YOffset - FontSize, FontSize, aBuf);
}
}
}
}
// Connection problems icon
if(g_Config.m_ClNameplates && g_Config.m_ClNameplatesNetwork)
{
if(ConnectionProblems)
{
ColorRGBA Color = ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f);
if(OtherTeam && !ForceAlpha)
Color.a = g_Config.m_ClShowOthersAlpha / 100.0f;
else if(g_Config.m_ClNameplatesAlways == 0)
Color.a = clamp(1 - std::pow(distance(m_pClient->m_Controls.m_aTargetPos[g_Config.m_ClDummy], Position) / 200.0f, 16.0f), 0.0f, 1.0f);
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_NETWORKICONS].m_Id);
Graphics()->QuadsBegin();
RenderTools()->SelectSprite(SPRITE_NETWORK_BAD);
float ScaleX, ScaleY;
RenderTools()->GetSpriteScale(SPRITE_NETWORK_BAD, ScaleX, ScaleY);
const float NetworkImgSize = 40.0f;
if(!ChangedOffset)
YOffset -= NetworkImgSize * ScaleY;
else
XOffset += NetworkImgSize;
Graphics()->SetColor(Color);
RenderTools()->DrawSprite(XOffset, YOffset + (NetworkImgSize / 2.0f) * ScaleY, NetworkImgSize);
Graphics()->QuadsEnd();
}
}
TextRender()->TextColor(TextRender()->DefaultTextColor());
TextRender()->TextOutlineColor(TextRender()->DefaultTextOutlineColor());

View file

@ -328,7 +328,10 @@ void CGameClient::OnInit()
for(int i = 0; i < OLD_NUM_NETOBJTYPES; i++)
Client()->SnapSetStaticsize7(i, m_NetObjHandler7.GetObjSize(i));
TextRender()->LoadFonts();
if(!TextRender()->LoadFonts())
{
Client()->AddWarning(SWarning(Localize("Some fonts could not be loaded. Check the local console for details.")));
}
TextRender()->SetFontLanguageVariant(g_Config.m_ClLanguagefile);
// update and swap after font loading, they are quite huge
@ -1616,6 +1619,7 @@ void CGameClient::OnNewSnapshot()
m_aClients[Item.m_Id].m_Afk = pInfo->m_Flags & EXPLAYERFLAG_AFK;
m_aClients[Item.m_Id].m_Paused = pInfo->m_Flags & EXPLAYERFLAG_PAUSED;
m_aClients[Item.m_Id].m_Spec = pInfo->m_Flags & EXPLAYERFLAG_SPEC;
m_aClients[Item.m_Id].m_ConnectionProblems = pInfo->m_Flags & EXPLAYERFLAG_CONNECTION_PROBLEMS;
if(Item.m_Id == m_Snap.m_LocalClientId && (m_aClients[Item.m_Id].m_Paused || m_aClients[Item.m_Id].m_Spec))
{
@ -2499,6 +2503,7 @@ void CGameClient::CClientData::Reset()
m_Afk = false;
m_Paused = false;
m_Spec = false;
m_ConnectionProblems = false;
std::fill(std::begin(m_aSwitchStates), std::end(m_aSwitchStates), 0);

View file

@ -420,6 +420,7 @@ public:
bool m_Afk;
bool m_Paused;
bool m_Spec;
bool m_ConnectionProblems;
// Editor allows 256 switches for now.
bool m_aSwitchStates[256];

View file

@ -424,6 +424,14 @@ void CPlayer::Snap(int SnappingClient)
if(m_Paused == PAUSE_PAUSED)
pDDNetPlayer->m_Flags |= EXPLAYERFLAG_PAUSED;
IServer::CClientInfo Info;
if(Server()->GetClientInfo(id, &Info))
{
// Send "connection problems" flag if player hasn't sent any packets after 5 seconds.
if(Server()->Tick() - Info.m_LastPacketTick >= 5 * Server()->TickSpeed())
pDDNetPlayer->m_Flags |= EXPLAYERFLAG_CONNECTION_PROBLEMS;
}
if(Server()->IsSixup(SnappingClient) && m_pCharacter && m_pCharacter->m_DDRaceState == DDRACE_STARTED &&
GameServer()->m_apPlayers[SnappingClient]->m_TimerType == TIMERTYPE_SIXUP)
{

View file

@ -3,7 +3,7 @@
#ifndef GAME_VERSION_H
#define GAME_VERSION_H
#ifndef GAME_RELEASE_VERSION
#define GAME_RELEASE_VERSION "18.7"
#define GAME_RELEASE_VERSION "18.8"
#endif
// teeworlds
@ -13,7 +13,7 @@
#define GAME_NETVERSION7 "0.7 802f1be60a05665f"
// ddnet
#define DDNET_VERSION_NUMBER 18070
#define DDNET_VERSION_NUMBER 18080
extern const char *GIT_SHORTREV_HASH;
#define GAME_NAME "DDNet"
#endif