mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-03-06 22:28:56 +00:00
(svn r15632) -Feature: allow downloading scenarios and heightmaps via bananas.
This commit is contained in:
parent
bc58d4ef9a
commit
406832fed8
111
src/fios.cpp
111
src/fios.cpp
@ -495,3 +495,114 @@ void FiosGetHeightmapList(SaveLoadDialogMode mode)
|
||||
|
||||
FiosGetFileList(mode, &FiosGetHeightmapListCallback, strcmp(base_path, _fios_path) == 0 ? HEIGHTMAP_DIR : NO_DIRECTORY);
|
||||
}
|
||||
|
||||
#if defined(ENABLE_NETWORK)
|
||||
#include "core/smallvec_type.hpp"
|
||||
#include "network/network_content.h"
|
||||
#include "md5.h"
|
||||
|
||||
/** Basic data to distinguish a scenario. Used in the server list window */
|
||||
struct ScenarioIdentifier {
|
||||
uint32 scenid; ///< ID for the scenario (generated by content)
|
||||
uint8 md5sum[16]; ///< MD5 checksum of file
|
||||
|
||||
bool operator == (const ScenarioIdentifier &other) const
|
||||
{
|
||||
return this->scenid == other.scenid &&
|
||||
memcmp(this->md5sum, other.md5sum, sizeof(this->md5sum)) == 0;
|
||||
}
|
||||
|
||||
bool operator != (const ScenarioIdentifier &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Scanner to find the unique IDs of scenarios
|
||||
*/
|
||||
class ScenarioScanner : protected FileScanner, public SmallVector<ScenarioIdentifier, 8> {
|
||||
bool scanned; ///< Whether we've already scanned
|
||||
public:
|
||||
/** Initialise */
|
||||
ScenarioScanner() : scanned(false) {}
|
||||
|
||||
/**
|
||||
* Scan, but only if it's needed.
|
||||
* @param rescan whether to force scanning even when it's not necessary
|
||||
*/
|
||||
void Scan(bool rescan)
|
||||
{
|
||||
if (this->scanned && !rescan) return;
|
||||
|
||||
this->FileScanner::Scan(".id", SCENARIO_DIR, true, true);
|
||||
this->scanned = true;
|
||||
}
|
||||
|
||||
/* virtual */ bool AddFile(const char *filename, size_t basepath_length)
|
||||
{
|
||||
FILE *f = FioFOpenFile(filename, "r");
|
||||
if (f == NULL) return false;
|
||||
|
||||
ScenarioIdentifier id;
|
||||
fscanf(f, "%i", &id.scenid);
|
||||
FioFCloseFile(f);
|
||||
|
||||
Md5 checksum;
|
||||
uint8 buffer[1024];
|
||||
size_t len, size;
|
||||
|
||||
/* open the scenario file, but first get the name.
|
||||
* This is safe as we check on extension which
|
||||
* must always exist. */
|
||||
*strrchr(filename, '.') = '\0';
|
||||
f = FioFOpenFile(filename, "rb", SCENARIO_DIR, &size);
|
||||
if (f == NULL) return false;
|
||||
|
||||
/* calculate md5sum */
|
||||
while ((len = fread(buffer, 1, (size > sizeof(buffer)) ? sizeof(buffer) : size, f)) != 0 && size != 0) {
|
||||
size -= len;
|
||||
checksum.Append(buffer, len);
|
||||
}
|
||||
checksum.Finish(id.md5sum);
|
||||
|
||||
FioFCloseFile(f);
|
||||
|
||||
this->Include(id);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/** Scanner for scenarios */
|
||||
static ScenarioScanner _scanner;
|
||||
|
||||
/**
|
||||
* Check whether we've got a given scenario based on it's unique ID.
|
||||
* @param ci the content info to compare it to
|
||||
* @param md5sum whether to look at the md5sum or the id
|
||||
* @return true if we've got the scenario
|
||||
*/
|
||||
bool HasScenario(const ContentInfo *ci, bool md5sum)
|
||||
{
|
||||
_scanner.Scan(false);
|
||||
|
||||
for (ScenarioIdentifier *id = _scanner.Begin(); id != _scanner.End(); id++) {
|
||||
if (md5sum ?
|
||||
(memcmp(id->md5sum, ci->md5sum, sizeof(id->md5sum)) == 0) :
|
||||
(id->scenid == ci->unique_id)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Force a (re)scan of the scenarios.
|
||||
*/
|
||||
void ScanScenarios()
|
||||
{
|
||||
_scanner.Scan(true);
|
||||
}
|
||||
|
||||
#endif /* ENABLE_NETWORK */
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
extern bool TarListAddFile(const char *filename);
|
||||
extern bool HasGraphicsSet(const ContentInfo *ci, bool md5sum);
|
||||
extern bool HasScenario(const ContentInfo *ci, bool md5sum);
|
||||
ClientNetworkContentSocketHandler _network_content_client;
|
||||
|
||||
/** Wrapper function for the HasProc */
|
||||
@ -86,6 +87,11 @@ DEF_CONTENT_RECEIVE_COMMAND(Client, PACKET_CONTENT_SERVER_INFO)
|
||||
proc = AI::HasAI; break;
|
||||
break;
|
||||
|
||||
case CONTENT_TYPE_SCENARIO:
|
||||
case CONTENT_TYPE_HEIGHTMAP:
|
||||
proc = HasScenario;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -143,6 +149,8 @@ void ClientNetworkContentSocketHandler::RequestContentList(ContentType type)
|
||||
{
|
||||
if (type == CONTENT_TYPE_END) {
|
||||
this->RequestContentList(CONTENT_TYPE_BASE_GRAPHICS);
|
||||
this->RequestContentList(CONTENT_TYPE_SCENARIO);
|
||||
this->RequestContentList(CONTENT_TYPE_HEIGHTMAP);
|
||||
this->RequestContentList(CONTENT_TYPE_AI);
|
||||
this->RequestContentList(CONTENT_TYPE_NEWGRF);
|
||||
this->RequestContentList(CONTENT_TYPE_AI_LIBRARY);
|
||||
|
@ -98,6 +98,13 @@ public:
|
||||
InvalidateWindowData(WC_NETWORK_WINDOW, 0, 2);
|
||||
break;
|
||||
|
||||
case CONTENT_TYPE_SCENARIO:
|
||||
case CONTENT_TYPE_HEIGHTMAP:
|
||||
InvalidateWindowClasses(WC_SAVELOAD);
|
||||
extern void ScanScenarios();
|
||||
ScanScenarios();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user