mirror of
https://github.com/liyunfan1223/mod-playerbots.git
synced 2026-06-20 15:39:25 +02:00
Compare commits
4 Commits
6cf10c5057
...
ac19374ed8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac19374ed8 | ||
|
|
793d3f8fdc | ||
|
|
7a8a2cd10c | ||
|
|
0e0b605e17 |
@ -0,0 +1,29 @@
|
||||
-- Manual travelnode coverage for the Aldrassil ramp in Shadowglen
|
||||
-- (Teldrassil, map 1, zone 141). Adds 9 anchor nodes along the spiral
|
||||
-- ramp (base -> intermediate ramp waypoints -> top platform near
|
||||
-- Tenaron Stormgrip). All nodes are `linked = 0` so
|
||||
-- `.playerbots travel generatenode` will iterate them and let mmap
|
||||
-- compute the actual walk paths between consecutive nodes. Splitting
|
||||
-- the climb into short segments (~30y each) gives mmap a much better
|
||||
-- chance of resolving each piece than a single 300y end-to-end probe.
|
||||
|
||||
SET @n1 := (SELECT IFNULL(MAX(id), 0) + 1 FROM playerbots_travelnode);
|
||||
SET @n2 := @n1 + 1;
|
||||
SET @n3 := @n1 + 2;
|
||||
SET @n4 := @n1 + 3;
|
||||
SET @n5 := @n1 + 4;
|
||||
SET @n6 := @n1 + 5;
|
||||
SET @n7 := @n1 + 6;
|
||||
SET @n8 := @n1 + 7;
|
||||
SET @n9 := @n1 + 8;
|
||||
|
||||
INSERT INTO playerbots_travelnode (id, name, map_id, x, y, z, linked) VALUES
|
||||
(@n1, 'Aldrassil Ramp 1 (base)', 1, 10413.756, 887.97363, 1319.3668, 0),
|
||||
(@n2, 'Aldrassil Ramp 2', 1, 10440.520, 870.32320, 1328.9324, 0),
|
||||
(@n3, 'Aldrassil Ramp 3', 1, 10497.001, 854.46014, 1345.1770, 0),
|
||||
(@n4, 'Aldrassil Ramp 4', 1, 10517.199, 821.48640, 1354.7914, 0),
|
||||
(@n5, 'Aldrassil Ramp 5', 1, 10477.926, 847.88855, 1372.1685, 0),
|
||||
(@n6, 'Aldrassil Ramp 6', 1, 10455.358, 831.34240, 1380.9377, 0),
|
||||
(@n7, 'Aldrassil Ramp 7', 1, 10460.220, 800.71716, 1388.3368, 0),
|
||||
(@n8, 'Aldrassil Ramp 8', 1, 10507.434, 793.30420, 1397.2166, 0),
|
||||
(@n9, 'Aldrassil Ramp 9 (top)', 1, 10495.496, 804.67700, 1397.2662, 0);
|
||||
@ -180,11 +180,11 @@ void MovementAction::EmitDebugMove(char const* method, char const* generator, fl
|
||||
|
||||
float dis = bot->GetExactDist(x, y, z);
|
||||
std::ostringstream out;
|
||||
out << "[MOVE] meth=" << method
|
||||
<< " | via=" << (generator && *generator ? generator : "-")
|
||||
<< " | rpg=" << statusName
|
||||
<< " | d=" << dis << "y"
|
||||
<< " | targ=" << (targetName.empty() ? "-" : targetName.c_str());
|
||||
out << "[M] | " << method
|
||||
<< " | " << (generator && *generator ? generator : "-")
|
||||
<< " | " << statusName
|
||||
<< " | " << std::fixed << std::setprecision(2) << dis << " yard"
|
||||
<< " | " << (targetName.empty() ? "-" : targetName.c_str());
|
||||
if (extra && *extra)
|
||||
out << " | " << extra;
|
||||
botAI->TellMasterNoFacing(out);
|
||||
|
||||
@ -2018,71 +2018,109 @@ void TravelNodeMap::saveNodeStore()
|
||||
|
||||
hasToSave = false;
|
||||
|
||||
PlayerbotsDatabaseTransaction trans = PlayerbotsDatabase.BeginTransaction();
|
||||
constexpr uint32 STMTS_PER_TX = 500; // bounded transaction size
|
||||
|
||||
trans->Append(PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_DEL_TRAVELNODE));
|
||||
trans->Append(PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_DEL_TRAVELNODE_LINK));
|
||||
trans->Append(PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_DEL_TRAVELNODE_PATH));
|
||||
// Phase 1: deletes in their own transaction.
|
||||
{
|
||||
PlayerbotsDatabaseTransaction delTrans = PlayerbotsDatabase.BeginTransaction();
|
||||
delTrans->Append(PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_DEL_TRAVELNODE));
|
||||
delTrans->Append(PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_DEL_TRAVELNODE_LINK));
|
||||
delTrans->Append(PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_DEL_TRAVELNODE_PATH));
|
||||
PlayerbotsDatabase.CommitTransaction(delTrans);
|
||||
}
|
||||
|
||||
std::unordered_map<TravelNode*, uint32> saveNodes;
|
||||
std::vector<TravelNode*> anodes = TravelNodeMap::instance().getNodes();
|
||||
|
||||
for (uint32 i = 0; i < anodes.size(); i++)
|
||||
// Phase 2: node inserts, chunked at STMTS_PER_TX per transaction.
|
||||
{
|
||||
TravelNode* node = anodes[i];
|
||||
PlayerbotsDatabaseTransaction nodeTrans = PlayerbotsDatabase.BeginTransaction();
|
||||
uint32 inTx = 0;
|
||||
for (uint32 i = 0; i < anodes.size(); i++)
|
||||
{
|
||||
TravelNode* node = anodes[i];
|
||||
|
||||
std::string name = node->getName();
|
||||
name.erase(remove(name.begin(), name.end(), '\''), name.end());
|
||||
std::string name = node->getName();
|
||||
name.erase(remove(name.begin(), name.end(), '\''), name.end());
|
||||
|
||||
PlayerbotsDatabasePreparedStatement* stmt = PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_INS_TRAVELNODE);
|
||||
stmt->SetData(0, i);
|
||||
stmt->SetData(1, name);
|
||||
stmt->SetData(2, node->GetMapId());
|
||||
stmt->SetData(3, node->getX());
|
||||
stmt->SetData(4, node->getY());
|
||||
stmt->SetData(5, node->getZ());
|
||||
stmt->SetData(6, node->isLinked());
|
||||
trans->Append(stmt);
|
||||
PlayerbotsDatabasePreparedStatement* stmt = PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_INS_TRAVELNODE);
|
||||
stmt->SetData(0, i);
|
||||
stmt->SetData(1, name);
|
||||
stmt->SetData(2, node->GetMapId());
|
||||
stmt->SetData(3, node->getX());
|
||||
stmt->SetData(4, node->getY());
|
||||
stmt->SetData(5, node->getZ());
|
||||
stmt->SetData(6, node->isLinked());
|
||||
nodeTrans->Append(stmt);
|
||||
|
||||
saveNodes.insert(std::make_pair(node, i));
|
||||
saveNodes.insert(std::make_pair(node, i));
|
||||
|
||||
if (++inTx >= STMTS_PER_TX)
|
||||
{
|
||||
PlayerbotsDatabase.CommitTransaction(nodeTrans);
|
||||
nodeTrans = PlayerbotsDatabase.BeginTransaction();
|
||||
inTx = 0;
|
||||
}
|
||||
}
|
||||
PlayerbotsDatabase.CommitTransaction(nodeTrans);
|
||||
}
|
||||
|
||||
LOG_INFO("playerbots", ">> Saved {} travelNodes.", anodes.size());
|
||||
|
||||
// Phase 3: link inserts, chunked at STMTS_PER_TX per transaction.
|
||||
uint32 paths = 0;
|
||||
for (uint32 i = 0; i < anodes.size(); i++)
|
||||
{
|
||||
TravelNode* node = anodes[i];
|
||||
|
||||
for (auto& link : *node->getLinks())
|
||||
PlayerbotsDatabaseTransaction linkTrans = PlayerbotsDatabase.BeginTransaction();
|
||||
uint32 inTx = 0;
|
||||
for (uint32 i = 0; i < anodes.size(); i++)
|
||||
{
|
||||
TravelNodePath* path = link.second;
|
||||
TravelNode* node = anodes[i];
|
||||
|
||||
PlayerbotsDatabasePreparedStatement* stmt =
|
||||
PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_INS_TRAVELNODE_LINK);
|
||||
stmt->SetData(0, i);
|
||||
stmt->SetData(1, saveNodes.find(link.first)->second);
|
||||
stmt->SetData(2, static_cast<uint8>(path->getPathType()));
|
||||
stmt->SetData(3, path->getPathObject());
|
||||
stmt->SetData(4, path->getDistance());
|
||||
stmt->SetData(5, path->getSwimDistance());
|
||||
stmt->SetData(6, path->getExtraCost());
|
||||
stmt->SetData(7, path->getCalculated());
|
||||
stmt->SetData(8, path->getMaxLevelCreature()[0]);
|
||||
stmt->SetData(9, path->getMaxLevelCreature()[1]);
|
||||
stmt->SetData(10, path->getMaxLevelCreature()[2]);
|
||||
trans->Append(stmt);
|
||||
for (auto& link : *node->getLinks())
|
||||
{
|
||||
TravelNodePath* path = link.second;
|
||||
|
||||
paths++;
|
||||
PlayerbotsDatabasePreparedStatement* stmt =
|
||||
PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_INS_TRAVELNODE_LINK);
|
||||
stmt->SetData(0, i);
|
||||
stmt->SetData(1, saveNodes.find(link.first)->second);
|
||||
stmt->SetData(2, static_cast<uint8>(path->getPathType()));
|
||||
stmt->SetData(3, path->getPathObject());
|
||||
stmt->SetData(4, path->getDistance());
|
||||
stmt->SetData(5, path->getSwimDistance());
|
||||
stmt->SetData(6, path->getExtraCost());
|
||||
stmt->SetData(7, path->getCalculated());
|
||||
stmt->SetData(8, path->getMaxLevelCreature()[0]);
|
||||
stmt->SetData(9, path->getMaxLevelCreature()[1]);
|
||||
stmt->SetData(10, path->getMaxLevelCreature()[2]);
|
||||
linkTrans->Append(stmt);
|
||||
|
||||
paths++;
|
||||
|
||||
if (++inTx >= STMTS_PER_TX)
|
||||
{
|
||||
PlayerbotsDatabase.CommitTransaction(linkTrans);
|
||||
linkTrans = PlayerbotsDatabase.BeginTransaction();
|
||||
inTx = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
PlayerbotsDatabase.CommitTransaction(linkTrans);
|
||||
}
|
||||
// Path points: bulk raw SQL multi-row INSERTs (~500 rows each) instead of
|
||||
// 1M+ individual prepared statements. Appended to the same transaction so
|
||||
// ordering is guaranteed.
|
||||
|
||||
// Phase 2: path points in chunked transactions. Previously all
|
||||
// ~1.5M point inserts went into a single mega-transaction which
|
||||
// exceeded MySQL's packet/transaction limits and partial-committed,
|
||||
// corrupting the DB (links saved, paths empty). Chunk now commits
|
||||
// every ~10000 rows. A failed chunk loses only its rows; the rest
|
||||
// survive.
|
||||
constexpr uint32 BATCH_SIZE = 500;
|
||||
constexpr uint32 BATCHES_PER_COMMIT = 20; // 20 * 500 = 10000 rows per tx
|
||||
uint32 points = 0;
|
||||
std::ostringstream ss;
|
||||
uint32 batchCount = 0;
|
||||
uint32 batchesInCurrentTx = 0;
|
||||
PlayerbotsDatabaseTransaction pathTrans = PlayerbotsDatabase.BeginTransaction();
|
||||
|
||||
auto flushBatch = [&]()
|
||||
{
|
||||
@ -2091,10 +2129,21 @@ void TravelNodeMap::saveNodeStore()
|
||||
|
||||
std::string sql = ss.str();
|
||||
sql.back() = ';'; // Replace trailing comma
|
||||
trans->Append(sql.c_str());
|
||||
pathTrans->Append(sql.c_str());
|
||||
ss.str("");
|
||||
ss.clear();
|
||||
batchCount = 0;
|
||||
batchesInCurrentTx++;
|
||||
};
|
||||
|
||||
auto commitIfFull = [&]()
|
||||
{
|
||||
if (batchesInCurrentTx >= BATCHES_PER_COMMIT)
|
||||
{
|
||||
PlayerbotsDatabase.CommitTransaction(pathTrans);
|
||||
pathTrans = PlayerbotsDatabase.BeginTransaction();
|
||||
batchesInCurrentTx = 0;
|
||||
}
|
||||
};
|
||||
|
||||
for (uint32 i = 0; i < anodes.size(); i++)
|
||||
@ -2125,16 +2174,18 @@ void TravelNodeMap::saveNodeStore()
|
||||
points++;
|
||||
|
||||
if (batchCount >= BATCH_SIZE)
|
||||
{
|
||||
flushBatch();
|
||||
commitIfFull();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flushBatch();
|
||||
PlayerbotsDatabase.CommitTransaction(pathTrans);
|
||||
|
||||
LOG_INFO("playerbots", ">> Saved {} travelNode Paths, {} points.", paths, points);
|
||||
|
||||
PlayerbotsDatabase.CommitTransaction(trans);
|
||||
}
|
||||
|
||||
void TravelNodeMap::LoadNodeStore()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user