mirror of
https://github.com/luanti-org/luanti.git
synced 2025-07-22 17:18:39 +00:00
Dynamic_Add_Media v2 (#11550)
This commit is contained in:
parent
bcb6565483
commit
bbfae0cc67
19 changed files with 796 additions and 246 deletions
|
@ -204,7 +204,7 @@ const ServerCommandFactory serverCommandFactoryTable[TOSERVER_NUM_MSG_TYPES] =
|
|||
null_command_factory, // 0x3e
|
||||
null_command_factory, // 0x3f
|
||||
{ "TOSERVER_REQUEST_MEDIA", 1, true }, // 0x40
|
||||
null_command_factory, // 0x41
|
||||
{ "TOSERVER_HAVE_MEDIA", 2, true }, // 0x41
|
||||
null_command_factory, // 0x42
|
||||
{ "TOSERVER_CLIENT_READY", 1, true }, // 0x43
|
||||
null_command_factory, // 0x44
|
||||
|
|
|
@ -670,21 +670,19 @@ void Client::handleCommand_AnnounceMedia(NetworkPacket* pkt)
|
|||
m_media_downloader->addFile(name, sha1_raw);
|
||||
}
|
||||
|
||||
try {
|
||||
{
|
||||
std::string str;
|
||||
|
||||
*pkt >> str;
|
||||
|
||||
Strfnd sf(str);
|
||||
while(!sf.at_end()) {
|
||||
while (!sf.at_end()) {
|
||||
std::string baseurl = trim(sf.next(","));
|
||||
if (!baseurl.empty())
|
||||
if (!baseurl.empty()) {
|
||||
m_remote_media_servers.emplace_back(baseurl);
|
||||
m_media_downloader->addRemoteServer(baseurl);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(SerializationError& e) {
|
||||
// not supported by server or turned off
|
||||
}
|
||||
|
||||
m_media_downloader->step(this);
|
||||
}
|
||||
|
@ -716,31 +714,38 @@ void Client::handleCommand_Media(NetworkPacket* pkt)
|
|||
if (num_files == 0)
|
||||
return;
|
||||
|
||||
if (!m_media_downloader || !m_media_downloader->isStarted()) {
|
||||
const char *problem = m_media_downloader ?
|
||||
"media has not been requested" :
|
||||
"all media has been received already";
|
||||
errorstream << "Client: Received media but "
|
||||
<< problem << "! "
|
||||
<< " bunch " << bunch_i << "/" << num_bunches
|
||||
<< " files=" << num_files
|
||||
<< " size=" << pkt->getSize() << std::endl;
|
||||
return;
|
||||
bool init_phase = m_media_downloader && m_media_downloader->isStarted();
|
||||
|
||||
if (init_phase) {
|
||||
// Mesh update thread must be stopped while
|
||||
// updating content definitions
|
||||
sanity_check(!m_mesh_update_thread.isRunning());
|
||||
}
|
||||
|
||||
// Mesh update thread must be stopped while
|
||||
// updating content definitions
|
||||
sanity_check(!m_mesh_update_thread.isRunning());
|
||||
|
||||
for (u32 i=0; i < num_files; i++) {
|
||||
std::string name;
|
||||
for (u32 i = 0; i < num_files; i++) {
|
||||
std::string name, data;
|
||||
|
||||
*pkt >> name;
|
||||
data = pkt->readLongString();
|
||||
|
||||
std::string data = pkt->readLongString();
|
||||
|
||||
m_media_downloader->conventionalTransferDone(
|
||||
name, data, this);
|
||||
bool ok = false;
|
||||
if (init_phase) {
|
||||
ok = m_media_downloader->conventionalTransferDone(name, data, this);
|
||||
} else {
|
||||
// Check pending dynamic transfers, one of them must be it
|
||||
for (const auto &it : m_pending_media_downloads) {
|
||||
if (it.second->conventionalTransferDone(name, data, this)) {
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ok) {
|
||||
errorstream << "Client: Received media \"" << name
|
||||
<< "\" but no downloads pending. " << num_bunches << " bunches, "
|
||||
<< num_files << " in this one. (init_phase=" << init_phase
|
||||
<< ")" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1497,46 +1502,72 @@ void Client::handleCommand_PlayerSpeed(NetworkPacket *pkt)
|
|||
void Client::handleCommand_MediaPush(NetworkPacket *pkt)
|
||||
{
|
||||
std::string raw_hash, filename, filedata;
|
||||
u32 token;
|
||||
bool cached;
|
||||
|
||||
*pkt >> raw_hash >> filename >> cached;
|
||||
filedata = pkt->readLongString();
|
||||
if (m_proto_ver >= 40)
|
||||
*pkt >> token;
|
||||
else
|
||||
filedata = pkt->readLongString();
|
||||
|
||||
if (raw_hash.size() != 20 || filedata.empty() || filename.empty() ||
|
||||
if (raw_hash.size() != 20 || filename.empty() ||
|
||||
(m_proto_ver < 40 && filedata.empty()) ||
|
||||
!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)) {
|
||||
throw PacketError("Illegal filename, data or hash");
|
||||
}
|
||||
|
||||
verbosestream << "Server pushes media file \"" << filename << "\" with "
|
||||
<< filedata.size() << " bytes of data (cached=" << cached
|
||||
<< ")" << std::endl;
|
||||
verbosestream << "Server pushes media file \"" << filename << "\" ";
|
||||
if (filedata.empty())
|
||||
verbosestream << "to be fetched ";
|
||||
else
|
||||
verbosestream << "with " << filedata.size() << " bytes ";
|
||||
verbosestream << "(cached=" << cached << ")" << std::endl;
|
||||
|
||||
if (m_media_pushed_files.count(filename) != 0) {
|
||||
// Silently ignore for synchronization purposes
|
||||
// Ignore (but acknowledge). Previously this was for sync purposes,
|
||||
// but even in new versions media cannot be replaced at runtime.
|
||||
if (m_proto_ver >= 40)
|
||||
sendHaveMedia({ token });
|
||||
return;
|
||||
}
|
||||
|
||||
// Compute and check checksum of data
|
||||
std::string computed_hash;
|
||||
{
|
||||
SHA1 ctx;
|
||||
ctx.addBytes(filedata.c_str(), filedata.size());
|
||||
unsigned char *buf = ctx.getDigest();
|
||||
computed_hash.assign((char*) buf, 20);
|
||||
free(buf);
|
||||
}
|
||||
if (raw_hash != computed_hash) {
|
||||
verbosestream << "Hash of file data mismatches, ignoring." << std::endl;
|
||||
if (!filedata.empty()) {
|
||||
// LEGACY CODEPATH
|
||||
// Compute and check checksum of data
|
||||
std::string computed_hash;
|
||||
{
|
||||
SHA1 ctx;
|
||||
ctx.addBytes(filedata.c_str(), filedata.size());
|
||||
unsigned char *buf = ctx.getDigest();
|
||||
computed_hash.assign((char*) buf, 20);
|
||||
free(buf);
|
||||
}
|
||||
if (raw_hash != computed_hash) {
|
||||
verbosestream << "Hash of file data mismatches, ignoring." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Actually load media
|
||||
loadMedia(filedata, filename, true);
|
||||
m_media_pushed_files.insert(filename);
|
||||
|
||||
// Cache file for the next time when this client joins the same server
|
||||
if (cached)
|
||||
clientMediaUpdateCache(raw_hash, filedata);
|
||||
return;
|
||||
}
|
||||
|
||||
// Actually load media
|
||||
loadMedia(filedata, filename, true);
|
||||
m_media_pushed_files.insert(filename);
|
||||
|
||||
// Cache file for the next time when this client joins the same server
|
||||
if (cached)
|
||||
clientMediaUpdateCache(raw_hash, filedata);
|
||||
// create a downloader for this file
|
||||
auto downloader = new SingleMediaDownloader(cached);
|
||||
m_pending_media_downloads.emplace_back(token, downloader);
|
||||
downloader->addFile(filename, raw_hash);
|
||||
for (const auto &baseurl : m_remote_media_servers)
|
||||
downloader->addRemoteServer(baseurl);
|
||||
|
||||
downloader->step(this);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -207,6 +207,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
Minimap modes
|
||||
PROTOCOL VERSION 40:
|
||||
Added 'basic_debug' privilege
|
||||
TOCLIENT_MEDIA_PUSH changed, TOSERVER_HAVE_MEDIA added
|
||||
*/
|
||||
|
||||
#define LATEST_PROTOCOL_VERSION 40
|
||||
|
@ -317,9 +318,8 @@ enum ToClientCommand
|
|||
/*
|
||||
std::string raw_hash
|
||||
std::string filename
|
||||
u32 callback_token
|
||||
bool should_be_cached
|
||||
u32 len
|
||||
char filedata[len]
|
||||
*/
|
||||
|
||||
// (oops, there is some gap here)
|
||||
|
@ -938,7 +938,13 @@ enum ToServerCommand
|
|||
}
|
||||
*/
|
||||
|
||||
TOSERVER_RECEIVED_MEDIA = 0x41, // Obsolete
|
||||
TOSERVER_HAVE_MEDIA = 0x41,
|
||||
/*
|
||||
u8 number of callback tokens
|
||||
for each:
|
||||
u32 token
|
||||
*/
|
||||
|
||||
TOSERVER_BREATH = 0x42, // Obsolete
|
||||
|
||||
TOSERVER_CLIENT_READY = 0x43,
|
||||
|
|
|
@ -89,7 +89,7 @@ const ToServerCommandHandler toServerCommandTable[TOSERVER_NUM_MSG_TYPES] =
|
|||
null_command_handler, // 0x3e
|
||||
null_command_handler, // 0x3f
|
||||
{ "TOSERVER_REQUEST_MEDIA", TOSERVER_STATE_STARTUP, &Server::handleCommand_RequestMedia }, // 0x40
|
||||
null_command_handler, // 0x41
|
||||
{ "TOSERVER_HAVE_MEDIA", TOSERVER_STATE_INGAME, &Server::handleCommand_HaveMedia }, // 0x41
|
||||
null_command_handler, // 0x42
|
||||
{ "TOSERVER_CLIENT_READY", TOSERVER_STATE_STARTUP, &Server::handleCommand_ClientReady }, // 0x43
|
||||
null_command_handler, // 0x44
|
||||
|
@ -167,7 +167,7 @@ const ClientCommandFactory clientCommandFactoryTable[TOCLIENT_NUM_MSG_TYPES] =
|
|||
{ "TOCLIENT_TIME_OF_DAY", 0, true }, // 0x29
|
||||
{ "TOCLIENT_CSM_RESTRICTION_FLAGS", 0, true }, // 0x2A
|
||||
{ "TOCLIENT_PLAYER_SPEED", 0, true }, // 0x2B
|
||||
{ "TOCLIENT_MEDIA_PUSH", 0, true }, // 0x2C (sent over channel 1 too)
|
||||
{ "TOCLIENT_MEDIA_PUSH", 0, true }, // 0x2C (sent over channel 1 too if legacy)
|
||||
null_command_factory, // 0x2D
|
||||
null_command_factory, // 0x2E
|
||||
{ "TOCLIENT_CHAT_MESSAGE", 0, true }, // 0x2F
|
||||
|
|
|
@ -362,16 +362,15 @@ void Server::handleCommand_RequestMedia(NetworkPacket* pkt)
|
|||
session_t peer_id = pkt->getPeerId();
|
||||
infostream << "Sending " << numfiles << " files to " <<
|
||||
getPlayerName(peer_id) << std::endl;
|
||||
verbosestream << "TOSERVER_REQUEST_MEDIA: " << std::endl;
|
||||
verbosestream << "TOSERVER_REQUEST_MEDIA: requested file(s)" << std::endl;
|
||||
|
||||
for (u16 i = 0; i < numfiles; i++) {
|
||||
std::string name;
|
||||
|
||||
*pkt >> name;
|
||||
|
||||
tosend.push_back(name);
|
||||
verbosestream << "TOSERVER_REQUEST_MEDIA: requested file "
|
||||
<< name << std::endl;
|
||||
tosend.emplace_back(name);
|
||||
verbosestream << " " << name << std::endl;
|
||||
}
|
||||
|
||||
sendRequestedMedia(peer_id, tosend);
|
||||
|
@ -1801,3 +1800,30 @@ void Server::handleCommand_ModChannelMsg(NetworkPacket *pkt)
|
|||
|
||||
broadcastModChannelMessage(channel_name, channel_msg, peer_id);
|
||||
}
|
||||
|
||||
void Server::handleCommand_HaveMedia(NetworkPacket *pkt)
|
||||
{
|
||||
std::vector<u32> tokens;
|
||||
u8 numtokens;
|
||||
|
||||
*pkt >> numtokens;
|
||||
for (u16 i = 0; i < numtokens; i++) {
|
||||
u32 n;
|
||||
*pkt >> n;
|
||||
tokens.emplace_back(n);
|
||||
}
|
||||
|
||||
const session_t peer_id = pkt->getPeerId();
|
||||
auto player = m_env->getPlayer(peer_id);
|
||||
|
||||
for (const u32 token : tokens) {
|
||||
auto it = m_pending_dyn_media.find(token);
|
||||
if (it == m_pending_dyn_media.end())
|
||||
continue;
|
||||
if (it->second.waiting_players.count(peer_id)) {
|
||||
it->second.waiting_players.erase(peer_id);
|
||||
if (player)
|
||||
getScriptIface()->on_dynamic_media_added(token, player->getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue