Skip to content

Commit

Permalink
Improve skin downloading: load from downloadedskins if possible
Browse files Browse the repository at this point in the history
Previously, skins not found in the `skins` folder were downloaded from the configured URL and saved to the `downloadedskins` folder, but the saved files were never used, leading to wasted downloads and write operations.

Now, if a skin to be downloaded already exists in the `downloadedskins` folder, the modified time of the skin file is determined and a HTTP HEAD request is sent to the skin download URL to determine when the skin to be downloaded was last modified. The times are compared with each other and if the local file is already up-to-date it will be loaded directly. The skin will be downloaded with a HTTP GET request if the response to the HEAD request does not contain a modified time, if the local file is older, or if the local file is more recent but failed to be loaded. If a skin could not be downloaded when it should but a file already exists in the `downloadedskins` folder then that file will be loaded instead.

Instead of checking whether the number of skins is different to determine whether to reload the list of skins in the settings menus, the last time that the list of skins was refreshed is now saved and compared, which is more robust. The additional check to refresh the skin list while skins are being downloaded is unnecessary, as any updates to the skin list are now covered by checking the last refresh time.
  • Loading branch information
Robyt3 committed Oct 6, 2024
1 parent 0bb829b commit 0ea7d6e
Show file tree
Hide file tree
Showing 4 changed files with 261 additions and 143 deletions.
11 changes: 3 additions & 8 deletions src/game/client/components/menus_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -717,21 +717,16 @@ void CMenus::RenderSettingsTee(CUIRect MainView)
static std::vector<CUISkin> s_vSkinList;
static std::vector<CUISkin> s_vSkinListHelper;
static std::vector<CUISkin> s_vFavoriteSkinListHelper;
static int s_SkinCount = 0;
static CListBox s_ListBox;

// be nice to the CPU
static auto s_SkinLastRebuildTime = time_get_nanoseconds();
const auto CurTime = time_get_nanoseconds();
if(m_SkinListNeedsUpdate || m_pClient->m_Skins.Num() != s_SkinCount || m_SkinFavoritesChanged || (m_pClient->m_Skins.IsDownloadingSkins() && (CurTime - s_SkinLastRebuildTime > 500ms)))
static std::chrono::nanoseconds s_SkinLastRefreshTime = m_pClient->m_Skins.LastRefreshTime();
if(m_SkinListNeedsUpdate || m_SkinFavoritesChanged || s_SkinLastRefreshTime != m_pClient->m_Skins.LastRefreshTime())
{
s_SkinLastRebuildTime = CurTime;
s_SkinLastRefreshTime = m_pClient->m_Skins.LastRefreshTime();
s_vSkinList.clear();
s_vSkinListHelper.clear();
s_vFavoriteSkinListHelper.clear();
// set skin count early, since Find of the skin class might load
// a downloading skin
s_SkinCount = m_pClient->m_Skins.Num();
m_SkinFavoritesChanged = false;

auto &&SkinNotFiltered = [&](const CSkin *pSkinToBeSelected) {
Expand Down
Loading

0 comments on commit 0ea7d6e

Please sign in to comment.