From 2d3078f851fe916a6db076fbfb3f496c0ef8c0ff Mon Sep 17 00:00:00 2001 From: ds Date: Sat, 11 Jul 2020 20:34:26 +0300 Subject: [PATCH] graph: save narrow places to file, so, bump graph version. graph: allow saving / loading graph manually on dedicated server. config: fix parsing for difficulty.cfg fixes #142 fix: restore fakeclient bit on entity flags every frame. --- LICENSE.txt | 2 +- ext/crlib/cr-ulz.h | 5 ++++- inc/graph.h | 4 +++- meson.build | 2 +- src/botlib.cpp | 2 ++ src/config.cpp | 2 +- src/control.cpp | 21 +++++++++++++++++++-- src/graph.cpp | 47 +++++++++++++++++++++++++++++++++------------- 8 files changed, 65 insertions(+), 20 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index 9e419e0..20d40b6 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -GNU GENERAL PUBLIC LICENSE + GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. diff --git a/ext/crlib/cr-ulz.h b/ext/crlib/cr-ulz.h index f339918..a4d2b6d 100644 --- a/ext/crlib/cr-ulz.h +++ b/ext/crlib/cr-ulz.h @@ -20,7 +20,7 @@ CR_NAMESPACE_BEGIN // see https://github.com/encode84/ulz/ -class ULZ final : DenyCopying { +class ULZ final : public Singleton { public: enum : int32 { Excess = 16, @@ -314,4 +314,7 @@ private: } }; +// expose global ulz object +CR_EXPOSE_GLOBAL_SINGLETON (ULZ, ulz); + CR_NAMESPACE_END diff --git a/inc/graph.h b/inc/graph.h index 91c07ae..5864a70 100644 --- a/inc/graph.h +++ b/inc/graph.h @@ -83,7 +83,7 @@ CR_DECLARE_SCOPED_ENUM (StorageOption, // storage header versions CR_DECLARE_SCOPED_ENUM (StorageVersion, - Graph = 1, + Graph = 2, Practice = 1, Vistable = 1, Matrix = 1, @@ -251,6 +251,7 @@ private: int x, y, z; }; + int m_version; int m_editFlags; int m_loadAttempts; int m_cacheNodeIndex; @@ -325,6 +326,7 @@ public: bool saveGraphData (); bool loadGraphData (); + bool canDownload (); template bool saveStorage (StringRef ext, StringRef name, StorageOption options, StorageVersion version, const SmallArray &data, ExtenHeader *exten); template bool loadStorage (StringRef ext, StringRef name, StorageOption options, StorageVersion version, SmallArray &data, ExtenHeader *exten, int32 *outOptions); diff --git a/meson.build b/meson.build index 1aee964..3f003ce 100644 --- a/meson.build +++ b/meson.build @@ -70,7 +70,7 @@ cdata.set ('commitCount', run_command ('git', 'rev-list', '--count', 'HEAD').std cdata.set ('commitAuthor', run_command ('git', 'log', '--pretty="%ae"', '-1').stdout ().strip ()) cdata.set ('buildVersion', buildVersion) -cdata.set ('buildMachine', run_command ('hostname').stdout ().strip ()) +cdata.set ('buildMachine', run_command ('hostname', '-f').stdout ().strip ()) cdata.set ('buildCompiler', compilerId + ' ' + compilerVersion) configure_file (input: 'inc/version.h.in', output: 'version.build.h', configuration: cdata) diff --git a/src/botlib.cpp b/src/botlib.cpp index 18db4da..02dc84c 100644 --- a/src/botlib.cpp +++ b/src/botlib.cpp @@ -2940,6 +2940,8 @@ void Bot::frame () { } void Bot::update () { + pev->flags |= FL_FAKECLIENT; // restore fake client bit + pev->button = 0; m_moveSpeed = 0.0f; diff --git a/src/config.cpp b/src/config.cpp index c84074d..0806c66 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -586,7 +586,7 @@ void BotConfig::loadDifficultyConfig () { if (util.openConfig ("difficulty.cfg", "Difficulty config file not found. Loading defaults.", &file)) { while (file.getLine (line)) { - if (isCommentLine (line)) { + if (isCommentLine (line) || line.length () < 3) { continue; } auto items = line.split ("="); diff --git a/src/control.cpp b/src/control.cpp index afcccf2..0a1df8a 100644 --- a/src/control.cpp +++ b/src/control.cpp @@ -269,8 +269,25 @@ int BotControl::cmdCvars () { int BotControl::cmdNode () { enum args { root, alias, cmd, cmd2 }; + static Array allowedOnDedicatedServer { + "acquire_editor", + "upload", + "save", + "load" + }; + + // check if cmd is allowed on dedicated server + auto isAllowedOnDedicatedServer = [] (StringRef str) -> bool { + for (const auto &test : allowedOnDedicatedServer) { + if (test == str) { + return true; + } + } + return false; + }; + // graph editor supported only with editor - if (game.isDedicated () && !graph.hasEditor () && strValue (cmd) != "acquire_editor" && strValue (cmd) != "upload") { + if (game.isDedicated () && !graph.hasEditor () && !isAllowedOnDedicatedServer (strValue (cmd))) { msg ("Unable to use graph edit commands without setting graph editor player. Please use \"graph acquire_editor\" to acquire rights for graph editing."); return BotCommandResult::Handled; } @@ -738,7 +755,7 @@ int BotControl::cmdNodeUpload () { http.setTimeout (6); // try to upload the file - if (http.uploadFile ("http://yapb.ru/graph", strings.format ("%sgraph/%s.graph", graph.getDataDirectory (false), game.getMapName ()))) { + if (http.uploadFile (strings.format ("http://%s/graph", product.download), strings.format ("%sgraph/%s.graph", graph.getDataDirectory (false), game.getMapName ()))) { msg ("Graph file was successfully validated and uploaded to the YaPB Graph DB (%s).", product.download); msg ("It will be available for download for all YaPB users in a few minutes."); msg ("\n"); diff --git a/src/graph.cpp b/src/graph.cpp index 5b28b24..acb0b11 100644 --- a/src/graph.cpp +++ b/src/graph.cpp @@ -16,7 +16,7 @@ #include ConVar cv_graph_fixcamp ("yb_graph_fixcamp", "1", "Specifies whether bot should not 'fix' camp directions of camp waypoints when loading old PWF format."); -ConVar cv_graph_url ("yb_graph_url", product.download.chars (), "Specifies the URL from bots will be able to download graph in case of missing local one.", false, 0.0f, 0.0f); +ConVar cv_graph_url ("yb_graph_url", product.download.chars (), "Specifies the URL from bots will be able to download graph in case of missing local one. Set to empty, if no downloads needed.", false, 0.0f, 0.0f); void BotGraph::initGraph () { // this function initialize the graph structures.. @@ -1316,6 +1316,13 @@ void BotGraph::initNarrowPlaces () { if (m_paths.empty () || m_narrowChecked) { return; } + constexpr int32 kNarrowPlacesMinGraphVersion = 2; + + // if version 2 or higher, narrow places already initialized and saved into file + if (m_version >= kNarrowPlacesMinGraphVersion) { + m_narrowChecked = true; + return; + } TraceResult tr; const auto distance = 178.0f; @@ -1518,13 +1525,11 @@ template bool BotGraph::saveStorage (StringRef ext, StringRef name, return false; } - ULZ lz; - int32 rawLength = data.template length () * sizeof (U); SmallArray compressed (rawLength + sizeof (uint8) * ULZ::Excess); // try to compress - auto compressedLength = lz.compress (reinterpret_cast (data.data ()), rawLength, reinterpret_cast (compressed.data ())); + auto compressedLength = ulz.compress (reinterpret_cast (data.data ()), rawLength, reinterpret_cast (compressed.data ())); if (compressedLength > 0) { StorageHeader hdr {}; @@ -1585,11 +1590,11 @@ template bool BotGraph::loadStorage (StringRef ext, StringRef name, // downloader for graph auto download = [&] () -> bool { - auto downloadAddress = cv_graph_url.str (); - - if (strings.isEmpty (downloadAddress)) { + if (!graph.canDownload ()) { return false; } + auto downloadAddress = cv_graph_url.str (); + auto toDownload = strings.format ("%sgraph/%s", getDataDirectory (false), filename); auto fromDownload = strings.format ("http://%s/graph/%s", downloadAddress, filename); @@ -1599,7 +1604,7 @@ template bool BotGraph::loadStorage (StringRef ext, StringRef name, return true; } else { - game.print ("Can't download '%s'. from '%s' to '%s'... (%d).", filename, fromDownload, toDownload, http.getLastStatusCode ()); + game.print ("Can't download '%s' from '%s' to '%s'... (%d).", filename, fromDownload, toDownload, http.getLastStatusCode ()); } return false; }; @@ -1656,13 +1661,18 @@ template bool BotGraph::loadStorage (StringRef ext, StringRef name, } // check the version - if (hdr.version != version) { + if (hdr.version > version) { if (tryReload ()) { return true; } return raiseLoadingError (isGraph, file, "Damaged %s (filename: '%s'). Version number differs (got: '%d', need: '%d').", name, filename, hdr.version, version); } + // save graph version + if (isGraph) { + m_version = hdr.version; + } + // check the storage type if ((hdr.options & options) != options) { return raiseLoadingError (isGraph, file, "Incorrect storage format for %s (filename: '%s').", name, filename); @@ -1676,10 +1686,9 @@ template bool BotGraph::loadStorage (StringRef ext, StringRef name, // read compressed data if (file.read (compressed.data (), sizeof (uint8), hdr.compressed) == static_cast (hdr.compressed)) { - ULZ lz; // try to uncompress - if (lz.uncompress (compressed.data (), hdr.compressed, reinterpret_cast (data.data ()), hdr.uncompressed) == ULZ::UncompressFailure) { + if (ulz.uncompress (compressed.data (), hdr.compressed, reinterpret_cast (data.data ()), hdr.uncompressed) == ULZ::UncompressFailure) { return raiseLoadingError (isGraph, file, "Unable to decompress ULZ data for %s (filename: '%s').", name, filename); } else { @@ -1692,7 +1701,7 @@ template bool BotGraph::loadStorage (StringRef ext, StringRef name, if ((hdr.options & StorageOption::Exten) && exten != nullptr) { file.read (exten, sizeof (ExtenHeader)); } - game.print ("Successfully loaded Bots %s data (%d/%.2fMB).", name, m_paths.length (), static_cast (data.capacity () * sizeof (U)) / 1024.0f / 1024.0f); + game.print ("Successfully loaded Bots %s data v%d.0 (%d/%.2fMB).", name, hdr.version, m_paths.length (), static_cast (data.capacity () * sizeof (U)) / 1024.0f / 1024.0f); file.close (); return true; @@ -1747,6 +1756,10 @@ bool BotGraph::loadGraphData () { return false; } +bool BotGraph::canDownload () { + return !strings.isEmpty (cv_graph_url.str ()); +} + bool BotGraph::saveGraphData () { auto options = StorageOption::Graph | StorageOption::Exten; String author; @@ -1754,7 +1767,9 @@ bool BotGraph::saveGraphData () { if (game.isNullEntity (m_editor) && !m_tempStrings.empty ()) { author = m_tempStrings; - options |= StorageOption::Recovered; + if (!game.isDedicated ()) { + options |= StorageOption::Recovered; + } } else if (!game.isNullEntity (m_editor)) { author = m_editor->v.netname.chars (); @@ -1772,6 +1787,10 @@ bool BotGraph::saveGraphData () { strings.copy (exten.author, author.chars (), cr::bufsize (exten.author)); exten.mapSize = engfuncs.pfnGetFileSize (strings.format ("maps/%s.bsp", game.getMapName ())); + // ensure narrow places saved into file + m_narrowChecked = false; + initNarrowPlaces (); + return saveStorage ("graph", "Graph", static_cast (options), StorageVersion::Graph, m_paths, &exten); } @@ -2798,8 +2817,10 @@ BotGraph::BotGraph () { m_rescuePoints.clear (); m_sniperPoints.clear (); + m_version = StorageVersion::Graph; m_loadAttempts = 0; m_editFlags = 0; + m_pathDisplayTime = 0.0f; m_arrowDisplayTime = 0.0f; m_autoPathDistance = 250.0f;