Fix and overhaul to bug reporting system

This commit is contained in:
Uleat 2018-02-18 14:03:13 -05:00
parent 97bb50a5c4
commit a493242c3c
23 changed files with 618 additions and 282 deletions

View File

@ -1,5 +1,13 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50)
-------------------------------------------------------
== 02/18/2018 ==
Uleat: Bug reporting fix and overhaul.
- Fixed bug reporting for SoD+ clients
- Added ability to disable bug reporting (set rule 'Bugs:ReportingSystemActive' to 'false')
- Implemented a more detailed reporting system (set rule 'Bugs:UseOldReportingMethod' to 'false')
-- New system is not currently compatible with script-based monitoring
- Soft-removal of defunct 'Petition Bug' system
== 02/14/2018 ==
mackal: Fix Heading -- Quests broken

View File

@ -18,3 +18,68 @@
*/
#include "emu_constants.h"
const char* EQEmu::bug::CategoryIDToCategoryName(CategoryID category_id) {
switch (category_id) {
case catVideo:
return "Video";
case catAudio:
return "Audio";
case catPathing:
return "Pathing";
case catQuest:
return "Quest";
case catTradeskills:
return "Tradeskills";
case catSpellStacking:
return "Spell stacking";
case catDoorsPortals:
return "Doors/Portals";
case catItems:
return "Items";
case catNPC:
return "NPC";
case catDialogs:
return "Dialogs";
case catLoNTCG:
return "LoN - TCG";
case catMercenaries:
return "Mercenaries";
case catOther:
default:
return "Other";
}
}
EQEmu::bug::CategoryID EQEmu::bug::CategoryNameToCategoryID(const char* category_name) {
if (!category_name)
return catOther;
if (!strcmp(category_name, "Video"))
return catVideo;
if (!strcmp(category_name, "Audio"))
return catAudio;
if (!strcmp(category_name, "Pathing"))
return catPathing;
if (!strcmp(category_name, "Quest"))
return catQuest;
if (!strcmp(category_name, "Tradeskills"))
return catTradeskills;
if (!strcmp(category_name, "Spell stacking"))
return catSpellStacking;
if (!strcmp(category_name, "Doors/Portals"))
return catDoorsPortals;
if (!strcmp(category_name, "Items"))
return catItems;
if (!strcmp(category_name, "NPC"))
return catNPC;
if (!strcmp(category_name, "Dialogs"))
return catDialogs;
if (!strcmp(category_name, "LoN - TCG"))
return catLoNTCG;
if (!strcmp(category_name, "Mercenaries"))
return catMercenaries;
return catOther;
}

View File

