2025-07-06 20:43:53 +03:00
# include "ResourceManager.hpp"
# include "Helpers/Networking/NetLibrary.hpp"
# include <include/core/SkImage.h>
2025-08-07 12:44:31 +03:00
# include "ResourceDisplay/SvgResourceDisplay.hpp"
2025-07-06 20:43:53 +03:00
# include "Server/CommandList.hpp"
# include "ResourceDisplay/ImageResourceDisplay.hpp"
# include "ResourceDisplay/FileResourceDisplay.hpp"
# include <cereal/types/string.hpp>
# include <Helpers/Logger.hpp>
# include <optional>
# include <sstream>
# include <fstream>
# include "World.hpp"
# include "ResourceDisplay/FileResourceDisplay.hpp"
ResourceManager : : ResourceManager ( World & initWorld ) :
world ( initWorld )
{ }
void ResourceManager : : init_client_callbacks ( ) {
2025-10-09 21:02:19 +03:00
world . con . client_add_recv_callback ( CLIENT_NEW_RESOURCE_ID , [ & ] ( cereal : : PortableBinaryInputArchive & message ) {
2025-10-10 10:34:12 +03:00
message ( resourceBeingRetrievedClient ) ;
2025-07-06 20:43:53 +03:00
} ) ;
2025-10-09 21:02:19 +03:00
world . con . client_add_recv_callback ( CLIENT_NEW_RESOURCE_DATA , [ & ] ( cereal : : PortableBinaryInputArchive & message ) {
2025-10-10 10:34:12 +03:00
message ( resources [ resourceBeingRetrievedClient ] ) ;
Logger : : get ( ) . log ( " INFO " , " Received new resource with id: " + std : : to_string ( resourceBeingRetrievedClient . first ) + " " + std : : to_string ( resourceBeingRetrievedClient . second ) + " of size " + std : : to_string ( resources [ resourceBeingRetrievedClient ] . data - > size ( ) ) ) ;
resourceBeingRetrievedClient = { 0 , 0 } ;
2025-10-09 21:02:19 +03:00
} ) ;
}
2025-10-10 10:34:12 +03:00
float ResourceManager : : get_resource_retrieval_progress ( const ServerClientID & id ) {
if ( id = = ServerClientID { 0 , 0 } )
2025-10-09 21:02:19 +03:00
return 0.0f ;
2025-10-10 10:34:12 +03:00
if ( world . con . host_exists ( ) & & ! world . con . is_host_disconnected ( ) ) {
auto it = serverDownloadProgress . find ( id ) ;
if ( it = = serverDownloadProgress . end ( ) )
return 0.0f ;
else {
auto & progressBytes = it - > second ;
if ( progressBytes . totalBytes = = 0 )
return 0.0f ;
return static_cast < float > ( progressBytes . downloadedBytes ) / static_cast < float > ( progressBytes . totalBytes ) ;
}
}
else if ( world . con . client_exists ( ) & & ! world . con . is_client_disconnected ( ) ) {
if ( id ! = resourceBeingRetrievedClient )
return 0.0f ;
else {
NetLibrary : : DownloadProgress progressBytes = world . con . client_get_resource_retrieval_progress ( ) ;
if ( progressBytes . totalBytes = = 0 )
return 0.0f ;
return static_cast < float > ( progressBytes . downloadedBytes ) / static_cast < float > ( progressBytes . totalBytes ) ;
}
}
return 0.0f ;
2025-07-06 20:43:53 +03:00
}
void ResourceManager : : update ( ) {
2025-10-10 10:34:12 +03:00
if ( ! world . con . host_exists ( ) | | world . con . is_host_disconnected ( ) )
serverDownloadProgress . clear ( ) ;
else
serverDownloadProgress = world . con . server_get_resource_retrieval_progress ( ) ;
2025-07-06 20:43:53 +03:00
for ( auto & [ k , v ] : displays )
v - > update ( world ) ;
}
2025-11-21 08:35:47 +03:00
ServerClientID ResourceManager : : add_resource_file ( const std : : filesystem : : path & filePath ) {
2025-07-06 20:43:53 +03:00
// https://nullptr.org/cpp-read-file-into-string/
2025-11-21 08:35:47 +03:00
std : : ifstream file ( filePath , std : : ios : : in | std : : ios : : binary | std : : ios : : ate ) ;
2025-07-06 20:43:53 +03:00
if ( ! file . is_open ( ) ) {
2025-11-21 10:03:11 +03:00
Logger : : get ( ) . log ( " INFO " , " [ResourceManager::add_resource_file] Could not open file " + filePath . string ( ) ) ;
2025-07-06 20:43:53 +03:00
return { 0 , 0 } ;
}
size_t resourcesize ;
auto tellgResult = file . tellg ( ) ;
if ( tellgResult = = - 1 ) {
2025-11-21 10:03:11 +03:00
Logger : : get ( ) . log ( " INFO " , " [ResourceManager::add_resource_file] tellg failed for file " + filePath . string ( ) ) ;
2025-07-06 20:43:53 +03:00
return { 0 , 0 } ;
}
resourcesize = static_cast < size_t > ( tellgResult ) ;
file . seekg ( 0 , std : : ios_base : : beg ) ;
ResourceData resource ;
resource . data = std : : make_shared < std : : string > ( ) ;
2025-11-21 08:35:47 +03:00
resource . name = std : : filesystem : : path ( filePath ) . filename ( ) . string ( ) ;
2025-07-06 20:43:53 +03:00
std : : string & toPlaceIn = * resource . data ;
toPlaceIn . resize ( resourcesize ) ;
file . read ( toPlaceIn . data ( ) , resourcesize ) ;
file . close ( ) ;
2025-11-21 08:35:47 +03:00
Logger : : get ( ) . log ( " INFO " , " [ResourceManager::add_resource_file] Successfully read file " + filePath . string ( ) ) ;
2025-07-06 20:43:53 +03:00
return add_resource ( resource ) ;
}
ServerClientID ResourceManager : : add_resource ( const ResourceData & resource ) {
auto it = std : : find_if ( resources . begin ( ) , resources . end ( ) , [ & ] ( const auto & p ) {
return p . second . data = = resource . data | | ( * p . second . data ) = = ( * resource . data ) ;
} ) ;
if ( it ! = resources . end ( ) ) {
Logger : : get ( ) . log ( " INFO " , " [ResourceManager::add_resource] File " + std : : string ( resource . name ) + " is a duplicate " ) ;
return it - > first ;
}
ServerClientID newID = world . get_new_id ( ) ;
resources [ newID ] = resource ;
2025-10-10 10:34:12 +03:00
world . con . client_send_items_to_server ( RESOURCE_COMMAND_CHANNEL , SERVER_NEW_RESOURCE_ID , newID ) ;
world . con . client_send_items_to_server ( RESOURCE_COMMAND_CHANNEL , SERVER_NEW_RESOURCE_DATA , resource ) ;
2025-07-06 20:43:53 +03:00
return newID ;
}
void ResourceManager : : copy_resource_set_to_map ( const std : : unordered_set < ServerClientID > & resourceSet , std : : unordered_map < ServerClientID , ResourceData > & resourceMap ) const {
resourceMap . clear ( ) ;
for ( auto & [ k , v ] : resources ) {
if ( resourceSet . contains ( k ) )
resourceMap [ k ] = v ;
}
}
ClientPortionID ResourceManager : : get_max_id ( ServerPortionID serverID ) const {
ClientPortionID maxClientID = 0 ;
for ( auto & p : resources ) {
if ( p . first . first = = serverID )
maxClientID = std : : max ( maxClientID , p . first . second ) ;
}
return maxClientID ;
}
std : : optional < ResourceData > ResourceManager : : get_resource ( const ServerClientID & id ) const {
auto it = resources . find ( id ) ;
if ( it = = resources . end ( ) )
return std : : nullopt ;
return it - > second ;
}
2025-10-10 18:41:08 +03:00
ResourceDisplay * ResourceManager : : get_display_data ( const ServerClientID & fileID ) {
2025-07-06 20:43:53 +03:00
auto loadedDisplayIt = displays . find ( fileID ) ;
if ( loadedDisplayIt ! = displays . end ( ) )
2025-10-10 18:41:08 +03:00
return loadedDisplayIt - > second . get ( ) ;
2025-07-06 20:43:53 +03:00
auto resourceIt = resources . find ( fileID ) ;
if ( resourceIt = = resources . end ( ) )
return nullptr ;
2025-10-10 18:41:08 +03:00
auto imgResource ( std : : make_unique < ImageResourceDisplay > ( ) ) ;
2025-08-07 17:45:10 +03:00
if ( imgResource - > load ( * this , resourceIt - > second . name , * resourceIt - > second . data ) ) {
2025-10-10 18:41:08 +03:00
displays . emplace ( fileID , std : : move ( imgResource ) ) ;
return displays [ fileID ] . get ( ) ;
2025-07-06 20:43:53 +03:00
}
2025-10-10 18:41:08 +03:00
auto svgResource ( std : : make_unique < SvgResourceDisplay > ( ) ) ;
2025-08-07 17:45:10 +03:00
if ( svgResource - > load ( * this , resourceIt - > second . name , * resourceIt - > second . data ) ) {
2025-10-10 18:41:08 +03:00
displays . emplace ( fileID , std : : move ( svgResource ) ) ;
return displays [ fileID ] . get ( ) ;
2025-08-07 12:44:31 +03:00
}
2025-10-10 18:41:08 +03:00
auto fileResource ( std : : make_unique < FileResourceDisplay > ( ) ) ;
2025-08-07 17:45:10 +03:00
fileResource - > load ( * this , resourceIt - > second . name , * resourceIt - > second . data ) ;
2025-10-10 18:41:08 +03:00
displays . emplace ( fileID , std : : move ( fileResource ) ) ;
return displays [ fileID ] . get ( ) ;
2025-07-06 20:43:53 +03:00
}
const std : : unordered_map < ServerClientID , ResourceData > & ResourceManager : : resource_list ( ) {
return resources ;
}