aim: do not reduce prediction for grenades

refactor: standardize access to bot files
graph: allow to specify graph upload url via cvar
graph. do not spam if extensions files  are not found
This commit is contained in:
jeefo 2023-04-13 03:05:35 +03:00
commit 9c73a070b7
No known key found for this signature in database
GPG key ID: 927BCA0779BEA8ED
11 changed files with 160 additions and 86 deletions

View file

@ -446,7 +446,7 @@ Successfully saved Bots %s data.
Bot %s Daten wurden erfolgreich gespeichert. Bot %s Daten wurden erfolgreich gespeichert.
[ORIGINAL] [ORIGINAL]
Successfully loaded Bots %s data v%d (%d/%.2fMB). Loaded Bots %s data v%d (%d/%.2fMB).
[TRANSLATED] [TRANSLATED]
Bot %s Daten v%d wurden erfolgreich geladen (%d/%.2fMB). Bot %s Daten v%d wurden erfolgreich geladen (%d/%.2fMB).

View file

@ -544,7 +544,7 @@ Successfully saved Bots %s data.
Успешно сохранены данные %s ботов. Успешно сохранены данные %s ботов.
[ORIGINAL] [ORIGINAL]
Successfully loaded Bots %s data v%d (%d/%.2fMB). Loaded Bots %s data v%d (%d/%.2fMB).
[TRANSLATED] [TRANSLATED]
Успешно загружены данные %s ботов v%d (%d/%.2fМБ). Успешно загружены данные %s ботов v%d (%d/%.2fМБ).

View file