@ -126,6 +126,37 @@ namespace EQEmu
} /*constants*/
namespace bug {
enum CategoryID : uint32 {
catOther = 0,
catVideo,
catAudio,
catPathing,
catQuest,
catTradeskills,
catSpellStacking,
catDoorsPortals,
catItems,
catNPC,
catDialogs,
catLoNTCG,
catMercenaries
};
enum OptionalInfoFlag : uint32 {
infoNoOptionalInfo = 0x0,
infoCanDuplicate = 0x1,
infoCrashBug = 0x2,
infoTargetInfo = 0x4,
infoCharacterFlags = 0x8,
infoUnknownValue = 0xFFFFFFF0
};
const char* CategoryIDToCategoryName(CategoryID category_id);
CategoryID CategoryNameToCategoryID(const char* category_name);
} // namespace bug
enum class CastingSlot : uint32 {
Gem1 = 0,
Gem2 = 1,

View File

@ -3323,23 +3323,32 @@ struct GuildMakeLeader{
char target[64];
};
struct BugStruct{
/*0000*/ char chartype[64];
/*0064*/ char name[96];
/*0160*/ char ui[128];
/*0288*/ float x;
/*0292*/ float y;
/*0296*/ float z;
/*0300*/ float heading;
/*0304*/ uint32 unknown304;
/*0308*/ char unknown308[160];
/*0468*/ char target_name[64];
/*0532*/ uint32 type;
/*0536*/ char unknown536[2052];
/*2584*/ char bug[2048];
/*4632*/ char unknown4632[6];
/*4638*/ char system_info[4094];
struct BugReport_Struct {
/*0000*/ uint32 category_id;
/*0004*/ char category_name[64];
/*0068*/ char reporter_name[64];
/*0132*/ char unused_0132[32];
/*0164*/ char ui_path[128];
/*0292*/ float pos_x;
/*0296*/ float pos_y;
/*0300*/ float pos_z;
/*0304*/ uint32 heading;
/*0308*/ uint32 unused_0308;
/*0312*/ uint32 time_played;
/*0316*/ char padding_0316[8];
/*0324*/ uint32 target_id;
/*0328*/ char padding_0328[140];
/*0468*/ uint32 unknown_0468; // seems to always be '0'
/*0472*/ char target_name[64];
/*0536*/ uint32 optional_info_mask;
// this looks like a butchered 8k buffer with 2 trailing dword fields
/*0540*/ char unused_0540[2052];
/*2592*/ char bug_report[2050];
/*4642*/ char system_info[4098];
/*8740*/
};
struct Make_Pet_Struct { //Simple struct for getting pet info
uint8 level;
uint8 class_;
@ -3366,20 +3375,21 @@ struct Ground_Spawn{
struct Ground_Spawns {
struct Ground_Spawn spawn[50]; //Assigned max number to allow
};
struct PetitionBug_Struct{
uint32 petition_number;
uint32 unknown4;
char accountname[64];
uint32 zoneid;
char name[64];
uint32 level;
uint32 class_;
uint32 race;
uint32 unknown152[3];
uint32 time;
uint32 unknown168;
char text[1028];
};
//struct PetitionBug_Struct{
// uint32 petition_number;
// uint32 unknown4;
// char accountname[64];
// uint32 zoneid;
// char name[64];
// uint32 level;
// uint32 class_;
// uint32 race;
// uint32 unknown152[3];
// uint32 time;
// uint32 unknown168;
// char text[1028];
//};
struct ApproveZone_Struct {
char name[64];

View File

@ -3605,21 +3605,6 @@ struct GuildSetRank_Struct
/*80*/
};
struct BugStruct{
/*0000*/ char chartype[64];
/*0064*/ char name[96];
/*0160*/ char ui[128];
/*0288*/ float x;
/*0292*/ float y;
/*0296*/ float z;
/*0300*/ float heading;
/*0304*/ uint32 unknown304;
/*0308*/ uint32 type;
/*0312*/ char unknown312[2144];
/*2456*/ char bug[1024];
/*3480*/ char placeholder[2];
/*3482*/ char system_info[4098];
};
struct Make_Pet_Struct { //Simple struct for getting pet info
uint8 level;
uint8 class_;
@ -3646,20 +3631,21 @@ struct Ground_Spawn{
struct Ground_Spawns {
struct Ground_Spawn spawn[50]; //Assigned max number to allow
};
struct PetitionBug_Struct{
uint32 petition_number;
uint32 unknown4;
char accountname[64];
uint32 zoneid;
char name[64];
uint32 level;
uint32 class_;
uint32 race;
uint32 unknown152[3];
uint32 time;
uint32 unknown168;
char text[1028];
};
//struct PetitionBug_Struct{
// uint32 petition_number;
// uint32 unknown4;
// char accountname[64];
// uint32 zoneid;
// char name[64];
// uint32 level;
// uint32 class_;
// uint32 race;
// uint32 unknown152[3];
// uint32 time;
// uint32 unknown168;
// char text[1028];
//};
struct ApproveZone_Struct {
char name[64];

View File

@ -3545,21 +3545,6 @@ struct GuildSetRank_Struct
/*80*/
};
struct BugStruct{
/*0000*/ char chartype[64];
/*0064*/ char name[96];
/*0160*/ char ui[128];
/*0288*/ float x;
/*0292*/ float y;
/*0296*/ float z;
/*0300*/ float heading;
/*0304*/ uint32 unknown304;
/*0308*/ uint32 type;
/*0312*/ char unknown312[2144];
/*2456*/ char bug[1024];
/*3480*/ char placeholder[2];
/*3482*/ char system_info[4098];
};
struct Make_Pet_Struct { //Simple struct for getting pet info
uint8 level;
uint8 class_;
@ -3586,20 +3571,21 @@ struct Ground_Spawn{
struct Ground_Spawns {
struct Ground_Spawn spawn[50]; //Assigned max number to allow
};
struct PetitionBug_Struct{
uint32 petition_number;
uint32 unknown4;
char accountname[64];
uint32 zoneid;
char name[64];
uint32 level;
uint32 class_;
uint32 race;
uint32 unknown152[3];
uint32 time;
uint32 unknown168;
char text[1028];
};
//struct PetitionBug_Struct{
// uint32 petition_number;
// uint32 unknown4;
// char accountname[64];
// uint32 zoneid;
// char name[64];
// uint32 level;
// uint32 class_;
// uint32 race;
// uint32 unknown152[3];
// uint32 time;
// uint32 unknown168;
// char text[1028];
//};
struct ApproveZone_Struct {
char name[64];

View File

@ -2933,25 +2933,6 @@ namespace SoD
FINISH_DIRECT_DECODE();
}
DECODE(OP_Bug)
{
DECODE_LENGTH_EXACT(structs::BugStruct);
SETUP_DIRECT_DECODE(BugStruct, structs::BugStruct);
strn0cpy(emu->chartype, eq->chartype, sizeof(emu->chartype));
strn0cpy(emu->name, eq->name, sizeof(emu->name));
strn0cpy(emu->ui, eq->ui, sizeof(emu->ui));
IN(x);
IN(y);
IN(z);
IN(heading);
strn0cpy(emu->target_name, eq->target_name, sizeof(emu->target_name));
strn0cpy(emu->bug, eq->bug, sizeof(emu->bug));
strn0cpy(emu->system_info, eq->system_info, sizeof(emu->system_info));
FINISH_DIRECT_DECODE();
}
DECODE(OP_CastSpell)
{
DECODE_LENGTH_EXACT(structs::CastSpell_Struct);

View File

@ -104,7 +104,6 @@ D(OP_AugmentInfo)
D(OP_AugmentItem)
D(OP_BazaarSearch)
D(OP_Buff)
D(OP_Bug)
D(OP_CastSpell)
D(OP_ChannelMessage)
D(OP_CharacterCreate)

View File

@ -3008,24 +3008,6 @@ struct GuildMakeLeader{
char target[64];
};
struct BugStruct{
/*0000*/ uint32 type1; //seems to be just a different way of seeing type; seems to be ordered completely differently
/*0004*/ char chartype[64];
/*0068*/ char name[96];
/*0164*/ char ui[128];
/*0292*/ float x;
/*0296*/ float y;
/*0300*/ float z;
/*0304*/ float heading;
/*0308*/ uint32 unknown304;
/*0312*/ char unknown308[160];
/*0472*/ char target_name[64];
/*0536*/ uint32 type;
/*0540*/ char unknown536[2052];
/*2588*/ char bug[2048];
/*4636*/ char unknown4632[6];
/*4642*/ char system_info[4094];
};
struct Make_Pet_Struct { //Simple struct for getting pet info
uint8 level;
uint8 class_;
@ -3052,20 +3034,21 @@ struct Ground_Spawn{
struct Ground_Spawns {
struct Ground_Spawn spawn[50]; //Assigned max number to allow
};
struct PetitionBug_Struct{
uint32 petition_number;
uint32 unknown4;
char accountname[64];
uint32 zoneid;
char name[64];
uint32 level;
uint32 class_;
uint32 race;
uint32 unknown152[3];
uint32 time;
uint32 unknown168;
char text[1028];
};
//struct PetitionBug_Struct{
// uint32 petition_number;
// uint32 unknown4;
// char accountname[64];
// uint32 zoneid;
// char name[64];
// uint32 level;
// uint32 class_;
// uint32 race;
// uint32 unknown152[3];
// uint32 time;
// uint32 unknown168;
// char text[1028];
//};
struct ApproveZone_Struct {
char name[64];

View File

@ -2385,6 +2385,17 @@ namespace SoF
FINISH_DIRECT_DECODE();
}
DECODE(OP_Bug)
{
DECODE_LENGTH_EXACT(structs::BugReport_Struct);
SETUP_DIRECT_DECODE(BugReport_Struct, structs::BugReport_Struct);
emu->category_id = EQEmu::bug::CategoryNameToCategoryID(eq->category_name);
memcpy(emu->category_name, eq, sizeof(structs::BugReport_Struct));
FINISH_DIRECT_DECODE();
}
DECODE(OP_CastSpell)
{
DECODE_LENGTH_EXACT(structs::CastSpell_Struct);

View File

@ -95,6 +95,7 @@ D(OP_ApplyPoison)
D(OP_AugmentInfo)
D(OP_AugmentItem)
D(OP_Buff)
D(OP_Bug)
D(OP_CastSpell)
D(OP_ChannelMessage)
D(OP_CharacterCreate)

View File

@ -2906,23 +2906,31 @@ struct GuildMakeLeader{
char target[64];
};
struct BugReport_Struct {
/*0000*/ char category_name[64];
/*0064*/ char character_name[64];
/*0128*/ char unused_0128[32];
/*0160*/ char ui_path[128];
/*0288*/ float pos_x;
/*0292*/ float pos_y;
/*0296*/ float pos_z;
/*0300*/ uint32 heading;
/*0304*/ uint32 unused_0304;
/*0308*/ uint32 time_played;
/*0312*/ char padding_0312[8];
/*0320*/ uint32 target_id;
/*0324*/ char padding_0324[140];
/*0464*/ uint32 unknown_0464; // seems to always be '0'
/*0468*/ char target_name[64];
/*0532*/ uint32 optional_info_mask;
struct BugStruct{
/*0000*/ char chartype[64];
/*0064*/ char name[96];
/*0160*/ char ui[128];
/*0288*/ float x;
/*0292*/ float y;
/*0296*/ float z;
/*0300*/ float heading;
/*0304*/ uint32 unknown304;
/*0308*/ uint32 type;
/*0312*/ char unknown312[2144];
/*2456*/ char bug[1024];
/*3480*/ char placeholder[2];
/*3482*/ char system_info[4098];
// this looks like a butchered 8k buffer with 2 trailing dword fields
/*0536*/ char unused_0536[2052];
/*2588*/ char bug_report[2050];
/*4638*/ char system_info[4098];
/*8736*/
};
struct Make_Pet_Struct { //Simple struct for getting pet info
uint8 level;
uint8 class_;
@ -2949,20 +2957,21 @@ struct Ground_Spawn{
struct Ground_Spawns {
struct Ground_Spawn spawn[50]; //Assigned max number to allow
};
struct PetitionBug_Struct{
uint32 petition_number;
uint32 unknown4;
char accountname[64];
uint32 zoneid;
char name[64];
uint32 level;
uint32 class_;
uint32 race;
uint32 unknown152[3];
uint32 time;
uint32 unknown168;
char text[1028];
};
//struct PetitionBug_Struct{
// uint32 petition_number;
// uint32 unknown4;
// char accountname[64];
// uint32 zoneid;
// char name[64];
// uint32 level;
// uint32 class_;
// uint32 race;
// uint32 unknown152[3];
// uint32 time;
// uint32 unknown168;
// char text[1028];
//};
struct ApproveZone_Struct {
char name[64];

View File

@ -1789,6 +1789,17 @@ namespace Titanium
FINISH_DIRECT_DECODE();
}
DECODE(OP_Bug)
{
DECODE_LENGTH_EXACT(structs::BugReport_Struct);
SETUP_DIRECT_DECODE(BugReport_Struct, structs::BugReport_Struct);
emu->category_id = EQEmu::bug::CategoryNameToCategoryID(eq->category_name);
memcpy(emu->category_name, eq, sizeof(structs::BugReport_Struct));
FINISH_DIRECT_DECODE();
}
DECODE(OP_CastSpell)
{
DECODE_LENGTH_EXACT(structs::CastSpell_Struct);

View File

@ -78,6 +78,7 @@ D(OP_AdventureMerchantSell)
D(OP_ApplyPoison)
D(OP_AugmentItem)
D(OP_Buff)
D(OP_Bug)
D(OP_CastSpell)
D(OP_ChannelMessage)
D(OP_CharacterCreate)

View File

@ -2571,21 +2571,32 @@ struct GuildMakeLeader{
char name[64];
char target[64];
};
struct BugStruct{
/*0000*/ char chartype[64];
/*0064*/ char name[96];
/*0160*/ char ui[128];
/*0288*/ float x;
/*0292*/ float y;
/*0296*/ float z;
/*0300*/ float heading;
/*0304*/ uint32 unknown304;
/*0308*/ uint32 type;
/*0312*/ char unknown312[2144];
/*2456*/ char bug[1024];
/*3480*/ char placeholder[2];
/*3482*/ char system_info[4098];
struct BugReport_Struct {
/*0000*/ char category_name[64];
/*0064*/ char character_name[64];
/*0128*/ char unused_0128[32];
/*0160*/ char ui_path[128];
/*0288*/ float pos_x;
/*0292*/ float pos_y;
/*0296*/ float pos_z;
/*0300*/ uint32 heading;
/*0304*/ uint32 unused_0304;
/*0308*/ uint32 time_played;
/*0312*/ char padding_0312[8];
/*0320*/ uint32 target_id;
/*0324*/ char padding_0324[140];
/*0464*/ uint32 unknown_0464; // seems to always be '0'
/*0468*/ char target_name[64];
/*0532*/ uint32 optional_info_mask;
// this looks like a butchered 8k buffer with 2 trailing dword fields
/*0536*/ char unused_0536[2052];
/*2588*/ char bug_report[2050];
/*4638*/ char system_info[4098];
/*8736*/
};
struct Make_Pet_Struct { //Simple struct for getting pet info
uint8 level;
uint8 class_;
@ -2612,20 +2623,21 @@ struct Ground_Spawn{
struct Ground_Spawns {
struct Ground_Spawn spawn[50]; //Assigned max number to allow
};
struct PetitionBug_Struct{
uint32 petition_number;
uint32 unknown4;
char accountname[64];
uint32 zoneid;
char name[64];
uint32 level;
uint32 class_;
uint32 race;
uint32 unknown152[3];
uint32 time;
uint32 unknown168;
char text[1028];
};
//struct PetitionBug_Struct{
// uint32 petition_number;
// uint32 unknown4;
// char accountname[64];
// uint32 zoneid;
// char name[64];
// uint32 level;
// uint32 class_;
// uint32 race;
// uint32 unknown152[3];
// uint32 time;
// uint32 unknown168;
// char text[1028];
//};
struct ApproveZone_Struct {
char name[64];

View File

@ -3060,23 +3060,6 @@ struct GuildMakeLeader{
char target[64];
};
struct BugStruct{
/*0000*/ char chartype[64];
/*0064*/ char name[96];
/*0160*/ char ui[128];
/*0288*/ float x;
/*0292*/ float y;
/*0296*/ float z;
/*0300*/ float heading;
/*0304*/ uint32 unknown304;
/*0308*/ uint32 type;
/*0312*/ char unknown312[2144];
/*2456*/ char bug[1024];
/*3480*/ char placeholder[2];
/*3482*/ char system_info[4098];
};
struct Make_Pet_Struct { //Simple struct for getting pet info
uint8 level;
uint8 class_;
@ -3103,20 +3086,21 @@ struct Ground_Spawn{
struct Ground_Spawns {
struct Ground_Spawn spawn[50]; //Assigned max number to allow
};
struct PetitionBug_Struct{
uint32 petition_number;
uint32 unknown4;
char accountname[64];
uint32 zoneid;
char name[64];
uint32 level;
uint32 class_;
uint32 race;
uint32 unknown152[3];
uint32 time;
uint32 unknown168;
char text[1028];
};
//struct PetitionBug_Struct{
// uint32 petition_number;
// uint32 unknown4;
// char accountname[64];
// uint32 zoneid;
// char name[64];
// uint32 level;
// uint32 class_;
// uint32 race;
// uint32 unknown152[3];
// uint32 time;
// uint32 unknown168;
// char text[1028];
//};
struct ApproveZone_Struct {
char name[64];

View File

@ -720,6 +720,12 @@ RULE_BOOL(Client, UseLiveFactionMessage, false) // Allows players to see faction
RULE_BOOL(Client, UseLiveBlockedMessage, false) // Allows players to see faction adjustments like Live
RULE_CATEGORY_END()
RULE_CATEGORY(Bugs)
RULE_BOOL(Bugs, ReportingSystemActive, true) // Activates bug reporting
RULE_BOOL(Bugs, UseOldReportingMethod, true) // Forces the use of the old bug reporting system
RULE_BOOL(Bugs, DumpTargetEntity, false) // Dumps the target entity, if one is provided
RULE_CATEGORY_END()
#undef RULE_CATEGORY
#undef RULE_INT
#undef RULE_REAL

View File

@ -30,7 +30,7 @@
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9120
#define CURRENT_BINARY_DATABASE_VERSION 9121
#ifdef BOTS
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9018
#else

View File

@ -374,6 +374,7 @@
9118|2018_02_04_Charm_Stats.sql|SHOW COLUMNS FROM `npc_types` LIKE 'charm_ac'|empty|
9119|2018_02_10_GlobalLoot.sql|SHOW TABLES LIKE 'global_loot'|empty|
9120|2018_02_13_Heading.sql|SELECT value FROM variables WHERE varname = 'fixed_heading'|empty|
9121|2018_02_18_bug_reports.sql|SHOW TABLES LIKE 'bug_reports'|empty|
# Upgrade conditions:
# This won't be needed after this system is implemented, but it is used database that are not

View File

@ -0,0 +1,44 @@
CREATE TABLE `bug_reports` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`zone` VARCHAR(32) NOT NULL DEFAULT 'Unknown',
`client_version_id` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`client_version_name` VARCHAR(24) NOT NULL DEFAULT 'Unknown',
`account_id` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`character_id` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`character_name` VARCHAR(64) NOT NULL DEFAULT 'Unknown',
`reporter_spoof` TINYINT(1) NOT NULL DEFAULT '1',
`category_id` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`category_name` VARCHAR(64) NOT NULL DEFAULT 'Other',
`reporter_name` VARCHAR(64) NOT NULL DEFAULT 'Unknown',
`ui_path` VARCHAR(128) NOT NULL DEFAULT 'Unknown',
`pos_x` FLOAT NOT NULL DEFAULT '0',
`pos_y` FLOAT NOT NULL DEFAULT '0',
`pos_z` FLOAT NOT NULL DEFAULT '0',
`heading` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`time_played` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`target_id` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`target_name` VARCHAR(64) NOT NULL DEFAULT 'Unknown',
`optional_info_mask` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`_can_duplicate` TINYINT(1) NOT NULL DEFAULT '0',
`_crash_bug` TINYINT(1) NOT NULL DEFAULT '0',
`_target_info` TINYINT(1) NOT NULL DEFAULT '0',
`_character_flags` TINYINT(1) NOT NULL DEFAULT '0',
`_unknown_value` TINYINT(1) NOT NULL DEFAULT '0',
`bug_report` VARCHAR(1024) NOT NULL DEFAULT '',
`system_info` VARCHAR(1024) NOT NULL DEFAULT '',
`report_datetime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`bug_status` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0',
`last_review` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`last_reviewer` VARCHAR(64) NOT NULL DEFAULT 'None',
`reviewer_notes` VARCHAR(1024) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
UNIQUE INDEX `id` (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES
(1, 'Bugs:ReportingSystemActive', 'true', 'Activates bug reporting'),
(1, 'Bugs:UseOldReportingMethod', 'true', 'Forces the use of the old bug reporting system'),
(1, 'Bugs:DumpTargetEntity', 'false', 'Dumps the target entity, if one is provided');

View File

@ -3960,12 +3960,23 @@ void Client::Handle_OP_BuffRemoveRequest(const EQApplicationPacket *app)
void Client::Handle_OP_Bug(const EQApplicationPacket *app)
{
if (app->size != sizeof(BugStruct))
printf("Wrong size of BugStruct got %d expected %zu!\n", app->size, sizeof(BugStruct));
else {
BugStruct* bug = (BugStruct*)app->pBuffer;
database.UpdateBug(bug);
if (!RuleB(Bugs, ReportingSystemActive)) {
Message(0, "Bug reporting is disabled on this server.");
return;
}
if (app->size != sizeof(BugReport_Struct)) {
printf("Wrong size of BugReport_Struct got %d expected %zu!\n", app->size, sizeof(BugReport_Struct));
}
else {
BugReport_Struct* bug_report = (BugReport_Struct*)app->pBuffer;
if (RuleB(Bugs, UseOldReportingMethod))
database.RegisterBug(bug_report);
else
database.RegisterBug(this, bug_report);
}
return;
}
@ -10553,11 +10564,8 @@ void Client::Handle_OP_Petition(const EQApplicationPacket *app)
void Client::Handle_OP_PetitionBug(const EQApplicationPacket *app)
{
if (app->size != sizeof(PetitionBug_Struct))
printf("Wrong size of BugStruct! Expected: %zu, Got: %i\n", sizeof(PetitionBug_Struct), app->size);
else {
Message(0, "Petition Bugs are not supported, please use /bug.");
}
Message(0, "Petition Bugs are not supported, please use /bug.");
return;
}

View File

@ -325,62 +325,260 @@ bool ZoneDatabase::logevents(const char* accountname,uint32 accountid,uint8 stat
return true;
}
void ZoneDatabase::RegisterBug(BugReport_Struct* bug_report) {
if (!bug_report)
return;
void ZoneDatabase::UpdateBug(BugStruct* bug) {
uint32 len = strlen(bug->bug);
char* bugtext = nullptr;
if(len > 0)
{
bugtext = new char[2*len+1];
memset(bugtext, 0, 2*len+1);
DoEscapeString(bugtext, bug->bug, len);
size_t len = 0;
char* name_ = nullptr;
char* ui_ = nullptr;
char* type_ = nullptr;
char* target_ = nullptr;
char* bug_ = nullptr;
len = strlen(bug_report->reporter_name);
if (len) {
if (len > 63) // check against db column size
len = 63;
name_ = new char[(2 * len + 1)];
memset(name_, 0, (2 * len + 1));
DoEscapeString(name_, bug_report->reporter_name, len);
}
len = strlen(bug->ui);
char* uitext = nullptr;
if(len > 0)
{
uitext = new char[2*len+1];
memset(uitext, 0, 2*len+1);
DoEscapeString(uitext, bug->ui, len);
len = strlen(bug_report->ui_path);
if (len) {
if (len > 127)
len = 127;
ui_ = new char[(2 * len + 1)];
memset(ui_, 0, (2 * len + 1));
DoEscapeString(ui_, bug_report->ui_path, len);
}
len = strlen(bug->target_name);
char* targettext = nullptr;
if(len > 0)
{
targettext = new char[2*len+1];
memset(targettext, 0, 2*len+1);
DoEscapeString(targettext, bug->target_name, len);
len = strlen(bug_report->category_name);
if (len) {
if (len > 63)
len = 63;
type_ = new char[(2 * len + 1)];
memset(type_, 0, (2 * len + 1));
DoEscapeString(type_, bug_report->category_name, len);
}
//x and y are intentionally swapped because eq is inversexy coords
std::string query = StringFormat("INSERT INTO bugs (zone, name, ui, x, y, z, type, flag, target, bug, date) "
len = strlen(bug_report->target_name);
if (len) {
if (len > 63)
len = 63;
target_ = new char[(2 * len + 1)];
memset(target_, 0, (2 * len + 1));
DoEscapeString(target_, bug_report->target_name, len);
}
len = strlen(bug_report->bug_report);
if (len) {
if (len > 1023)
len = 1023;
bug_ = new char[(2 * len + 1)];
memset(bug_, 0, (2 * len + 1));
DoEscapeString(bug_, bug_report->bug_report, len);
}
//x and y are intentionally swapped because eq is inversexy coords //is this msg out-of-date or are the parameters wrong?
std::string query = StringFormat(
"INSERT INTO `bugs` (`zone`, `name`, `ui`, `x`, `y`, `z`, `type`, `flag`, `target`, `bug`, `date`) "
"VALUES('%s', '%s', '%s', '%.2f', '%.2f', '%.2f', '%s', %d, '%s', '%s', CURDATE())",
zone->GetShortName(), bug->name, uitext == nullptr ? "": uitext,
bug->x, bug->y, bug->z, bug->chartype, bug->type, targettext == nullptr? "Unknown Target": targettext,
bugtext==nullptr?"":bugtext);
safe_delete_array(bugtext);
safe_delete_array(uitext);
safe_delete_array(targettext);
zone->GetShortName(),
(name_ ? name_ : ""),
(ui_ ? ui_ : ""),
bug_report->pos_x,
bug_report->pos_y,
bug_report->pos_z,
(type_ ? type_ : ""),
bug_report->optional_info_mask,
(target_ ? target_ : "Unknown Target"),
(bug_ ? bug_ : "")
);
safe_delete_array(name_);
safe_delete_array(ui_);
safe_delete_array(type_);
safe_delete_array(target_);
safe_delete_array(bug_);
QueryDatabase(query);
}
void ZoneDatabase::UpdateBug(PetitionBug_Struct* bug){
void ZoneDatabase::RegisterBug(Client* client, BugReport_Struct* bug_report) {
if (!client || !bug_report)
return;
uint32 len = strlen(bug->text);
auto bugtext = new char[2 * len + 1];
memset(bugtext, 0, 2*len+1);
DoEscapeString(bugtext, bug->text, len);
size_t len = 0;
char* category_name_ = nullptr;
char* reporter_name_ = nullptr;
char* ui_path_ = nullptr;
char* target_name_ = nullptr;
char* bug_report_ = nullptr;
char* system_info_ = nullptr;
std::string query = StringFormat("INSERT INTO bugs (type, name, bugtext, flag) "
"VALUES('%s', '%s', '%s', %i)",
"Petition", bug->name, bugtext, 25);
safe_delete_array(bugtext);
QueryDatabase(query);
len = strlen(bug_report->category_name);
if (len) {
if (len > 63) // check against db column size
len = 63;
category_name_ = new char[(2 * len + 1)];
memset(category_name_, 0, (2 * len + 1));
DoEscapeString(category_name_, bug_report->category_name, len);
}
len = strlen(bug_report->reporter_name);
if (len) {
if (len > 63)
len = 63;
reporter_name_ = new char[(2 * len + 1)];
memset(reporter_name_, 0, (2 * len + 1));
DoEscapeString(reporter_name_, bug_report->reporter_name, len);
}
len = strlen(bug_report->ui_path);
if (len) {
if (len > 127)
len = 127;
ui_path_ = new char[(2 * len + 1)];
memset(ui_path_, 0, (2 * len + 1));
DoEscapeString(ui_path_, bug_report->ui_path, len);
}
len = strlen(bug_report->target_name);
if (len) {
if (len > 63)
len = 63;
target_name_ = new char[(2 * len + 1)];
memset(target_name_, 0, (2 * len + 1));
DoEscapeString(target_name_, bug_report->target_name, len);
}
len = strlen(bug_report->bug_report);
if (len) {
if (len > 1023)
len = 1023;
bug_report_ = new char[(2 * len + 1)];
memset(bug_report_, 0, (2 * len + 1));
DoEscapeString(bug_report_, bug_report->bug_report, len);
}
len = strlen(bug_report->system_info);
if (len) {
if (len > 1023)
len = 1023;
system_info_ = new char[(2 * len + 1)];
memset(system_info_, 0, (2 * len + 1));
DoEscapeString(system_info_, bug_report->system_info, len);
}
std::string query = StringFormat(
"INSERT INTO `bug_reports` "
"(`zone`,"
" `client_version_id`,"
" `client_version_name`,"
" `account_id`,"
" `character_id`,"
" `character_name`,"
" `reporter_spoof`,"
" `category_id`,"
" `category_name`,"
" `reporter_name`,"
" `ui_path`,"
" `pos_x`,"
" `pos_y`,"
" `pos_z`,"
" `heading`,"
" `time_played`,"
" `target_id`,"
" `target_name`,"
" `optional_info_mask`,"
" `_can_duplicate`,"
" `_crash_bug`,"
" `_target_info`,"
" `_character_flags`,"
" `_unknown_value`,"
" `bug_report`,"
" `system_info`) "
"VALUES "
"('%s',"
" '%u',"
" '%s',"
" '%u',"
" '%u',"
" '%s',"
" '%u',"
" '%u',"
" '%s',"
" '%s',"
" '%s',"
" '%1.1f',"
" '%1.1f',"
" '%1.1f',"
" '%u',"
" '%u',"
" '%u',"
" '%s',"
" '%u',"
" '%u',"
" '%u',"
" '%u',"
" '%u',"
" '%u',"
" '%s',"
" '%s')",
zone->GetShortName(),
client->ClientVersion(),
EQEmu::versions::ClientVersionName(client->ClientVersion()),
client->AccountID(),
client->CharacterID(),
client->GetName(),
(strcmp(client->GetName(), reporter_name_) != 0 ? 1 : 0),
bug_report->category_id,
(category_name_ ? category_name_ : ""),
(reporter_name_ ? reporter_name_ : ""),
(ui_path_ ? ui_path_ : ""),
bug_report->pos_x,
bug_report->pos_y,
bug_report->pos_z,
bug_report->heading,
bug_report->time_played,
bug_report->target_id,
(target_name_ ? target_name_ : ""),
bug_report->optional_info_mask,
((bug_report->optional_info_mask & EQEmu::bug::infoCanDuplicate) != 0 ? 1 : 0),
((bug_report->optional_info_mask & EQEmu::bug::infoCrashBug) != 0 ? 1 : 0),
((bug_report->optional_info_mask & EQEmu::bug::infoTargetInfo) != 0 ? 1 : 0),
((bug_report->optional_info_mask & EQEmu::bug::infoCharacterFlags) != 0 ? 1 : 0),
((bug_report->optional_info_mask & EQEmu::bug::infoUnknownValue) != 0 ? 1 : 0),
(bug_report_ ? bug_report_ : ""),
(system_info_ ? system_info_ : "")
);
safe_delete_array(category_name_);
safe_delete_array(reporter_name_);
safe_delete_array(ui_path_);
safe_delete_array(target_name_);
safe_delete_array(bug_report_);
safe_delete_array(system_info_);
auto result = QueryDatabase(query);
// TODO: Entity dumping [RuleB(Bugs, DumpTargetEntity)]
}
//void ZoneDatabase::UpdateBug(PetitionBug_Struct* bug) {
//
// uint32 len = strlen(bug->text);
// auto bugtext = new char[2 * len + 1];
// memset(bugtext, 0, 2 * len + 1);
// DoEscapeString(bugtext, bug->text, len);
//
// std::string query = StringFormat("INSERT INTO bugs (type, name, bugtext, flag) "
// "VALUES('%s', '%s', '%s', %i)",
// "Petition", bug->name, bugtext, 25);
// safe_delete_array(bugtext);
// QueryDatabase(query);
//}
bool ZoneDatabase::SetSpecialAttkFlag(uint8 id, const char* flag) {
std::string query = StringFormat("UPDATE npc_types SET npcspecialattks='%s' WHERE id = %i;", flag, id);

View File

@ -442,8 +442,9 @@ public:
bool DeleteMerc(uint32 merc_id);
/* Petitions */
void UpdateBug(BugStruct* bug);
void UpdateBug(PetitionBug_Struct* bug);
void RegisterBug(BugReport_Struct* bug_report); // old method
void RegisterBug(Client* client, BugReport_Struct* bug_report); // new method
//void UpdateBug(PetitionBug_Struct* bug);
void DeletePetitionFromDB(Petition* wpet);
void UpdatePetitionToDB(Petition* wpet);
void InsertPetitionToDB(Petition* wpet);