mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-19 08:11:30 +00:00
Make guild consent persistent for summoned corpses
Live drops group/raid consent but not guild when moving corpse to another zone Store guild consent id in db for character corpses and keep it updated
This commit is contained in:
parent
63b8df72b2
commit
371265d143
@ -401,6 +401,7 @@
|
|||||||
9145|2019_12_24_banned_ips_update.sql|SHOW TABLES LIKE 'Banned_IPs'|not_empty|
|
9145|2019_12_24_banned_ips_update.sql|SHOW TABLES LIKE 'Banned_IPs'|not_empty|
|
||||||
9146|2020_01_10_character_soft_deletes.sql|SHOW COLUMNS FROM `character_data` LIKE 'deleted_at'|empty|
|
9146|2020_01_10_character_soft_deletes.sql|SHOW COLUMNS FROM `character_data` LIKE 'deleted_at'|empty|
|
||||||
9147|2020_01_24_grid_centerpoint_wp.sql|SHOW COLUMNS FROM `grid_entries` LIKE 'centerpoint'|empty|
|
9147|2020_01_24_grid_centerpoint_wp.sql|SHOW COLUMNS FROM `grid_entries` LIKE 'centerpoint'|empty|
|
||||||
|
9148|2020_01_28_corpse_guild_consent_id.sql|SHOW COLUMNS FROM `character_corpses` LIKE 'guild_consent_id'|empty|
|
||||||
|
|
||||||
# Upgrade conditions:
|
# Upgrade conditions:
|
||||||
# This won't be needed after this system is implemented, but it is used database that are not
|
# This won't be needed after this system is implemented, but it is used database that are not
|
||||||
|
|||||||
@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE `character_corpses` ADD COLUMN `guild_consent_id` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `time_of_death`;
|
||||||
@ -6294,6 +6294,8 @@ void Client::ConsentCorpses(const char* consent_name, bool deny)
|
|||||||
scs->consent_id = GuildID();
|
scs->consent_id = GuildID();
|
||||||
}
|
}
|
||||||
scs->consent_type = EQEmu::consent::Guild;
|
scs->consent_type = EQEmu::consent::Guild;
|
||||||
|
// update all corpses in db so buried/unloaded corpses see new consent id
|
||||||
|
database.UpdateCharacterCorpseConsent(CharacterID(), scs->consent_id);
|
||||||
}
|
}
|
||||||
worldserver.SendPacket(pack);
|
worldserver.SendPacket(pack);
|
||||||
safe_delete(pack);
|
safe_delete(pack);
|
||||||
|
|||||||
@ -73,7 +73,7 @@ void Corpse::SendLootReqErrorPacket(Client* client, LootResponse response) {
|
|||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
}
|
}
|
||||||
|
|
||||||
Corpse* Corpse::LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std::string in_charname, const glm::vec4& position, std::string time_of_death, bool rezzed, bool was_at_graveyard) {
|
Corpse* Corpse::LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std::string in_charname, const glm::vec4& position, std::string time_of_death, bool rezzed, bool was_at_graveyard, uint32 guild_consent_id) {
|
||||||
uint32 item_count = database.GetCharacterCorpseItemCount(in_dbid);
|
uint32 item_count = database.GetCharacterCorpseItemCount(in_dbid);
|
||||||
auto buffer =
|
auto buffer =
|
||||||
new char[sizeof(PlayerCorpse_Struct) + (item_count * sizeof(player_lootitem::ServerLootItem_Struct))];
|
new char[sizeof(PlayerCorpse_Struct) + (item_count * sizeof(player_lootitem::ServerLootItem_Struct))];
|
||||||
@ -138,6 +138,7 @@ Corpse* Corpse::LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std:
|
|||||||
pc->drakkin_details = pcs->drakkin_details;
|
pc->drakkin_details = pcs->drakkin_details;
|
||||||
pc->IsRezzed(rezzed);
|
pc->IsRezzed(rezzed);
|
||||||
pc->become_npc = false;
|
pc->become_npc = false;
|
||||||
|
pc->consent_guild_id = guild_consent_id;
|
||||||
|
|
||||||
pc->UpdateEquipmentLight(); // itemlist populated above..need to determine actual values
|
pc->UpdateEquipmentLight(); // itemlist populated above..need to determine actual values
|
||||||
|
|
||||||
@ -617,11 +618,11 @@ bool Corpse::Save() {
|
|||||||
|
|
||||||
/* Create New Corpse*/
|
/* Create New Corpse*/
|
||||||
if (corpse_db_id == 0) {
|
if (corpse_db_id == 0) {
|
||||||
corpse_db_id = database.SaveCharacterCorpse(char_id, corpse_name, zone->GetZoneID(), zone->GetInstanceID(), dbpc, m_Position);
|
corpse_db_id = database.SaveCharacterCorpse(char_id, corpse_name, zone->GetZoneID(), zone->GetInstanceID(), dbpc, m_Position, consent_guild_id);
|
||||||
}
|
}
|
||||||
/* Update Corpse Data */
|
/* Update Corpse Data */
|
||||||
else{
|
else{
|
||||||
corpse_db_id = database.UpdateCharacterCorpse(corpse_db_id, char_id, corpse_name, zone->GetZoneID(), zone->GetInstanceID(), dbpc, m_Position, IsRezzed());
|
corpse_db_id = database.UpdateCharacterCorpse(corpse_db_id, char_id, corpse_name, zone->GetZoneID(), zone->GetInstanceID(), dbpc, m_Position, consent_guild_id, IsRezzed());
|
||||||
}
|
}
|
||||||
|
|
||||||
safe_delete_array(dbpc);
|
safe_delete_array(dbpc);
|
||||||
|
|||||||
@ -48,7 +48,7 @@ class Corpse : public Mob {
|
|||||||
Corpse(uint32 in_corpseid, uint32 in_charid, const char* in_charname, ItemList* in_itemlist, uint32 in_copper, uint32 in_silver, uint32 in_gold, uint32 in_plat, const glm::vec4& position, float in_size, uint8 in_gender, uint16 in_race, uint8 in_class, uint8 in_deity, uint8 in_level, uint8 in_texture, uint8 in_helmtexture, uint32 in_rezexp, bool wasAtGraveyard = false);
|
Corpse(uint32 in_corpseid, uint32 in_charid, const char* in_charname, ItemList* in_itemlist, uint32 in_copper, uint32 in_silver, uint32 in_gold, uint32 in_plat, const glm::vec4& position, float in_size, uint8 in_gender, uint16 in_race, uint8 in_class, uint8 in_deity, uint8 in_level, uint8 in_texture, uint8 in_helmtexture, uint32 in_rezexp, bool wasAtGraveyard = false);
|
||||||
|
|
||||||
~Corpse();
|
~Corpse();
|
||||||
static Corpse* LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std::string in_charname, const glm::vec4& position, std::string time_of_death, bool rezzed, bool was_at_graveyard);
|
static Corpse* LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std::string in_charname, const glm::vec4& position, std::string time_of_death, bool rezzed, bool was_at_graveyard, uint32 guild_consent_id);
|
||||||
|
|
||||||
/* Corpse: General */
|
/* Corpse: General */
|
||||||
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill) { return true; }
|
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill) { return true; }
|
||||||
|
|||||||
@ -4288,10 +4288,10 @@ uint32 ZoneDatabase::GetCharacterCorpseDecayTimer(uint32 corpse_db_id){
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 ZoneDatabase::UpdateCharacterCorpse(uint32 db_id, uint32 char_id, const char* char_name, uint32 zone_id, uint16 instance_id, PlayerCorpse_Struct* dbpc, const glm::vec4& position, bool is_rezzed) {
|
uint32 ZoneDatabase::UpdateCharacterCorpse(uint32 db_id, uint32 char_id, const char* char_name, uint32 zone_id, uint16 instance_id, PlayerCorpse_Struct* dbpc, const glm::vec4& position, uint32 guild_id, bool is_rezzed) {
|
||||||
std::string query = StringFormat("UPDATE `character_corpses` "
|
std::string query = StringFormat("UPDATE `character_corpses` "
|
||||||
"SET `charname` = '%s', `zone_id` = %u, `instance_id` = %u, `charid` = %d, "
|
"SET `charname` = '%s', `zone_id` = %u, `instance_id` = %u, `charid` = %d, "
|
||||||
"`x` = %1.1f,`y` = %1.1f,`z` = %1.1f, `heading` = %1.1f, "
|
"`x` = %1.1f,`y` = %1.1f,`z` = %1.1f, `heading` = %1.1f, `guild_consent_id` = %u, "
|
||||||
"`is_locked` = %d, `exp` = %u, `size` = %f, `level` = %u, "
|
"`is_locked` = %d, `exp` = %u, `size` = %f, `level` = %u, "
|
||||||
"`race` = %u, `gender` = %u, `class` = %u, `deity` = %u, "
|
"`race` = %u, `gender` = %u, `class` = %u, `deity` = %u, "
|
||||||
"`texture` = %u, `helm_texture` = %u, `copper` = %u, "
|
"`texture` = %u, `helm_texture` = %u, `copper` = %u, "
|
||||||
@ -4303,7 +4303,7 @@ uint32 ZoneDatabase::UpdateCharacterCorpse(uint32 db_id, uint32 char_id, const c
|
|||||||
"`wc_7` = %u, `wc_8` = %u, `wc_9` = %u "
|
"`wc_7` = %u, `wc_8` = %u, `wc_9` = %u "
|
||||||
"WHERE `id` = %u",
|
"WHERE `id` = %u",
|
||||||
EscapeString(char_name).c_str(), zone_id, instance_id, char_id,
|
EscapeString(char_name).c_str(), zone_id, instance_id, char_id,
|
||||||
position.x, position.y, position.z, position.w,
|
position.x, position.y, position.z, position.w, guild_id,
|
||||||
dbpc->locked, dbpc->exp, dbpc->size, dbpc->level, dbpc->race,
|
dbpc->locked, dbpc->exp, dbpc->size, dbpc->level, dbpc->race,
|
||||||
dbpc->gender, dbpc->class_, dbpc->deity, dbpc->texture,
|
dbpc->gender, dbpc->class_, dbpc->deity, dbpc->texture,
|
||||||
dbpc->helmtexture, dbpc->copper, dbpc->silver, dbpc->gold,
|
dbpc->helmtexture, dbpc->copper, dbpc->silver, dbpc->gold,
|
||||||
@ -4319,12 +4319,19 @@ uint32 ZoneDatabase::UpdateCharacterCorpse(uint32 db_id, uint32 char_id, const c
|
|||||||
return db_id;
|
return db_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32 ZoneDatabase::UpdateCharacterCorpseConsent(uint32 charid, uint32 guildid)
|
||||||
|
{
|
||||||
|
std::string query = StringFormat("UPDATE `character_corpses` SET `guild_consent_id` = %u WHERE `charid` = %u", guildid, charid);
|
||||||
|
auto results = QueryDatabase(query);
|
||||||
|
return results.RowsAffected();
|
||||||
|
}
|
||||||
|
|
||||||
void ZoneDatabase::MarkCorpseAsRezzed(uint32 db_id) {
|
void ZoneDatabase::MarkCorpseAsRezzed(uint32 db_id) {
|
||||||
std::string query = StringFormat("UPDATE `character_corpses` SET `is_rezzed` = 1 WHERE `id` = %i", db_id);
|
std::string query = StringFormat("UPDATE `character_corpses` SET `is_rezzed` = 1 WHERE `id` = %i", db_id);
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 ZoneDatabase::SaveCharacterCorpse(uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, PlayerCorpse_Struct* dbpc, const glm::vec4& position) {
|
uint32 ZoneDatabase::SaveCharacterCorpse(uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, PlayerCorpse_Struct* dbpc, const glm::vec4& position, uint32 guildid) {
|
||||||
/* Dump Basic Corpse Data */
|
/* Dump Basic Corpse Data */
|
||||||
std::string query = StringFormat(
|
std::string query = StringFormat(
|
||||||
"INSERT INTO `character_corpses` "
|
"INSERT INTO `character_corpses` "
|
||||||
@ -4336,6 +4343,7 @@ uint32 ZoneDatabase::SaveCharacterCorpse(uint32 charid, const char* charname, ui
|
|||||||
"`y` = %1.1f, "
|
"`y` = %1.1f, "
|
||||||
"`z` = %1.1f, "
|
"`z` = %1.1f, "
|
||||||
"`heading` = %1.1f, "
|
"`heading` = %1.1f, "
|
||||||
|
"`guild_consent_id` = %u, "
|
||||||
"`time_of_death` = NOW(), "
|
"`time_of_death` = NOW(), "
|
||||||
"`is_buried` = 0, "
|
"`is_buried` = 0, "
|
||||||
"`is_locked` = %d, "
|
"`is_locked` = %d, "
|
||||||
@ -4379,6 +4387,7 @@ uint32 ZoneDatabase::SaveCharacterCorpse(uint32 charid, const char* charname, ui
|
|||||||
position.y,
|
position.y,
|
||||||
position.z,
|
position.z,
|
||||||
position.w,
|
position.w,
|
||||||
|
guildid,
|
||||||
dbpc->locked,
|
dbpc->locked,
|
||||||
dbpc->exp,
|
dbpc->exp,
|
||||||
dbpc->size,
|
dbpc->size,
|
||||||
@ -4637,7 +4646,7 @@ bool ZoneDatabase::LoadCharacterCorpseData(uint32 corpse_id, PlayerCorpse_Struct
|
|||||||
|
|
||||||
Corpse* ZoneDatabase::SummonBuriedCharacterCorpses(uint32 char_id, uint32 dest_zone_id, uint16 dest_instance_id, const glm::vec4& position) {
|
Corpse* ZoneDatabase::SummonBuriedCharacterCorpses(uint32 char_id, uint32 dest_zone_id, uint16 dest_instance_id, const glm::vec4& position) {
|
||||||
Corpse* corpse = nullptr;
|
Corpse* corpse = nullptr;
|
||||||
std::string query = StringFormat("SELECT `id`, `charname`, `time_of_death`, `is_rezzed` "
|
std::string query = StringFormat("SELECT `id`, `charname`, `time_of_death`, `is_rezzed`, `guild_consent_id` "
|
||||||
"FROM `character_corpses` "
|
"FROM `character_corpses` "
|
||||||
"WHERE `charid` = '%u' AND `is_buried` = 1 "
|
"WHERE `charid` = '%u' AND `is_buried` = 1 "
|
||||||
"ORDER BY `time_of_death` LIMIT 1",
|
"ORDER BY `time_of_death` LIMIT 1",
|
||||||
@ -4652,7 +4661,8 @@ Corpse* ZoneDatabase::SummonBuriedCharacterCorpses(uint32 char_id, uint32 dest_z
|
|||||||
position,
|
position,
|
||||||
row[2], // char* time_of_death
|
row[2], // char* time_of_death
|
||||||
atoi(row[3]) == 1, // bool rezzed
|
atoi(row[3]) == 1, // bool rezzed
|
||||||
false // bool was_at_graveyard
|
false, // bool was_at_graveyard
|
||||||
|
atoul(row[4]) // uint32 guild_consent_id
|
||||||
);
|
);
|
||||||
if (!corpse)
|
if (!corpse)
|
||||||
continue;
|
continue;
|
||||||
@ -4678,7 +4688,7 @@ bool ZoneDatabase::SummonAllCharacterCorpses(uint32 char_id, uint32 dest_zone_id
|
|||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
|
|
||||||
query = StringFormat(
|
query = StringFormat(
|
||||||
"SELECT `id`, `charname`, `time_of_death`, `is_rezzed` FROM `character_corpses` WHERE `charid` = '%u'"
|
"SELECT `id`, `charname`, `time_of_death`, `is_rezzed`, `guild_consent_id` FROM `character_corpses` WHERE `charid` = '%u'"
|
||||||
"ORDER BY time_of_death",
|
"ORDER BY time_of_death",
|
||||||
char_id);
|
char_id);
|
||||||
results = QueryDatabase(query);
|
results = QueryDatabase(query);
|
||||||
@ -4691,7 +4701,8 @@ bool ZoneDatabase::SummonAllCharacterCorpses(uint32 char_id, uint32 dest_zone_id
|
|||||||
position,
|
position,
|
||||||
row[2],
|
row[2],
|
||||||
atoi(row[3]) == 1,
|
atoi(row[3]) == 1,
|
||||||
false);
|
false,
|
||||||
|
atoul(row[4]));
|
||||||
|
|
||||||
if (corpse) {
|
if (corpse) {
|
||||||
entity_list.AddCorpse(corpse);
|
entity_list.AddCorpse(corpse);
|
||||||
@ -4766,7 +4777,7 @@ bool ZoneDatabase::UnburyCharacterCorpse(uint32 db_id, uint32 new_zone_id, uint1
|
|||||||
Corpse* ZoneDatabase::LoadCharacterCorpse(uint32 player_corpse_id) {
|
Corpse* ZoneDatabase::LoadCharacterCorpse(uint32 player_corpse_id) {
|
||||||
Corpse* NewCorpse = 0;
|
Corpse* NewCorpse = 0;
|
||||||
std::string query = StringFormat(
|
std::string query = StringFormat(
|
||||||
"SELECT `id`, `charid`, `charname`, `x`, `y`, `z`, `heading`, `time_of_death`, `is_rezzed`, `was_at_graveyard` FROM `character_corpses` WHERE `id` = '%u' LIMIT 1",
|
"SELECT `id`, `charid`, `charname`, `x`, `y`, `z`, `heading`, `time_of_death`, `is_rezzed`, `was_at_graveyard`, `guild_consent_id` FROM `character_corpses` WHERE `id` = '%u' LIMIT 1",
|
||||||
player_corpse_id
|
player_corpse_id
|
||||||
);
|
);
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
@ -4779,7 +4790,8 @@ Corpse* ZoneDatabase::LoadCharacterCorpse(uint32 player_corpse_id) {
|
|||||||
position,
|
position,
|
||||||
row[7], // time_of_death char* time_of_death
|
row[7], // time_of_death char* time_of_death
|
||||||
atoi(row[8]) == 1, // is_rezzed bool rezzed
|
atoi(row[8]) == 1, // is_rezzed bool rezzed
|
||||||
atoi(row[9]) // was_at_graveyard bool was_at_graveyard
|
atoi(row[9]), // was_at_graveyard bool was_at_graveyard
|
||||||
|
atoul(row[10]) // guild_consent_id uint32 guild_consent_id
|
||||||
);
|
);
|
||||||
entity_list.AddCorpse(NewCorpse);
|
entity_list.AddCorpse(NewCorpse);
|
||||||
}
|
}
|
||||||
@ -4789,10 +4801,10 @@ Corpse* ZoneDatabase::LoadCharacterCorpse(uint32 player_corpse_id) {
|
|||||||
bool ZoneDatabase::LoadCharacterCorpses(uint32 zone_id, uint16 instance_id) {
|
bool ZoneDatabase::LoadCharacterCorpses(uint32 zone_id, uint16 instance_id) {
|
||||||
std::string query;
|
std::string query;
|
||||||
if (!RuleB(Zone, EnableShadowrest)){
|
if (!RuleB(Zone, EnableShadowrest)){
|
||||||
query = StringFormat("SELECT id, charid, charname, x, y, z, heading, time_of_death, is_rezzed, was_at_graveyard FROM character_corpses WHERE zone_id='%u' AND instance_id='%u'", zone_id, instance_id);
|
query = StringFormat("SELECT id, charid, charname, x, y, z, heading, time_of_death, is_rezzed, was_at_graveyard, guild_consent_id FROM character_corpses WHERE zone_id='%u' AND instance_id='%u'", zone_id, instance_id);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
query = StringFormat("SELECT id, charid, charname, x, y, z, heading, time_of_death, is_rezzed, 0 as was_at_graveyard FROM character_corpses WHERE zone_id='%u' AND instance_id='%u' AND is_buried=0", zone_id, instance_id);
|
query = StringFormat("SELECT id, charid, charname, x, y, z, heading, time_of_death, is_rezzed, 0 as was_at_graveyard, guild_consent_id FROM character_corpses WHERE zone_id='%u' AND instance_id='%u' AND is_buried=0", zone_id, instance_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
@ -4806,7 +4818,8 @@ bool ZoneDatabase::LoadCharacterCorpses(uint32 zone_id, uint16 instance_id) {
|
|||||||
position,
|
position,
|
||||||
row[7], // time_of_death char* time_of_death
|
row[7], // time_of_death char* time_of_death
|
||||||
atoi(row[8]) == 1, // is_rezzed bool rezzed
|
atoi(row[8]) == 1, // is_rezzed bool rezzed
|
||||||
atoi(row[9]))
|
atoi(row[9]),
|
||||||
|
atoul(row[10])) // guild_consent_id uint32 guild_consent_id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -367,8 +367,9 @@ public:
|
|||||||
uint32 SendCharacterCorpseToGraveyard(uint32 dbid, uint32 zoneid, uint16 instanceid, const glm::vec4& position);
|
uint32 SendCharacterCorpseToGraveyard(uint32 dbid, uint32 zoneid, uint16 instanceid, const glm::vec4& position);
|
||||||
uint32 CreateGraveyardRecord(uint32 graveyard_zoneid, const glm::vec4& position);
|
uint32 CreateGraveyardRecord(uint32 graveyard_zoneid, const glm::vec4& position);
|
||||||
uint32 AddGraveyardIDToZone(uint32 zone_id, uint32 graveyard_id);
|
uint32 AddGraveyardIDToZone(uint32 zone_id, uint32 graveyard_id);
|
||||||
uint32 SaveCharacterCorpse(uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, PlayerCorpse_Struct* dbpc, const glm::vec4& position);
|
uint32 SaveCharacterCorpse(uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, PlayerCorpse_Struct* dbpc, const glm::vec4& position, uint32 guildid);
|
||||||
uint32 UpdateCharacterCorpse(uint32 dbid, uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, PlayerCorpse_Struct* dbpc, const glm::vec4& position, bool rezzed = false);
|
uint32 UpdateCharacterCorpse(uint32 dbid, uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, PlayerCorpse_Struct* dbpc, const glm::vec4& position, uint32 guildid, bool rezzed = false);
|
||||||
|
uint32 UpdateCharacterCorpseConsent(uint32 charid, uint32 guildid);
|
||||||
uint32 GetFirstCorpseID(uint32 char_id);
|
uint32 GetFirstCorpseID(uint32 char_id);
|
||||||
uint32 GetCharacterCorpseCount(uint32 char_id);
|
uint32 GetCharacterCorpseCount(uint32 char_id);
|
||||||
uint32 GetCharacterCorpseID(uint32 char_id, uint8 corpse);
|
uint32 GetCharacterCorpseID(uint32 char_id, uint8 corpse);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user