@ -343,8 +343,8 @@ public:
bool loadGraphData (); bool loadGraphData ();
bool canDownload (); bool canDownload ();
template <typename U> bool saveStorage (StringRef ext, StringRef name, StorageOption options, StorageVersion version, const SmallArray <U> &data, ExtenHeader *exten); template <typename U> bool saveStorage (StringRef name, StorageOption options, StorageVersion version, const SmallArray <U> &data, ExtenHeader *exten);
template <typename U> bool loadStorage (StringRef ext, StringRef name, StorageOption options, StorageVersion version, SmallArray <U> &data, ExtenHeader *exten, int32_t *outOptions); template <typename U> bool loadStorage (StringRef name, StorageOption options, StorageVersion version, SmallArray <U> &data, ExtenHeader *exten, int32_t *outOptions);
template <typename ...Args> bool raiseLoadingError (bool isGraph, MemFile &file, const char *fmt, Args &&...args); template <typename ...Args> bool raiseLoadingError (bool isGraph, MemFile &file, const char *fmt, Args &&...args);
void saveOldFormat (); void saveOldFormat ();
@ -389,9 +389,6 @@ public:
void showStats (); void showStats ();
void showFileInfo (); void showFileInfo ();
const char *getDataDirectory (bool isMemoryFile = false);
const char *getOldFormatGraphName (bool isMemoryFile = false);
IntArray getNarestInRadius (float radius, const Vector &origin, int maxCount = -1); IntArray getNarestInRadius (float radius, const Vector &origin, int maxCount = -1);
const IntArray &getNodesInBucket (const Vector &pos); const IntArray &getNodesInBucket (const Vector &pos);
@ -490,7 +487,11 @@ public:
// helper for reporting load errors // helper for reporting load errors
template <typename ...Args> bool BotGraph::raiseLoadingError (bool isGraph, MemFile &file, const char *fmt, Args &&...args) { template <typename ...Args> bool BotGraph::raiseLoadingError (bool isGraph, MemFile &file, const char *fmt, Args &&...args) {
auto result = strings.format (fmt, cr::forward <Args> (args)...); auto result = strings.format (fmt, cr::forward <Args> (args)...);
// display error only for graph file
if (isGraph || cv_debug.bool_ ()) {
logger.error (result); logger.error (result);
}
// if graph reset paths // if graph reset paths
if (isGraph) { if (isGraph) {

View file

@ -7,6 +7,16 @@
#pragma once #pragma once
CR_DECLARE_SCOPED_ENUM_TYPE (BotFile, uint32_t,
Vistable = 0,
LogFile = 1,
Practice = 2,
Graph = 3,
Pathmatrix = 4,
PodbotPWF = 5,
EbotEWP = 6
)
class BotSupport final : public Singleton <BotSupport> { class BotSupport final : public Singleton <BotSupport> {
private: private:
bool m_needToSendWelcome {}; bool m_needToSendWelcome {};
@ -96,6 +106,12 @@ public:
// get the current date and time as string // get the current date and time as string
String getCurrentDateTime (); String getCurrentDateTime ();
// builds the filename to requested filename
String buildPath (int32_t type, bool isMemoryLoad = false);
// converts storage option to stroage filename
int32_t storageToBotFile (StorageOption options);
public: public:
// re-show welcome after changelevel ? // re-show welcome after changelevel ?

View file

@ -1211,6 +1211,7 @@ extern ConVar cv_debug_goal;
extern ConVar cv_save_bots_names; extern ConVar cv_save_bots_names;
extern ConVar cv_random_knife_attacks; extern ConVar cv_random_knife_attacks;
extern ConVar cv_rotate_bots; extern ConVar cv_rotate_bots;
extern ConVar cv_graph_url_upload;
extern ConVar mp_freezetime; extern ConVar mp_freezetime;
extern ConVar mp_roundtime; extern ConVar mp_roundtime;

View file

@ -3992,7 +3992,7 @@ void Bot::throwExplosive_ () {
m_moveToGoal = false; m_moveToGoal = false;
} }
else if (!(m_states & Sense::SuspectEnemy) && !game.isNullEntity (m_enemy)) { else if (!(m_states & Sense::SuspectEnemy) && !game.isNullEntity (m_enemy)) {
dest = m_enemy->v.origin + m_enemy->v.velocity.get2d () * 0.6f; dest = m_enemy->v.origin + m_enemy->v.velocity.get2d ();
} }
m_isUsingGrenade = true; m_isUsingGrenade = true;
m_checkTerrain = false; m_checkTerrain = false;
@ -4058,7 +4058,7 @@ void Bot::throwFlashbang_ () {
m_moveToGoal = false; m_moveToGoal = false;
} }
else if (!(m_states & Sense::SuspectEnemy) && !game.isNullEntity (m_enemy)) { else if (!(m_states & Sense::SuspectEnemy) && !game.isNullEntity (m_enemy)) {
dest = m_enemy->v.origin + m_enemy->v.velocity.get2d () * 0.6f; dest = m_enemy->v.origin + m_enemy->v.velocity.get2d ();
} }
m_isUsingGrenade = true; m_isUsingGrenade = true;
@ -4129,9 +4129,9 @@ void Bot::throwSmoke_ () {
Vector src = m_lastEnemyOrigin - pev->velocity; Vector src = m_lastEnemyOrigin - pev->velocity;
// predict where the enemy is in 0.5 secs // predict where the enemy is in secs
if (!game.isNullEntity (m_enemy)) { if (!game.isNullEntity (m_enemy)) {
src = src + m_enemy->v.velocity * 0.6f; src = src + m_enemy->v.velocity;
} }
m_grenade = (src - getEyesPos ()).normalize (); m_grenade = (src - getEyesPos ()).normalize ();

View file

@ -252,7 +252,6 @@ bool Bot::lookupEnemies () {
newEnemy = player; newEnemy = player;
} }
} }
auto distanceScale = usesKnife () ? 1.0f : 0.75f;
// the old enemy is no longer visible or // the old enemy is no longer visible or
if (game.isNullEntity (newEnemy)) { if (game.isNullEntity (newEnemy)) {
@ -279,7 +278,7 @@ bool Bot::lookupEnemies () {
float scaleFactor = (1.0f / calculateScaleFactor (intresting)); float scaleFactor = (1.0f / calculateScaleFactor (intresting));
float distance = intresting->v.origin.distanceSq (pev->origin) * scaleFactor; float distance = intresting->v.origin.distanceSq (pev->origin) * scaleFactor;
if (distance * distanceScale < nearestDistance) { if (distance < nearestDistance) {
nearestDistance = distance; nearestDistance = distance;
newEnemy = intresting; newEnemy = intresting;
} }
@ -312,7 +311,7 @@ bool Bot::lookupEnemies () {
} }
float distance = player->v.origin.distanceSq (pev->origin); float distance = player->v.origin.distanceSq (pev->origin);
if (distance * distanceScale < nearestDistance) { if (distance < nearestDistance) {
nearestDistance = distance; nearestDistance = distance;
newEnemy = player; newEnemy = player;
@ -602,6 +601,8 @@ bool Bot::isFriendInLineOfFire (float distance) {
} }
} }
// doesn't seems to be have any effect
#if 0
// search the world for players // search the world for players
for (const auto &client : util.getClients ()) { for (const auto &client : util.getClients ()) {
if (!(client.flags & ClientFlags::Used) || !(client.flags & ClientFlags::Alive) || client.team != m_team || client.ent == ent ()) { if (!(client.flags & ClientFlags::Used) || !(client.flags & ClientFlags::Alive) || client.team != m_team || client.ent == ent ()) {
@ -613,6 +614,7 @@ bool Bot::isFriendInLineOfFire (float distance) {
return true; return true;
} }
} }
#endif
return false; return false;
} }
@ -1934,12 +1936,9 @@ void Bot::checkGrenadesThrow () {
allowThrowing = false; allowThrowing = false;
} }
else { else {
float radius = m_lastEnemy->v.velocity.length2d (); float radius = cr::max (192.0f, m_lastEnemy->v.velocity.length2d ());
const Vector &pos = (m_lastEnemy->v.velocity * 0.5f).get2d () + m_lastEnemy->v.origin; const Vector &pos = m_lastEnemy->v.velocity.get2d () + m_lastEnemy->v.origin;
if (radius < 164.0f) {
radius = 164.0f;
}
auto predicted = graph.getNarestInRadius (radius, pos, 12); auto predicted = graph.getNarestInRadius (radius, pos, 12);
if (predicted.empty ()) { if (predicted.empty ()) {
@ -1980,9 +1979,8 @@ void Bot::checkGrenadesThrow () {
} }
break; break;
case Weapon::Flashbang: case Weapon::Flashbang: {
{ int nearest = graph.getNearest (m_lastEnemy->v.velocity.get2d () + m_lastEnemy->v.origin);
int nearest = graph.getNearest ((m_lastEnemy->v.velocity * 0.5f).get2d () + m_lastEnemy->v.origin);
if (nearest != kInvalidNodeIndex) { if (nearest != kInvalidNodeIndex) {
m_throw = graph[nearest].origin; m_throw = graph[nearest].origin;

View file

@ -759,11 +759,12 @@ int BotControl::cmdNodeUpload () {
msg ("you may notice the game freezes a bit during upload and issue request creation. Please, be patient."); msg ("you may notice the game freezes a bit during upload and issue request creation. Please, be patient.");
msg ("\n"); msg ("\n");
// upload everytime in lowercase String uploadUrl = cv_graph_url_upload.str ();
String mapName = game.getMapName ();
game.print ("%s", uploadUrl);
// try to upload the file // try to upload the file
if (http.uploadFile ("http://yapb.jeefo.net/upload", strings.format ("%sgraph/%s.graph", graph.getDataDirectory (false), mapName.lowercase ()))) { if (http.uploadFile (uploadUrl, util.buildPath (BotFile::Graph))) {
msg ("Graph file was successfully validated and uploaded to the YaPB Graph DB (%s).", product.download); 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 ("It will be available for download for all YaPB users in a few minutes.");
msg ("\n"); msg ("\n");

View file

@ -834,7 +834,7 @@ bool Game::loadCSBinary () {
bool Game::postload () { bool Game::postload () {
// register logger // register logger
logger.initialize (strings.format ("%slogs/%s.log", graph.getDataDirectory (false), product.folder), [] (const char *msg) { logger.initialize (util.buildPath (BotFile::LogFile), [] (const char *msg) {
game.print (msg); game.print (msg);
}); });

View file

@ -9,6 +9,7 @@
ConVar cv_graph_fixcamp ("yb_graph_fixcamp", "0", "Specifies whether bot should not 'fix' camp directions of camp waypoints when loading old PWF format."); ConVar cv_graph_fixcamp ("yb_graph_fixcamp", "0", "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. Set to empty, if no downloads needed.", 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);
ConVar cv_graph_url_upload ("yb_graph_url_upload", "http://yapb.jeefo.net/upload", "Specifies the URL to bots will try to upload te graph file to database.", false, 0.0f, 0.0f);
ConVar cv_graph_auto_save_count ("yb_graph_auto_save_count", "15", "Every N graph nodes placed on map, the graph will be saved automatically (without checks).", true, 0.0f, kMaxNodes); ConVar cv_graph_auto_save_count ("yb_graph_auto_save_count", "15", "Every N graph nodes placed on map, the graph will be saved automatically (without checks).", true, 0.0f, kMaxNodes);
ConVar cv_graph_draw_distance ("yb_graph_draw_distance", "400", "Maximum distance to draw graph nodes from editor viewport.", true, 64.0f, 3072.0f); ConVar cv_graph_draw_distance ("yb_graph_draw_distance", "400", "Maximum distance to draw graph nodes from editor viewport.", true, 64.0f, 3072.0f);
@ -1270,7 +1271,7 @@ void BotGraph::loadPractice () {
m_highestDamage[team] = 1; m_highestDamage[team] = 1;
} }
bool dataLoaded = loadStorage <Practice> ("prc", "Practice", StorageOption::Practice, StorageVersion::Practice, m_practice, nullptr, nullptr); bool dataLoaded = loadStorage <Practice> ("Practice", StorageOption::Practice, StorageVersion::Practice, m_practice, nullptr, nullptr);
int count = length (); int count = length ();
// set's the highest damage if loaded ok // set's the highest damage if loaded ok
@ -1308,7 +1309,7 @@ void BotGraph::savePractice () {
if (m_paths.empty () || m_hasChanged) { if (m_paths.empty () || m_hasChanged) {
return; return;
} }
saveStorage <Practice> ("prc", "Practice", StorageOption::Practice, StorageVersion::Practice, m_practice, nullptr); saveStorage <Practice> ("Practice", StorageOption::Practice, StorageVersion::Practice, m_practice, nullptr);
} }
void BotGraph::loadVisibility () { void BotGraph::loadVisibility () {
@ -1317,7 +1318,7 @@ void BotGraph::loadVisibility () {
if (m_paths.empty ()) { if (m_paths.empty ()) {
return; return;
} }
bool dataLoaded = loadStorage <uint8_t> ("vis", "Visibility", StorageOption::Vistable, StorageVersion::Vistable, m_vistable, nullptr, nullptr); bool dataLoaded = loadStorage <uint8_t> ("Visibility", StorageOption::Vistable, StorageVersion::Vistable, m_vistable, nullptr, nullptr);
// if loaded, do not recalculate visibility // if loaded, do not recalculate visibility
if (dataLoaded) { if (dataLoaded) {
@ -1329,14 +1330,14 @@ void BotGraph::saveVisibility () {
if (m_paths.empty () || m_hasChanged || m_needsVisRebuild) { if (m_paths.empty () || m_hasChanged || m_needsVisRebuild) {
return; return;
} }
saveStorage <uint8_t> ("vis", "Visibility", StorageOption::Vistable, StorageVersion::Vistable, m_vistable, nullptr); saveStorage <uint8_t> ("Visibility", StorageOption::Vistable, StorageVersion::Vistable, m_vistable, nullptr);
} }
bool BotGraph::loadPathMatrix () { bool BotGraph::loadPathMatrix () {
if (m_paths.empty ()) { if (m_paths.empty ()) {
return false; return false;
} }
bool dataLoaded = loadStorage <Matrix> ("pmx", "Pathmatrix", StorageOption::Matrix, StorageVersion::Matrix, m_matrix, nullptr, nullptr); bool dataLoaded = loadStorage <Matrix> ("Pathmatrix", StorageOption::Matrix, StorageVersion::Matrix, m_matrix, nullptr, nullptr);
// do not rebuild if loaded // do not rebuild if loaded
if (dataLoaded) { if (dataLoaded) {
@ -1387,7 +1388,7 @@ void BotGraph::savePathMatrix () {
if (m_paths.empty ()) { if (m_paths.empty ()) {
return; return;
} }
saveStorage <Matrix> ("pmx", "Pathmatrix", StorageOption::Matrix, StorageVersion::Matrix, m_matrix, nullptr); saveStorage <Matrix> ("Pathmatrix", StorageOption::Matrix, StorageVersion::Matrix, m_matrix, nullptr);
} }
void BotGraph::initLightLevels () { void BotGraph::initLightLevels () {
@ -1533,7 +1534,13 @@ void BotGraph::initNodesTypes () {
} }
bool BotGraph::convertOldFormat () { bool BotGraph::convertOldFormat () {
MemFile fp (getOldFormatGraphName (true)); MemFile fp (util.buildPath (BotFile::PodbotPWF, true));
if (!fp) {
if (!fp.open (util.buildPath (BotFile::EbotEWP, true))) {
return false;
}
}
PODGraphHeader header {}; PODGraphHeader header {};
plat.bzero (&header, sizeof (header)); plat.bzero (&header, sizeof (header));
@ -1606,7 +1613,7 @@ bool BotGraph::convertOldFormat () {
return false; return false;
} }
template <typename U> bool BotGraph::saveStorage (StringRef ext, StringRef name, StorageOption options, StorageVersion version, const SmallArray <U> &data, ExtenHeader *exten) { template <typename U> bool BotGraph::saveStorage (StringRef name, StorageOption options, StorageVersion version, const SmallArray <U> &data, ExtenHeader *exten) {
bool isGraph = !!(options & StorageOption::Graph); bool isGraph = !!(options & StorageOption::Graph);
// do not allow to save graph with less than 8 nodes // do not allow to save graph with less than 8 nodes
@ -1614,9 +1621,7 @@ template <typename U> bool BotGraph::saveStorage (StringRef ext, StringRef name,
ctrl.msg ("Can't save graph data with less than %d nodes. Please add some more before saving.", kMaxNodeLinks); ctrl.msg ("Can't save graph data with less than %d nodes. Please add some more before saving.", kMaxNodeLinks);
return false; return false;
} }
String filename = util.buildPath (util.storageToBotFile (options));
String filename;
filename.assignf ("%s.%s", game.getMapName (), ext).lowercase ();
if (data.empty ()) { if (data.empty ()) {
logger.error ("Unable to save %s file. Empty data. (filename: '%s').", name, filename); logger.error ("Unable to save %s file. Empty data. (filename: '%s').", name, filename);
@ -1630,7 +1635,7 @@ template <typename U> bool BotGraph::saveStorage (StringRef ext, StringRef name,
} }
// open the file // open the file
File file (strings.format ("%s%s/%s", getDataDirectory (false), isGraph ? "graph" : "train", filename), "wb"); File file (filename, "wb");
// no open no fun // no open no fun
if (!file) { if (!file) {
@ -1660,8 +1665,12 @@ template <typename U> bool BotGraph::saveStorage (StringRef ext, StringRef name,
if ((options & StorageOption::Exten) && exten != nullptr) { if ((options & StorageOption::Exten) && exten != nullptr) {
file.write (exten, sizeof (ExtenHeader)); file.write (exten, sizeof (ExtenHeader));
} }
// notify only about graph
if (isGraph || cv_debug.bool_ ()) {
ctrl.msg ("Successfully saved Bots %s data.", name); ctrl.msg ("Successfully saved Bots %s data.", name);
} }
}
else { else {
logger.error ("Unable to compress %s data (filename: '%s').", name, filename); logger.error ("Unable to compress %s data (filename: '%s').", name, filename);
return false; return false;
@ -1669,13 +1678,12 @@ template <typename U> bool BotGraph::saveStorage (StringRef ext, StringRef name,
return true; return true;
} }
template <typename U> bool BotGraph::loadStorage (StringRef ext, StringRef name, StorageOption options, StorageVersion version, SmallArray <U> &data, ExtenHeader *exten, int32_t *outOptions) { template <typename U> bool BotGraph::loadStorage (StringRef name, StorageOption options, StorageVersion version, SmallArray <U> &data, ExtenHeader *exten, int32_t *outOptions) {
String filename; String filename = util.buildPath (util.storageToBotFile (options), true);
filename.assignf ("%s.%s", game.getMapName (), ext).lowercase ();
// graphs can be downloaded... // graphs can be downloaded...
bool isGraph = !!(options & StorageOption::Graph); bool isGraph = !!(options & StorageOption::Graph);
MemFile file (strings.format ("%s%s/%s", getDataDirectory (true), isGraph ? "graph" : "train", filename)); // open the file MemFile file (filename); // open the file
data.clear (); data.clear ();
data.shrink (); data.shrink ();
@ -1707,8 +1715,8 @@ template <typename U> bool BotGraph::loadStorage (StringRef ext, StringRef name,
} }
auto downloadAddress = cv_graph_url.str (); auto downloadAddress = cv_graph_url.str ();
auto toDownload = strings.format ("%sgraph/%s", getDataDirectory (false), filename); auto toDownload = util.buildPath (util.storageToBotFile (options), false);
auto fromDownload = strings.format ("http://%s/graph/%s", downloadAddress, filename); auto fromDownload = strings.format ("http://%s/graph/%s.graph", downloadAddress, game.getMapName ());
// try to download // try to download
if (http.downloadFile (fromDownload, toDownload)) { if (http.downloadFile (fromDownload, toDownload)) {
@ -1730,11 +1738,11 @@ template <typename U> bool BotGraph::loadStorage (StringRef ext, StringRef name,
} }
if (download ()) { if (download ()) {
return loadStorage <U> (ext, name, options, version, data, exten, outOptions); return loadStorage <U> (name, options, version, data, exten, outOptions);
} }
if (convertOldFormat ()) { if (convertOldFormat ()) {
return loadStorage <U> (ext, name, options, version, data, exten, outOptions); return loadStorage <U> (name, options, version, data, exten, outOptions);
} }
return false; return false;
}; };
@ -1780,13 +1788,12 @@ template <typename U> bool BotGraph::loadStorage (StringRef ext, StringRef name,
return raiseLoadingError (isGraph, file, "Damaged %s (filename: '%s'). Version number differs (got: '%d', need: '%d').", name, filename, hdr.version, version); return raiseLoadingError (isGraph, file, "Damaged %s (filename: '%s'). Version number differs (got: '%d', need: '%d').", name, filename, hdr.version, version);
} }
// temporary solution to kill version 1 vistables, which has a bugs // temporary solution to kill version 1 vistables, which has a bugs
if ((options & StorageOption::Vistable) && hdr.version == 1) { if ((options & StorageOption::Vistable) && hdr.version == 1) {
auto vistablePath = strings.format ("%strain/%s.vis", getDataDirectory (), game.getMapName ()); auto vistablePath = util.buildPath (BotFile::Vistable);
if (File::exists (vistablePath)) { if (File::exists (vistablePath)) {
plat.removeFile (vistablePath); plat.removeFile (vistablePath.chars ());
} }
return raiseLoadingError (isGraph, file, "Bugged vistable %s (filename: '%s'). Version 1 has a bugs, vistable will be recreated.", name, filename); return raiseLoadingError (isGraph, file, "Bugged vistable %s (filename: '%s'). Version 1 has a bugs, vistable will be recreated.", name, filename);
} }
@ -1843,7 +1850,7 @@ template <typename U> bool BotGraph::loadStorage (StringRef ext, StringRef name,
m_extenHeader.mapSize = exten->mapSize; m_extenHeader.mapSize = exten->mapSize;
} }
} }
ctrl.msg ("Successfully loaded Bots %s data v%d (%d/%.2fMB).", name, hdr.version, m_paths.length (), static_cast <float> (data.capacity () * sizeof (U)) / 1024.0f / 1024.0f); ctrl.msg ("Loaded Bots %s data v%d (%d/%.2fMB).", name, hdr.version, m_paths.length (), static_cast <float> (data.capacity () * sizeof (U)) / 1024.0f / 1024.0f);
file.close (); file.close ();
return true; return true;
@ -1863,7 +1870,7 @@ bool BotGraph::loadGraphData () {
m_extenHeader = {}; m_extenHeader = {};
// check if loaded // check if loaded
bool dataLoaded = loadStorage <Path> ("graph", "Graph", StorageOption::Graph, StorageVersion::Graph, m_paths, &exten, &outOptions); bool dataLoaded = loadStorage <Path> ("Graph", StorageOption::Graph, StorageVersion::Graph, m_paths, &exten, &outOptions);
if (dataLoaded) { if (dataLoaded) {
reset (); reset ();
@ -1951,7 +1958,7 @@ bool BotGraph::saveGraphData () {
m_narrowChecked = false; m_narrowChecked = false;
initNarrowPlaces (); initNarrowPlaces ();
return saveStorage <Path> ("graph", "Graph", static_cast <StorageOption> (options), StorageVersion::Graph, m_paths, &exten); return saveStorage <Path> ("Graph", static_cast <StorageOption> (options), StorageVersion::Graph, m_paths, &exten);
} }
void BotGraph::saveOldFormat () { void BotGraph::saveOldFormat () {
@ -1968,7 +1975,7 @@ void BotGraph::saveOldFormat () {
File fp; File fp;
// file was opened // file was opened
if (fp.open (getOldFormatGraphName (), "wb")) { if (fp.open (util.buildPath (BotFile::PodbotPWF), "wb")) {
// write the node header to the file... // write the node header to the file...
fp.write (&header, sizeof (header)); fp.write (&header, sizeof (header));
@ -1986,16 +1993,6 @@ void BotGraph::saveOldFormat () {
} }
} }
const char *BotGraph::getOldFormatGraphName (bool isMemoryFile) {
static String buffer;
buffer.assignf ("%s/pwf/%s.pwf", getDataDirectory (isMemoryFile), game.getMapName ());
if (File::exists (buffer)) {
return buffer.chars ();
}
return strings.format ("%s/pwf/%s.pwf", getDataDirectory (isMemoryFile), game.getMapName ());
}
float BotGraph::calculateTravelTime (float maxSpeed, const Vector &src, const Vector &origin) { float BotGraph::calculateTravelTime (float maxSpeed, const Vector &src, const Vector &origin) {
// this function returns 2D traveltime to a position // this function returns 2D traveltime to a position
@ -2898,15 +2895,11 @@ void BotGraph::eraseFromDisk () {
StringArray forErase; StringArray forErase;
bots.kickEveryone (true); bots.kickEveryone (true);
auto map = game.getMapName ();
auto data = getDataDirectory ();
// if we're delete graph, delete all corresponding to it files // if we're delete graph, delete all corresponding to it files
forErase.push (strings.format ("%spwf/%s.pwf", data, map)); // graph itself forErase.emplace (util.buildPath (BotFile::Graph)); // graph itself
forErase.push (strings.format ("%strain/%s.prc", data, map)); // corresponding to practice forErase.emplace (util.buildPath (BotFile::Practice)); // corresponding to practice
forErase.push (strings.format ("%strain/%s.vis", data, map)); // corresponding to vistable forErase.emplace (util.buildPath (BotFile::Vistable)); // corresponding to vistable
forErase.push (strings.format ("%strain/%s.pmx", data, map)); // corresponding to matrix forErase.emplace (util.buildPath (BotFile::Pathmatrix)); // corresponding to matrix
forErase.push (strings.format ("%sgraph/%s.graph", data, map)); // new format graph
for (const auto &item : forErase) { for (const auto &item : forErase) {
if (File::exists (item)) { if (File::exists (item)) {
@ -2921,19 +2914,6 @@ void BotGraph::eraseFromDisk () {
m_paths.clear (); m_paths.clear ();
} }
const char *BotGraph::getDataDirectory (bool isMemoryFile) {
static String buffer;
buffer.clear ();
if (isMemoryFile) {
buffer.assignf ("addons/%s/data/", product.folder);
}
else {
buffer.assignf ("%s/addons/%s/data/", game.getRunningModName (), product.folder);
}
return buffer.chars ();
}
void BotGraph::setBombOrigin (bool reset, const Vector &pos) { void BotGraph::setBombOrigin (bool reset, const Vector &pos) {
// this function stores the bomb position as a vector // this function stores the bomb position as a vector

View file

@ -538,6 +538,83 @@ String BotSupport::getCurrentDateTime () {
return String (timebuf); return String (timebuf);
} }
String BotSupport::buildPath (int32_t file, bool isMemoryLoad) {
static HashMap <int32_t, StringArray> directories;
static HashMap <int32_t, String> extensions;
// fill out directories paths, it's permanenet
if (directories.empty ()) {
directories[BotFile::Vistable] = { "data", "train" };
directories[BotFile::Practice] = { "data", "train" };
directories[BotFile::Pathmatrix] = { "data", "train" };
directories[BotFile::LogFile] = { "data", "logs" };
directories[BotFile::Graph] = { "data", "graph" };
directories[BotFile::PodbotPWF] = { "data", "pwf" };
directories[BotFile::EbotEWP] = { "data", "ewp" };
// fill out extensions fo needed types
extensions[BotFile::Vistable] = "vis";
extensions[BotFile::Practice] = "prc";
extensions[BotFile::Pathmatrix] = "pmx";
extensions[BotFile::LogFile] = "txt";
extensions[BotFile::Graph] = "graph";
extensions[BotFile::PodbotPWF] = "pwf";
extensions[BotFile::EbotEWP] = "ewp";
}
static StringArray path;
path.clear ();
// if not memory file we're don't need game dir
if (!isMemoryLoad) {
path.emplace (game.getRunningModName ());
}
// allways append addons/product
path.emplace ("addons");
path.emplace (product.folder);
// append real filepath
path.extend (directories[file]);
// if file is logfile use correct logfile name with date
if (file == BotFile::LogFile) {
time_t ticks = time (&ticks);
tm timeinfo {};
plat.loctime (&timeinfo, &ticks);
auto timebuf = strings.chars ();
strftime (timebuf, StringBuffer::StaticBufferSize, "L%d%m%Y", &timeinfo);
path.emplace (strings.format ("%s_%s.%s", product.folder, timebuf, extensions[file]));
}
else {
String mapName = game.getMapName ();
path.emplace (strings.format ("%s.%s", mapName.lowercase (), extensions[file]));
}
// finally use correct path separarators for us
return String::join (path, plat.win ? "\\" : "/");
}
// converts storage option to stroage filename
int32_t BotSupport::storageToBotFile (StorageOption options) {
if (options & StorageOption::Graph) {
return BotFile::Graph;
}
else if (options & StorageOption::Matrix) {
return BotFile::Pathmatrix;
}
else if (options & StorageOption::Vistable) {
return BotFile::Vistable;
}
else if (options & StorageOption::Practice) {
return BotFile::Practice;
}
return BotFile::Graph;
}
int32_t BotSupport::sendTo (int socket, const void *message, size_t length, int flags, const sockaddr *dest, int destLength) { int32_t BotSupport::sendTo (int socket, const void *message, size_t length, int flags, const sockaddr *dest, int destLength) {
const auto send = [&] (const Twin <const uint8_t *, size_t> &msg) -> int32_t { const auto send = [&] (const Twin <const uint8_t *, size_t> &msg) -> int32_t {
return Socket::sendto (socket, msg.first, msg.second, flags, dest, destLength); return Socket::sendto (socket, msg.first, msg.second, flags, dest, destLength);