mirror of
https://github.com/EQEmu/Server.git
synced 2026-01-04 07:23:57 +00:00
Merge git://github.com/EQEmu/Server into Development
This commit is contained in:
commit
5ec0b9993a
@ -1,5 +1,8 @@
|
||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||
-------------------------------------------------------
|
||||
== 10/28/2014 ==
|
||||
Uleat: Added Client::InterrogateInventory(). Can be invoked by #interrogateinv and is also called when Handle_OP_MoveItem() calls for SwapItemResync()
|
||||
|
||||
== 10/22/2014 ==
|
||||
Uleat: Fix for stacking items in a world object..added a new command option: #peekinv world - will show world container contents, if one is in use by target.
|
||||
|
||||
|
||||
@ -261,7 +261,8 @@ enum {
|
||||
commandChangeFlags = 200, //ability to set/refresh flags
|
||||
commandBanPlayers = 100, //can set bans on players
|
||||
commandChangeDatarate = 201, //edit client's data rate
|
||||
commandZoneToCoords = 0 //can #zone with coords
|
||||
commandZoneToCoords = 0, //can #zone with coords
|
||||
commandInterrogateInv = 100 //below this == only log on error state and self-only target dump
|
||||
};
|
||||
|
||||
//default states for logging flag on NPCs and clients (having NPCs on by default is prolly a bad idea)
|
||||
|
||||
@ -327,6 +327,8 @@ Client::Client(EQStreamInterface* ieqs)
|
||||
|
||||
EngagedRaidTarget = false;
|
||||
SavedRaidRestTimer = 0;
|
||||
|
||||
interrogateinv_flag = false;
|
||||
}
|
||||
|
||||
Client::~Client() {
|
||||
|
||||
@ -1212,6 +1212,11 @@ public:
|
||||
|
||||
void ShowNumHits(); // work around function for numhits not showing on buffs
|
||||
|
||||
void TripInterrogateInvState() { interrogateinv_flag = true; }
|
||||
bool GetInterrogateInvState() { return interrogateinv_flag; }
|
||||
|
||||
bool InterrogateInventory(Client* requester, bool log, bool silent, bool allowtrip, bool& error, bool autolog = true);
|
||||
|
||||
protected:
|
||||
friend class Mob;
|
||||
void CalcItemBonuses(StatBonuses* newbon);
|
||||
@ -1524,6 +1529,11 @@ private:
|
||||
std::map<std::string,std::string> accountflags;
|
||||
|
||||
uint8 initial_respawn_selection;
|
||||
|
||||
bool interrogateinv_flag; // used to minimize log spamming by players
|
||||
|
||||
void InterrogateInventory_(bool errorcheck, Client* requester, int16 head, int16 index, const ItemInst* inst, const ItemInst* parent, bool log, bool silent, bool &error, int depth);
|
||||
bool InterrogateInventory_error(int16 head, int16 index, const ItemInst* inst, const ItemInst* parent, int depth);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -9915,7 +9915,14 @@ void Client::Handle_OP_MoveItem(const EQApplicationPacket *app)
|
||||
|
||||
if (mi_hack) { Message(15, "Caution: Illegal use of inaccessable bag slots!"); }
|
||||
|
||||
if (!SwapItem(mi) && IsValidSlot(mi->from_slot) && IsValidSlot(mi->to_slot)) { SwapItemResync(mi); }
|
||||
if (!SwapItem(mi) && IsValidSlot(mi->from_slot) && IsValidSlot(mi->to_slot)) {
|
||||
SwapItemResync(mi);
|
||||
|
||||
bool error = false;
|
||||
InterrogateInventory(this, false, true, false, error, false);
|
||||
if (error)
|
||||
InterrogateInventory(this, true, false, true, error);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -259,6 +259,7 @@ int command_init(void) {
|
||||
command_add("appearance","[type] [value] - Send an appearance packet for you or your target",150,command_appearance) ||
|
||||
command_add("nukeitem","[itemid] - Remove itemid from your player target's inventory",150,command_nukeitem) ||
|
||||
command_add("peekinv","[worn/inv/cursor/trib/bank/trade/world/all] - Print out contents of your player target's inventory",100,command_peekinv) ||
|
||||
command_add("interrogateinv","- use [help] argument for available options",0,command_interrogateinv) ||
|
||||
command_add("findnpctype","[search criteria] - Search database NPC types",100,command_findnpctype) ||
|
||||
command_add("findzone","[search criteria] - Search database zones",100,command_findzone) ||
|
||||
command_add("fz",nullptr,100, command_findzone) ||
|
||||
@ -3002,12 +3003,80 @@ void command_peekinv(Client *c, const Seperator *sep)
|
||||
|
||||
if (!bFound)
|
||||
{
|
||||
c->Message(0, "Usage: #peekinv [worn|cursor|inv|bank|trade|trib|all]");
|
||||
c->Message(0, "Usage: #peekinv [worn|inv|cursor|trib|bank|trade|world|all]");
|
||||
c->Message(0, " Displays a portion of the targeted user's inventory");
|
||||
c->Message(0, " Caution: 'all' is a lot of information!");
|
||||
}
|
||||
}
|
||||
|
||||
void command_interrogateinv(Client *c, const Seperator *sep)
|
||||
{
|
||||
// 'command_interrogateinv' is an in-memory inventory interrogation tool only.
|
||||
//
|
||||
// it does not verify against actual database entries..but, the output can be
|
||||
// used to verify that something has been corrupted in a player's inventory.
|
||||
// any error condition should be assumed that the item in question will be
|
||||
// lost when the player logs out or zones (or incurrs any action that will
|
||||
// consume the Client-Inventory object instance in question.)
|
||||
//
|
||||
// any item instances located at a greater depth than a reported error should
|
||||
// be treated as an error themselves regardless of whether they report as the
|
||||
// same or not.
|
||||
|
||||
if (strcasecmp(sep->arg[1], "help") == 0) {
|
||||
if (c->Admin() < commandInterrogateInv) {
|
||||
c->Message(0, "Usage: #interrogateinv");
|
||||
c->Message(0, " Displays your inventory's current in-memory nested storage references");
|
||||
}
|
||||
else {
|
||||
c->Message(0, "Usage: #interrogateinv [log] [silent]");
|
||||
c->Message(0, " Displays your or your Player target inventory's current in-memory nested storage references");
|
||||
c->Message(0, " [log] - Logs interrogation to file");
|
||||
c->Message(0, " [silent] - Omits the in-game message portion of the interrogation");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Client* target = nullptr;
|
||||
std::map<int16, const ItemInst*> instmap;
|
||||
bool log = false;
|
||||
bool silent = false;
|
||||
bool error = false;
|
||||
bool allowtrip = false;
|
||||
|
||||
if (c->Admin() < commandInterrogateInv) {
|
||||
if (c->GetInterrogateInvState()) {
|
||||
c->Message(13, "The last use of #interrogateinv on this inventory instance discovered an error...");
|
||||
c->Message(13, "Logging out, zoning or re-arranging items at this point will result in item loss!");
|
||||
return;
|
||||
}
|
||||
target = c;
|
||||
allowtrip = true;
|
||||
}
|
||||
else {
|
||||
if (c->GetTarget() == nullptr) {
|
||||
target = c;
|
||||
}
|
||||
else if (c->GetTarget()->IsClient()) {
|
||||
target = c->GetTarget()->CastToClient();
|
||||
}
|
||||
else {
|
||||
c->Message(1, "Use of this command is limited to Client entities");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcasecmp(sep->arg[1], "log") == 0)
|
||||
log = true;
|
||||
if (strcasecmp(sep->arg[2], "silent") == 0)
|
||||
silent = true;
|
||||
}
|
||||
|
||||
bool success = target->InterrogateInventory(c, log, silent, allowtrip, error);
|
||||
|
||||
if (!success)
|
||||
c->Message(13, "An unknown error occurred while processing Client::InterrogateInventory()");
|
||||
}
|
||||
|
||||
void command_findnpctype(Client *c, const Seperator *sep)
|
||||
{
|
||||
if(sep->arg[1][0] == 0) {
|
||||
|
||||
@ -152,6 +152,7 @@ void command_heal(Client *c, const Seperator *sep);
|
||||
void command_appearance(Client *c, const Seperator *sep);
|
||||
void command_nukeitem(Client *c, const Seperator *sep);
|
||||
void command_peekinv(Client *c, const Seperator *sep);
|
||||
void command_interrogateinv(Client *c, const Seperator *sep);
|
||||
void command_findnpctype(Client *c, const Seperator *sep);
|
||||
void command_findzone(Client *c, const Seperator *sep);
|
||||
void command_viewnpctype(Client *c, const Seperator *sep);
|
||||
|
||||
@ -2732,6 +2732,211 @@ bool Client::MoveItemToInventory(ItemInst *ItemToReturn, bool UpdateClient) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Client::InterrogateInventory(Client* requester, bool log, bool silent, bool allowtrip, bool& error, bool autolog)
|
||||
{
|
||||
if (!requester)
|
||||
return false;
|
||||
|
||||
std::map<int16, const ItemInst*> instmap;
|
||||
|
||||
// build reference map
|
||||
for (int16 index = MAIN_BEGIN; index < EmuConstants::MAP_POSSESSIONS_SIZE; ++index)
|
||||
if (m_inv[index])
|
||||
instmap[index] = m_inv[index];
|
||||
for (int16 index = EmuConstants::TRIBUTE_BEGIN; index <= EmuConstants::TRIBUTE_END; ++index)
|
||||
if (m_inv[index])
|
||||
instmap[index] = m_inv[index];
|
||||
for (int16 index = EmuConstants::BANK_BEGIN; index <= EmuConstants::BANK_END; ++index)
|
||||
if (m_inv[index])
|
||||
instmap[index] = m_inv[index];
|
||||
for (int16 index = EmuConstants::SHARED_BANK_BEGIN; index <= EmuConstants::SHARED_BANK_END; ++index)
|
||||
if (m_inv[index])
|
||||
instmap[index] = m_inv[index];
|
||||
for (int16 index = EmuConstants::TRADE_BEGIN; index <= EmuConstants::TRADE_END; ++index)
|
||||
if (m_inv[index])
|
||||
instmap[index] = m_inv[index];
|
||||
|
||||
if (Object* tsobject = GetTradeskillObject())
|
||||
for (int16 index = MAIN_BEGIN; index < EmuConstants::MAP_WORLD_SIZE; ++index)
|
||||
if (tsobject->GetItem(index))
|
||||
instmap[EmuConstants::WORLD_BEGIN + index] = tsobject->GetItem(index);
|
||||
|
||||
int limbo = 0;
|
||||
for (iter_queue cursor_itr = m_inv.cursor_begin(); cursor_itr != m_inv.cursor_end(); ++cursor_itr, ++limbo) {
|
||||
if (cursor_itr == m_inv.cursor_begin()) // m_inv.cursor_begin() is referenced as MainCursor in MapPossessions above
|
||||
continue;
|
||||
|
||||
instmap[8000 + limbo] = *cursor_itr;
|
||||
}
|
||||
|
||||
if (m_inv[MainPowerSource])
|
||||
instmap[MainPowerSource] = m_inv[MainPowerSource];
|
||||
|
||||
// call InterrogateInventory_ for error check
|
||||
for (std::map<int16, const ItemInst*>::iterator instmap_itr = instmap.begin(); (instmap_itr != instmap.end()) && (!error); ++instmap_itr)
|
||||
InterrogateInventory_(true, requester, instmap_itr->first, INVALID_INDEX, instmap_itr->second, nullptr, log, silent, error, 0);
|
||||
|
||||
if (autolog && error && (!log))
|
||||
log = true;
|
||||
|
||||
if (log)
|
||||
_log(INVENTORY__ERROR, "Client::InterrogateInventory() called for %s by %s with an error state of %s", GetName(), requester->GetName(), (error ? "TRUE" : "FALSE"));
|
||||
if (!silent)
|
||||
requester->Message(1, "--- Inventory Interrogation Report for %s (requested by: %s, error state: %s) ---", GetName(), requester->GetName(), (error ? "TRUE" : "FALSE"));
|
||||
|
||||
// call InterrogateInventory_ for report
|
||||
for (std::map<int16, const ItemInst*>::iterator instmap_itr = instmap.begin(); (instmap_itr != instmap.end()); ++instmap_itr)
|
||||
InterrogateInventory_(false, requester, instmap_itr->first, INVALID_INDEX, instmap_itr->second, nullptr, log, silent, error, 0);
|
||||
|
||||
if (error) {
|
||||
Message(13, "An error has been discovered in your inventory!");
|
||||
Message(13, "Do not log out, zone or re-arrange items until this");
|
||||
Message(13, "issue has been resolved or item loss may occur!");
|
||||
|
||||
if (allowtrip)
|
||||
TripInterrogateInvState();
|
||||
}
|
||||
|
||||
if (log) {
|
||||
_log(INVENTORY__ERROR, "Target interrogate inventory flag: %s", (GetInterrogateInvState() ? "TRUE" : "FALSE"));
|
||||
_log(INVENTORY__ERROR, "Client::InterrogateInventory() -- End");
|
||||
}
|
||||
if (!silent) {
|
||||
requester->Message(1, "Target interrogation flag: %s", (GetInterrogateInvState() ? "TRUE" : "FALSE"));
|
||||
requester->Message(1, "--- End of Interrogation Report ---");
|
||||
}
|
||||
|
||||
instmap.clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Client::InterrogateInventory_(bool errorcheck, Client* requester, int16 head, int16 index, const ItemInst* inst, const ItemInst* parent, bool log, bool silent, bool &error, int depth)
|
||||
{
|
||||
if (depth >= 10) {
|
||||
_log(INVENTORY__ERROR, "Client::InterrogateInventory_() - Recursion count has exceeded the maximum allowable (You have a REALLY BIG PROBLEM!!)");
|
||||
return;
|
||||
}
|
||||
|
||||
if (errorcheck) {
|
||||
if (InterrogateInventory_error(head, index, inst, parent, depth)) {
|
||||
error = true;
|
||||
}
|
||||
else {
|
||||
if (inst)
|
||||
for (int16 sub = SUB_BEGIN; (sub < EmuConstants::ITEM_CONTAINER_SIZE) && (!error); ++sub) // treat any ItemInst as having the max internal slots available
|
||||
if (inst->GetItem(sub))
|
||||
InterrogateInventory_(true, requester, head, sub, inst->GetItem(sub), inst, log, silent, error, depth + 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
bool localerror = InterrogateInventory_error(head, index, inst, parent, depth);
|
||||
std::string i;
|
||||
std::string p;
|
||||
std::string e;
|
||||
|
||||
if (inst) { i = StringFormat("%s (class: %u | augtype: %u)", inst->GetItem()->Name, inst->GetItem()->ItemClass, inst->GetItem()->AugType); }
|
||||
else { i = "NONE"; }
|
||||
if (parent) { p = StringFormat("%s (class: %u | augtype: %u), index: %i", parent->GetItem()->Name, parent->GetItem()->ItemClass, parent->GetItem()->AugType, index); }
|
||||
else { p = "NONE"; }
|
||||
if (localerror) { e = " [ERROR]"; }
|
||||
else { e = ""; }
|
||||
|
||||
if (log)
|
||||
_log(INVENTORY__ERROR, "Head: %i, Depth: %i, Instance: %s, Parent: %s%s",
|
||||
head, depth, i.c_str(), p.c_str(), e.c_str());
|
||||
if (!silent)
|
||||
requester->Message(1, "%i:%i - inst: %s - parent: %s%s",
|
||||
head, depth, i.c_str(), p.c_str(), e.c_str());
|
||||
|
||||
if (inst)
|
||||
for (int16 sub = SUB_BEGIN; (sub < EmuConstants::ITEM_CONTAINER_SIZE); ++sub)
|
||||
if (inst->GetItem(sub))
|
||||
InterrogateInventory_(false, requester, head, sub, inst->GetItem(sub), inst, log, silent, error, depth + 1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool Client::InterrogateInventory_error(int16 head, int16 index, const ItemInst* inst, const ItemInst* parent, int depth)
|
||||
{
|
||||
// very basic error checking - can be elaborated upon if more in-depth testing is needed...
|
||||
|
||||
if (
|
||||
(head >= EmuConstants::EQUIPMENT_BEGIN && head <= EmuConstants::EQUIPMENT_END) ||
|
||||
(head >= EmuConstants::TRIBUTE_BEGIN && head <= EmuConstants::TRIBUTE_END) ||
|
||||
(head >= EmuConstants::WORLD_BEGIN && head <= EmuConstants::WORLD_END) ||
|
||||
(head >= 8000 && head <= 8101) ||
|
||||
(head == MainPowerSource)) {
|
||||
switch (depth)
|
||||
{
|
||||
case 0: // requirement: inst is extant
|
||||
if (!inst)
|
||||
return true;
|
||||
break;
|
||||
case 1: // requirement: parent is common and inst is augment
|
||||
if ((!parent) || (!inst))
|
||||
return true;
|
||||
if (!parent->IsType(ItemClassCommon))
|
||||
return true;
|
||||
if (index >= EmuConstants::ITEM_COMMON_SIZE)
|
||||
return true;
|
||||
break;
|
||||
default: // requirement: none (something bad happened...)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (
|
||||
(head >= EmuConstants::GENERAL_BEGIN && head <= EmuConstants::GENERAL_END) ||
|
||||
(head == MainCursor) ||
|
||||
(head >= EmuConstants::BANK_BEGIN && head <= EmuConstants::BANK_END) ||
|
||||
(head >= EmuConstants::SHARED_BANK_BEGIN && head <= EmuConstants::SHARED_BANK_END) ||
|
||||
(head >= EmuConstants::TRADE_BEGIN && head <= EmuConstants::TRADE_END)) {
|
||||
switch (depth)
|
||||
{
|
||||
case 0: // requirement: inst is extant
|
||||
if (!inst)
|
||||
return true;
|
||||
break;
|
||||
case 1: // requirement: parent is common and inst is augment ..or.. parent is container and inst is extant
|
||||
if ((!parent) || (!inst))
|
||||
return true;
|
||||
if (parent->IsType(ItemClassContainer))
|
||||
break;
|
||||
if (parent->IsType(ItemClassBook))
|
||||
return true;
|
||||
if (parent->IsType(ItemClassCommon)) {
|
||||
if (!(inst->GetItem()->AugType > 0))
|
||||
return true;
|
||||
if (index >= EmuConstants::ITEM_COMMON_SIZE)
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case 2: // requirement: parent is common and inst is augment
|
||||
if ((!parent) || (!inst))
|
||||
return true;
|
||||
if (parent->IsType(ItemClassContainer))
|
||||
return true;
|
||||
if (parent->IsType(ItemClassBook))
|
||||
return true;
|
||||
if (parent->IsType(ItemClassCommon)) {
|
||||
if (!(inst->GetItem()->AugType > 0))
|
||||
return true;
|
||||
if (index >= EmuConstants::ITEM_COMMON_SIZE)
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default: // requirement: none (something bad happened again...)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Inventory::SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, std::string value) {
|
||||
ItemInst *inst = GetItem(slot_id);
|
||||
if(inst) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user