summaryrefslogtreecommitdiff
path: root/src/fios.cpp
diff options
context:
space:
mode:
authorrubidium <rubidium@openttd.org>2009-03-06 19:33:45 +0000
committerrubidium <rubidium@openttd.org>2009-03-06 19:33:45 +0000
commit406832fed8008718aad8005215c1ecfbdb6f9d3a (patch)
tree785d2e3194f2744aa1c4620d6c6364ac056d5a8a /src/fios.cpp
parentbc58d4ef9a13623f1b7c679a298940383c6b4a20 (diff)
downloadopenttd-406832fed8008718aad8005215c1ecfbdb6f9d3a.tar.xz
(svn r15632) -Feature: allow downloading scenarios and heightmaps via bananas.
Diffstat (limited to 'src/fios.cpp')
-rw-r--r--src/fios.cpp111
1 files changed, 111 insertions, 0 deletions
diff --git a/src/fios.cpp b/src/fios.cpp
index 3fb5dabe4..3a365e62f 100644
--- a/src/fios.cpp
+++ b/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 */