Merge git://github.com/EQEmu/Server into Development

This commit is contained in:
KayenEQ 2014-10-30 19:51:22 -04:00
commit 5ec0b9993a
8 changed files with 301 additions and 3 deletions

View File

@ -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.

View File

@ -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)

View File

@ -327,6 +327,8 @@ Client::Client(EQStreamInterface* ieqs)
EngagedRaidTarget = false;
SavedRaidRestTimer = 0;
interrogateinv_flag = false;
}
Client::~Client() {

View File

@ -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

View File

@ -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;
}

View File

@ -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) {

View File

@ -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);

View File

@ -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) {