Core/BattlePets: Implemented BattlePetSpeciesFlags::NotAccountWide

Port From (https://github.com/TrinityCore/TrinityCore/commit/93c668ac50a529876054212dfef6544f70259035)
This commit is contained in:
hondacrx
2021-11-29 17:09:03 -05:00
parent 7b5524222b
commit 56f1c3d984
7 changed files with 99 additions and 17 deletions
@@ -151,9 +151,10 @@ namespace Framework.Database
PrepareStatement(LoginStatements.REP_ACCOUNT_TOYS, "REPLACE INTO battlenet_account_toys (accountId, itemId, isFavourite, hasFanfare) VALUES (?, ?, ?, ?)"); PrepareStatement(LoginStatements.REP_ACCOUNT_TOYS, "REPLACE INTO battlenet_account_toys (accountId, itemId, isFavourite, hasFanfare) VALUES (?, ?, ?, ?)");
// Battle Pets // Battle Pets
PrepareStatement(LoginStatements.SEL_BATTLE_PETS, "SELECT bp.guid, bp.species, bp.breed, bp.displayId, bp.level, bp.exp, bp.health, bp.quality, bp.flags, bp.name, bp.nameTimestamp, dn.genitive, dn.dative, dn.accusative, dn.instrumental, dn.prepositional FROM battle_pets bp LEFT JOIN battle_pet_declinedname dn ON bp.guid = dn.guid WHERE bp.battlenetAccountId = ?"); PrepareStatement(LoginStatements.SEL_BATTLE_PETS, "SELECT bp.guid, bp.species, bp.breed, bp.displayId, bp.level, bp.exp, bp.health, bp.quality, bp.flags, bp.name, bp.nameTimestamp, bp.owner, dn.genitive, dn.dative, dn.accusative, dn.instrumental, dn.prepositional FROM battle_pets bp LEFT JOIN battle_pet_declinedname dn ON bp.guid = dn.guid WHERE bp.battlenetAccountId = ? AND (bp.ownerRealmId IS NULL OR bp.ownerRealmId = ?)");
PrepareStatement(LoginStatements.INS_BATTLE_PETS, "INSERT INTO battle_pets (guid, battlenetAccountId, species, breed, displayId, level, exp, health, quality, flags, name, nameTimestamp) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); PrepareStatement(LoginStatements.INS_BATTLE_PETS, "INSERT INTO battle_pets (guid, battlenetAccountId, species, breed, displayId, level, exp, health, quality, flags, name, nameTimestamp, owner, ownerRealmId) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
PrepareStatement(LoginStatements.DEL_BATTLE_PETS, "DELETE FROM battle_pets WHERE battlenetAccountId = ? AND guid = ?"); PrepareStatement(LoginStatements.DEL_BATTLE_PETS, "DELETE FROM battle_pets WHERE battlenetAccountId = ? AND guid = ?");
PrepareStatement(LoginStatements.DEL_BATTLE_PETS_BY_OWNER, "DELETE FROM battle_pets WHERE owner = ? AND ownerRealmId = ?");
PrepareStatement(LoginStatements.UPD_BATTLE_PETS, "UPDATE battle_pets SET level = ?, exp = ?, health = ?, quality = ?, flags = ?, name = ?, nameTimestamp = ? WHERE battlenetAccountId = ? AND guid = ?"); PrepareStatement(LoginStatements.UPD_BATTLE_PETS, "UPDATE battle_pets SET level = ?, exp = ?, health = ?, quality = ?, flags = ?, name = ?, nameTimestamp = ? WHERE battlenetAccountId = ? AND guid = ?");
PrepareStatement(LoginStatements.SEL_BATTLE_PET_SLOTS, "SELECT id, battlePetGuid, locked FROM battle_pet_slots WHERE battlenetAccountId = ?"); PrepareStatement(LoginStatements.SEL_BATTLE_PET_SLOTS, "SELECT id, battlePetGuid, locked FROM battle_pet_slots WHERE battlenetAccountId = ?");
PrepareStatement(LoginStatements.INS_BATTLE_PET_SLOTS, "INSERT INTO battle_pet_slots (id, battlenetAccountId, battlePetGuid, locked) VALUES (?, ?, ?, ?)"); PrepareStatement(LoginStatements.INS_BATTLE_PET_SLOTS, "INSERT INTO battle_pet_slots (id, battlenetAccountId, battlePetGuid, locked) VALUES (?, ?, ?, ?)");
@@ -300,6 +301,7 @@ namespace Framework.Database
SEL_BATTLE_PETS, SEL_BATTLE_PETS,
INS_BATTLE_PETS, INS_BATTLE_PETS,
DEL_BATTLE_PETS, DEL_BATTLE_PETS,
DEL_BATTLE_PETS_BY_OWNER,
UPD_BATTLE_PETS, UPD_BATTLE_PETS,
SEL_BATTLE_PET_SLOTS, SEL_BATTLE_PET_SLOTS,
INS_BATTLE_PET_SLOTS, INS_BATTLE_PET_SLOTS,
+77 -12
View File
@@ -174,13 +174,35 @@ namespace Game.BattlePets
do do
{ {
uint species = petsResult.Read<uint>(1); uint species = petsResult.Read<uint>(1);
ObjectGuid ownerGuid = !petsResult.IsNull(11) ? ObjectGuid.Create(HighGuid.Player, petsResult.Read<ulong>(11)) : ObjectGuid.Empty;
BattlePetSpeciesRecord speciesEntry = CliDB.BattlePetSpeciesStorage.LookupByKey(species); BattlePetSpeciesRecord speciesEntry = CliDB.BattlePetSpeciesStorage.LookupByKey(species);
if (speciesEntry != null) if (speciesEntry != null)
{ {
if (HasMaxPetCount(speciesEntry)) if (speciesEntry.GetFlags().HasFlag(BattlePetSpeciesFlags.NotAccountWide))
{ {
Log.outError(LogFilter.Misc, "Battlenet account with id {0} has more than maximum battle pets of species {1}", _owner.GetBattlenetAccountId(), species); if (ownerGuid.IsEmpty())
{
Log.outError(LogFilter.Misc, $"Battlenet account with id {_owner.GetBattlenetAccountId()} has battle pet of species {species} with BattlePetSpeciesFlags::NotAccountWide but no owner");
continue;
}
}
else
{
if (!ownerGuid.IsEmpty())
{
Log.outError(LogFilter.Misc, $"Battlenet account with id {_owner.GetBattlenetAccountId()} has battle pet of species {species} without BattlePetSpeciesFlags::NotAccountWide but with owner");
continue;
}
}
if (HasMaxPetCount(speciesEntry, ownerGuid))
{
if (ownerGuid.IsEmpty())
Log.outError(LogFilter.Misc, $"Battlenet account with id {_owner.GetBattlenetAccountId()} has more than maximum battle pets of species {species}");
else
Log.outError(LogFilter.Misc, $"Battlenet account with id {_owner.GetBattlenetAccountId()} has more than maximum battle pets of species {species} for player {ownerGuid}");
continue; continue;
} }
@@ -198,11 +220,19 @@ namespace Game.BattlePets
pet.NameTimestamp = petsResult.Read<long>(10); pet.NameTimestamp = petsResult.Read<long>(10);
pet.PacketInfo.CreatureID = speciesEntry.CreatureID; pet.PacketInfo.CreatureID = speciesEntry.CreatureID;
if (!petsResult.IsNull(11)) if (!petsResult.IsNull(12))
{ {
pet.DeclinedName = new(); pet.DeclinedName = new();
for (byte i = 0; i < SharedConst.MaxDeclinedNameCases; ++i) for (byte i = 0; i < SharedConst.MaxDeclinedNameCases; ++i)
pet.DeclinedName.name[i] = petsResult.Read<string>(11 + i); pet.DeclinedName.name[i] = petsResult.Read<string>(12 + i);
}
if (!ownerGuid.IsEmpty())
{
pet.PacketInfo.OwnerInfo.HasValue = true;
pet.PacketInfo.OwnerInfo.Value.Guid = ownerGuid;
pet.PacketInfo.OwnerInfo.Value.PlayerVirtualRealm = Global.WorldMgr.GetVirtualRealmAddress();
pet.PacketInfo.OwnerInfo.Value.PlayerNativeRealm = Global.WorldMgr.GetVirtualRealmAddress();
} }
pet.SaveInfo = BattlePetSaveInfo.Unchanged; pet.SaveInfo = BattlePetSaveInfo.Unchanged;
@@ -250,6 +280,17 @@ namespace Game.BattlePets
stmt.AddValue(9, pair.Value.PacketInfo.Flags); stmt.AddValue(9, pair.Value.PacketInfo.Flags);
stmt.AddValue(10, pair.Value.PacketInfo.Name); stmt.AddValue(10, pair.Value.PacketInfo.Name);
stmt.AddValue(11, pair.Value.NameTimestamp); stmt.AddValue(11, pair.Value.NameTimestamp);
if (pair.Value.PacketInfo.OwnerInfo.HasValue)
{
stmt.AddValue(12, pair.Value.PacketInfo.OwnerInfo.Value.Guid.GetCounter());
stmt.AddValue(13, Global.WorldMgr.GetRealmId().Index);
}
else
{
stmt.AddNull(12);
stmt.AddNull(13);
}
trans.Append(stmt); trans.Append(stmt);
if (pair.Value.DeclinedName != null) if (pair.Value.DeclinedName != null)
@@ -352,7 +393,16 @@ namespace Game.BattlePets
pet.PacketInfo.Name = ""; pet.PacketInfo.Name = "";
pet.CalculateStats(); pet.CalculateStats();
pet.PacketInfo.Health = pet.PacketInfo.MaxHealth; pet.PacketInfo.Health = pet.PacketInfo.MaxHealth;
pet.NameTimestamp = 0;
Player player = _owner.GetPlayer();
if (battlePetSpecies.GetFlags().HasFlag(BattlePetSpeciesFlags.NotAccountWide))
{
pet.PacketInfo.OwnerInfo.HasValue = true;
pet.PacketInfo.OwnerInfo.Value.Guid = player.GetGUID();
pet.PacketInfo.OwnerInfo.Value.PlayerVirtualRealm = Global.WorldMgr.GetVirtualRealmAddress();
pet.PacketInfo.OwnerInfo.Value.PlayerNativeRealm = Global.WorldMgr.GetVirtualRealmAddress();
}
pet.SaveInfo = BattlePetSaveInfo.New; pet.SaveInfo = BattlePetSaveInfo.New;
_pets[pet.PacketInfo.Guid.GetCounter()] = pet; _pets[pet.PacketInfo.Guid.GetCounter()] = pet;
@@ -361,8 +411,8 @@ namespace Game.BattlePets
updates.Add(pet); updates.Add(pet);
SendUpdates(updates, true); SendUpdates(updates, true);
_owner.GetPlayer().UpdateCriteria(CriteriaType.UniquePetsOwned); player.UpdateCriteria(CriteriaType.UniquePetsOwned);
_owner.GetPlayer().UpdateCriteria(CriteriaType.LearnedNewPet, species); player.UpdateCriteria(CriteriaType.LearnedNewPet, species);
} }
public void RemovePet(ObjectGuid guid) public void RemovePet(ObjectGuid guid)
@@ -426,15 +476,29 @@ namespace Game.BattlePets
return false; return false;
} }
public byte GetPetCount(uint species) public byte GetPetCount(BattlePetSpeciesRecord battlePetSpecies, ObjectGuid ownerGuid)
{ {
return (byte)_pets.Values.Count(battlePet => battlePet.PacketInfo.Species == species && battlePet.SaveInfo != BattlePetSaveInfo.Removed); return (byte)_pets.Values.Count(battlePet =>
{
if (battlePet.PacketInfo.Species != battlePetSpecies.Id)
return false;
if (battlePet.SaveInfo == BattlePetSaveInfo.Removed)
return false;
if (battlePetSpecies.GetFlags().HasFlag(BattlePetSpeciesFlags.NotAccountWide))
if (!ownerGuid.IsEmpty() && battlePet.PacketInfo.OwnerInfo.HasValue)
if (battlePet.PacketInfo.OwnerInfo.Value.Guid != ownerGuid)
return false;
return true;
});
} }
public bool HasMaxPetCount(BattlePetSpeciesRecord speciesEntry) public bool HasMaxPetCount(BattlePetSpeciesRecord battlePetSpecies, ObjectGuid ownerGuid)
{ {
int maxPetsPerSpecies = speciesEntry.GetFlags().HasFlag(BattlePetSpeciesFlags.LegacyAccountUnique) ? 1 : SharedConst.DefaultMaxBattlePetsPerSpecies; int maxPetsPerSpecies = battlePetSpecies.GetFlags().HasFlag(BattlePetSpeciesFlags.LegacyAccountUnique) ? 1 : SharedConst.DefaultMaxBattlePetsPerSpecies;
return GetPetCount(speciesEntry.Id) >= maxPetsPerSpecies; return GetPetCount(battlePetSpecies, ownerGuid) >= maxPetsPerSpecies;
} }
public uint GetPetUniqueSpeciesCount() public uint GetPetUniqueSpeciesCount()
@@ -575,6 +639,7 @@ namespace Game.BattlePets
foreach (var pet in _pets) foreach (var pet in _pets)
if (pet.Value.SaveInfo != BattlePetSaveInfo.Removed) if (pet.Value.SaveInfo != BattlePetSaveInfo.Removed)
if (!pet.Value.PacketInfo.OwnerInfo.HasValue || pet.Value.PacketInfo.OwnerInfo.Value.Guid == _owner.GetPlayer().GetGUID())
battlePetJournal.Pets.Add(pet.Value.PacketInfo); battlePetJournal.Pets.Add(pet.Value.PacketInfo);
battlePetJournal.Slots = _slots; battlePetJournal.Slots = _slots;
+8
View File
@@ -3823,6 +3823,8 @@ namespace Game.Entities
} }
SQLTransaction trans = new(); SQLTransaction trans = new();
SQLTransaction loginTransaction = new();
ulong guildId = Global.CharacterCacheStorage.GetCharacterGuildIdByGuid(playerGuid); ulong guildId = Global.CharacterCacheStorage.GetCharacterGuildIdByGuid(playerGuid);
if (guildId != 0) if (guildId != 0)
{ {
@@ -4215,6 +4217,11 @@ namespace Game.Entities
stmt.AddValue(0, guid); stmt.AddValue(0, guid);
trans.Append(stmt); trans.Append(stmt);
stmt = DB.Login.GetPreparedStatement(LoginStatements.DEL_BATTLE_PETS_BY_OWNER);
stmt.AddValue(0, guid);
stmt.AddValue(0, Global.WorldMgr.GetRealmId().Index);
loginTransaction.Append(stmt);
Corpse.DeleteFromDB(playerGuid, trans); Corpse.DeleteFromDB(playerGuid, trans);
Garrison.DeleteFromDB(guid, trans); Garrison.DeleteFromDB(guid, trans);
@@ -4240,6 +4247,7 @@ namespace Game.Entities
return; return;
} }
DB.Login.CommitTransaction(loginTransaction);
DB.Characters.CommitTransaction(trans); DB.Characters.CommitTransaction(trans);
if (updateRealmChars) if (updateRealmChars)
+1
View File
@@ -1059,6 +1059,7 @@ namespace Game
stmt = DB.Login.GetPreparedStatement(LoginStatements.SEL_BATTLE_PETS); stmt = DB.Login.GetPreparedStatement(LoginStatements.SEL_BATTLE_PETS);
stmt.AddValue(0, battlenetAccountId); stmt.AddValue(0, battlenetAccountId);
stmt.AddValue(1, Global.WorldMgr.GetRealmId().Index);
SetQuery(AccountInfoQueryLoad.BattlePets, stmt); SetQuery(AccountInfoQueryLoad.BattlePets, stmt);
stmt = DB.Login.GetPreparedStatement(LoginStatements.SEL_BATTLE_PET_SLOTS); stmt = DB.Login.GetPreparedStatement(LoginStatements.SEL_BATTLE_PET_SLOTS);
+1 -1
View File
@@ -5445,7 +5445,7 @@ namespace Game.Spells
return; return;
} }
if (battlePetMgr.HasMaxPetCount(speciesEntry)) if (battlePetMgr.HasMaxPetCount(speciesEntry, player.GetGUID()))
{ {
battlePetMgr.SendError(BattlePetError.CantHaveMorePetsOfThatType, speciesEntry.CreatureID); battlePetMgr.SendError(BattlePetError.CantHaveMorePetsOfThatType, speciesEntry.CreatureID);
SendCastResult(SpellCastResult.CantAddBattlePet); SendCastResult(SpellCastResult.CantAddBattlePet);
+4 -1
View File
@@ -272,6 +272,8 @@ CREATE TABLE `battle_pets` (
`flags` smallint(5) NOT NULL DEFAULT '0', `flags` smallint(5) NOT NULL DEFAULT '0',
`name` varchar(12) NOT NULL, `name` varchar(12) NOT NULL,
`nameTimestamp` bigint(20) NOT NULL DEFAULT '0', `nameTimestamp` bigint(20) NOT NULL DEFAULT '0',
`owner` bigint(20) DEFAULT NULL,
`ownerRealmId` int(11) DEFAULT NULL,
PRIMARY KEY (`guid`) PRIMARY KEY (`guid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */; /*!40101 SET character_set_client = @saved_cs_client */;
@@ -2457,7 +2459,8 @@ INSERT INTO `updates` VALUES
('2021_11_12_00_auth.sql','012C088794362FE57BAEA0C3BD05356B40289028','ARCHIVED','2021-11-12 12:17:24',0), ('2021_11_12_00_auth.sql','012C088794362FE57BAEA0C3BD05356B40289028','ARCHIVED','2021-11-12 12:17:24',0),
('2021_11_17_00_auth.sql','298DA8468B30042B15FA17A90325C72879DF6D8E','ARCHIVED','2021-11-17 13:23:17',0), ('2021_11_17_00_auth.sql','298DA8468B30042B15FA17A90325C72879DF6D8E','ARCHIVED','2021-11-17 13:23:17',0),
('2021_11_19_00_auth.sql','BE4F77E254D76A59DBF28B2CEEA5CAF6777B650E','RELEASED','2021-11-19 00:37:56',0), ('2021_11_19_00_auth.sql','BE4F77E254D76A59DBF28B2CEEA5CAF6777B650E','RELEASED','2021-11-19 00:37:56',0),
('2021_11_20_00_auth.sql','E476B6DAD9C47FC81E1DA5016DC79AB527F1847A','RELEASED','2021-11-20 18:40:53',0); ('2021_11_20_00_auth.sql','E476B6DAD9C47FC81E1DA5016DC79AB527F1847A','RELEASED','2021-11-20 18:40:53',0),
('2021_11_25_00_auth.sql','7A01CEB201CB825BFD565BBF5EED0162BEA733E7','RELEASED','2021-11-25 19:32:21',0);
/*!40000 ALTER TABLE `updates` ENABLE KEYS */; /*!40000 ALTER TABLE `updates` ENABLE KEYS */;
UNLOCK TABLES; UNLOCK TABLES;
@@ -0,0 +1,3 @@
ALTER TABLE `battle_pets`
ADD `owner` bigint(20) DEFAULT NULL AFTER `nameTimestamp`,
ADD `ownerRealmId` int(11) DEFAULT NULL AFTER `owner`;