#include "../client.h" void command_invsnapshot(Client *c, const Seperator *sep) { if (!c) { return; } if (sep->argnum == 0 || strcmp(sep->arg[1], "help") == 0) { std::string window_title = "Inventory Snapshot Argument Help Menu"; std::string window_text = "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""; if (c->Admin() >= commandInvSnapshot) { window_text.append( "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ); } window_text.append( "
Usage:#invsnapshot arguments
(required optional)
helpthis menu
capturetakes snapshot of character inventory
gcountreturns global snapshot count
gclear
now
delete all snapshots - rule
delete all snapshots - now
countreturns character snapshot count
clear
now
delete character snapshots - rule
delete character snapshots - now
list
count
lists entry ids for current character
limits to count
parsetstmpdisplays slots and items in snapshot
comparetstmpcompares inventory against snapshot
restoretstmprestores slots and items in snapshot
" ); c->SendPopupToClient(window_title.c_str(), window_text.c_str()); return; } if (c->Admin() >= commandInvSnapshot) { // global arguments if (strcmp(sep->arg[1], "gcount") == 0) { auto is_count = database.CountInvSnapshots(); c->Message( Chat::White, "There %s %i inventory snapshot%s.", (is_count == 1 ? "is" : "are"), is_count, (is_count == 1 ? "" : "s")); return; } if (strcmp(sep->arg[1], "gclear") == 0) { if (strcmp(sep->arg[2], "now") == 0) { database.ClearInvSnapshots(true); c->Message(Chat::White, "Inventory snapshots cleared using current time."); } else { database.ClearInvSnapshots(); c->Message( Chat::White, "Inventory snapshots cleared using RuleI(Character, InvSnapshotHistoryD) (%i day%s).", RuleI(Character, InvSnapshotHistoryD), (RuleI(Character, InvSnapshotHistoryD) == 1 ? "" : "s")); } return; } } if (!c->GetTarget() || !c->GetTarget()->IsClient()) { c->Message(Chat::White, "Target must be a client."); return; } auto tc = (Client *) c->GetTarget(); if (strcmp(sep->arg[1], "capture") == 0) { if (database.SaveCharacterInvSnapshot(tc->CharacterID())) { tc->SetNextInvSnapshot(RuleI(Character, InvSnapshotMinIntervalM)); c->Message( Chat::White, "Successful inventory snapshot taken of %s - setting next interval for %i minute%s.", tc->GetName(), RuleI(Character, InvSnapshotMinIntervalM), (RuleI(Character, InvSnapshotMinIntervalM) == 1 ? "" : "s")); } else { tc->SetNextInvSnapshot(RuleI(Character, InvSnapshotMinRetryM)); c->Message( Chat::White, "Failed to take inventory snapshot of %s - retrying in %i minute%s.", tc->GetName(), RuleI(Character, InvSnapshotMinRetryM), (RuleI(Character, InvSnapshotMinRetryM) == 1 ? "" : "s")); } return; } if (c->Admin() >= commandInvSnapshot) { if (strcmp(sep->arg[1], "count") == 0) { auto is_count = database.CountCharacterInvSnapshots(tc->CharacterID()); c->Message( Chat::White, "%s (id: %u) has %i inventory snapshot%s.", tc->GetName(), tc->CharacterID(), is_count, (is_count == 1 ? "" : "s")); return; } if (strcmp(sep->arg[1], "clear") == 0) { if (strcmp(sep->arg[2], "now") == 0) { database.ClearCharacterInvSnapshots(tc->CharacterID(), true); c->Message( Chat::White, "%s\'s (id: %u) inventory snapshots cleared using current time.", tc->GetName(), tc->CharacterID()); } else { database.ClearCharacterInvSnapshots(tc->CharacterID()); c->Message( Chat::White, "%s\'s (id: %u) inventory snapshots cleared using RuleI(Character, InvSnapshotHistoryD) (%i day%s).", tc->GetName(), tc->CharacterID(), RuleI(Character, InvSnapshotHistoryD), (RuleI(Character, InvSnapshotHistoryD) == 1 ? "" : "s")); } return; } if (strcmp(sep->arg[1], "list") == 0) { std::list> is_list; database.ListCharacterInvSnapshots(tc->CharacterID(), is_list); if (is_list.empty()) { c->Message(Chat::White, "No inventory snapshots for %s (id: %u)", tc->GetName(), tc->CharacterID()); return; } auto list_count = 0; if (sep->IsNumber(2)) { list_count = Strings::ToInt(sep->arg[2]); } if (list_count < 1 || list_count > is_list.size()) { list_count = is_list.size(); } std::string window_title = StringFormat("Snapshots for %s", tc->GetName()); std::string window_text = "" "" "" "" ""; for (auto iter : is_list) { if (!list_count) { break; } window_text.append( StringFormat( "" "" "" "", iter.first, iter.second )); --list_count; } window_text.append( "
TimestampEntry Count
%u%i
" ); c->SendPopupToClient(window_title.c_str(), window_text.c_str()); return; } if (strcmp(sep->arg[1], "parse") == 0) { if (!sep->IsNumber(2)) { c->Message(Chat::White, "A timestamp is required to use this option."); return; } uint32 timestamp = Strings::ToUnsignedInt(sep->arg[2]); if (!database.ValidateCharacterInvSnapshotTimestamp(tc->CharacterID(), timestamp)) { c->Message( Chat::White, "No inventory snapshots for %s (id: %u) exist at %u.", tc->GetName(), tc->CharacterID(), timestamp ); return; } std::list> parse_list; database.ParseCharacterInvSnapshot(tc->CharacterID(), timestamp, parse_list); std::string window_title = StringFormat("Snapshot Parse for %s @ %u", tc->GetName(), timestamp); std::string window_text = "Slot: ItemID - Description
"; for (auto iter : parse_list) { auto item_data = database.GetItem(iter.second); std::string window_line = StringFormat( "%i: %u - %s
", iter.first, iter.second, (item_data ? item_data->Name : "[error]")); if (window_text.length() + window_line.length() < 4095) { window_text.append(window_line); } else { c->Message(Chat::White, "Too many snapshot entries to list..."); break; } } c->SendPopupToClient(window_title.c_str(), window_text.c_str()); return; } if (strcmp(sep->arg[1], "compare") == 0) { if (!sep->IsNumber(2)) { c->Message(Chat::White, "A timestamp is required to use this option."); return; } uint32 timestamp = Strings::ToUnsignedInt(sep->arg[2]); if (!database.ValidateCharacterInvSnapshotTimestamp(tc->CharacterID(), timestamp)) { c->Message( Chat::White, "No inventory snapshots for %s (id: %u) exist at %u.", tc->GetName(), tc->CharacterID(), timestamp ); return; } std::list> inv_compare_list; database.DivergeCharacterInventoryFromInvSnapshot(tc->CharacterID(), timestamp, inv_compare_list); std::list> iss_compare_list; database.DivergeCharacterInvSnapshotFromInventory(tc->CharacterID(), timestamp, iss_compare_list); std::string window_title = StringFormat("Snapshot Comparison for %s @ %u", tc->GetName(), timestamp); std::string window_text = "Slot: (action) Snapshot -> Inventory
"; auto inv_iter = inv_compare_list.begin(); auto iss_iter = iss_compare_list.begin(); while (true) { std::string window_line; if (inv_iter == inv_compare_list.end() && iss_iter == iss_compare_list.end()) { break; } else if (inv_iter != inv_compare_list.end() && iss_iter == iss_compare_list.end()) { window_line = StringFormat("%i: (delete) [empty] -> %u
", inv_iter->first, inv_iter->second); ++inv_iter; } else if (inv_iter == inv_compare_list.end() && iss_iter != iss_compare_list.end()) { window_line = StringFormat("%i: (insert) %u -> [empty]
", iss_iter->first, iss_iter->second); ++iss_iter; } else { if (inv_iter->first < iss_iter->first) { window_line = StringFormat( "%i: (delete) [empty] -> %u
", inv_iter->first, inv_iter->second ); ++inv_iter; } else if (inv_iter->first > iss_iter->first) { window_line = StringFormat( "%i: (insert) %u -> [empty]
", iss_iter->first, iss_iter->second ); ++iss_iter; } else { window_line = StringFormat( "%i: (replace) %u -> %u
", iss_iter->first, iss_iter->second, inv_iter->second ); ++inv_iter; ++iss_iter; } } if (window_text.length() + window_line.length() < 4095) { window_text.append(window_line); } else { c->Message(Chat::White, "Too many comparison entries to list..."); break; } } c->SendPopupToClient(window_title.c_str(), window_text.c_str()); return; } if (strcmp(sep->arg[1], "restore") == 0) { if (!sep->IsNumber(2)) { c->Message(Chat::White, "A timestamp is required to use this option."); return; } uint32 timestamp = Strings::ToUnsignedInt(sep->arg[2]); if (!database.ValidateCharacterInvSnapshotTimestamp(tc->CharacterID(), timestamp)) { c->Message( Chat::White, "No inventory snapshots for %s (id: %u) exist at %u.", tc->GetName(), tc->CharacterID(), timestamp ); return; } if (database.SaveCharacterInvSnapshot(tc->CharacterID())) { tc->SetNextInvSnapshot(RuleI(Character, InvSnapshotMinIntervalM)); } else { c->Message( Chat::Red, "Failed to take pre-restore inventory snapshot of %s (id: %u).", tc->GetName(), tc->CharacterID()); return; } if (database.RestoreCharacterInvSnapshot(tc->CharacterID(), timestamp)) { // cannot delete all valid item slots from client..so, we worldkick tc->WorldKick(); // self restores update before the 'kick' is processed c->Message( Chat::White, "Successfully applied snapshot %u to %s's (id: %u) inventory.", timestamp, tc->GetName(), tc->CharacterID()); } else { c->Message( Chat::Red, "Failed to apply snapshot %u to %s's (id: %u) inventory.", timestamp, tc->GetName(), tc->CharacterID()); } return; } } }