/// <summary> /// Returns a friendly string for the position of a biota /// </summary> private static string GetCoords(Biota biota) { var p = biota.BiotaPropertiesPosition.FirstOrDefault(i => i.PositionType == (ushort)PositionType.Location); return(GetCoords(new Position(p.ObjCellId, p.OriginX, p.OriginY, p.OriginZ, p.AnglesX, p.AnglesY, p.AnglesZ, p.AnglesW, 0))); }
public Hotspot(Biota biota) : base(biota) { SetEphemeralValues(); }
public override bool SaveBiota(Biota biota, ReaderWriterLockSlim rwLock) { if (BiotaContexts.TryGetValue(biota, out var cachedContext)) { rwLock.EnterReadLock(); try { SetBiotaPopulatedCollections(biota); Exception firstException = null; retry: try { cachedContext.SaveChanges(); if (firstException != null) { log.Debug($"[DATABASE] SaveBiota 0x{biota.Id:X8}:{biota.GetProperty(PropertyString.Name)} retry succeeded after initial exception of: {firstException.GetFullMessage()}"); } return(true); } catch (Exception ex) { if (firstException == null) { firstException = ex; goto retry; } // Character name might be in use or some other fault log.Error($"[DATABASE] SaveBiota 0x{biota.Id:X8}:{biota.GetProperty(PropertyString.Name)} failed first attempt with exception: {firstException}"); log.Error($"[DATABASE] SaveBiota 0x{biota.Id:X8}:{biota.GetProperty(PropertyString.Name)} failed second attempt with exception: {ex}"); return(false); } } finally { rwLock.ExitReadLock(); } } if (ObjectGuid.IsPlayer(biota.Id)) { var context = new ShardDbContext(); BiotaContexts.Add(biota, context); rwLock.EnterReadLock(); try { SetBiotaPopulatedCollections(biota); context.Biota.Add(biota); Exception firstException = null; retry: try { context.SaveChanges(); if (firstException != null) { log.Debug($"[DATABASE] SaveBiota 0x{biota.Id:X8}:{biota.GetProperty(PropertyString.Name)} retry succeeded after initial exception of: {firstException.GetFullMessage()}"); } return(true); } catch (Exception ex) { if (firstException == null) { firstException = ex; goto retry; } // Character name might be in use or some other fault log.Error($"[DATABASE] SaveBiota 0x{biota.Id:X8}:{biota.GetProperty(PropertyString.Name)} failed first attempt with exception: {firstException}"); log.Error($"[DATABASE] SaveBiota 0x{biota.Id:X8}:{biota.GetProperty(PropertyString.Name)} failed second attempt with exception: {ex}"); return(false); } } finally { rwLock.ExitReadLock(); } } using (var context = new ShardDbContext()) { var existingBiota = GetBiota(context, biota.Id); rwLock.EnterReadLock(); try { SetBiotaPopulatedCollections(biota); if (existingBiota == null) { context.Biota.Add(biota); } else { UpdateBiota(context, existingBiota, biota); } Exception firstException = null; retry: try { context.SaveChanges(); if (firstException != null) { log.Debug($"[DATABASE] SaveBiota 0x{biota.Id:X8}:{biota.GetProperty(PropertyString.Name)} retry succeeded after initial exception of: {firstException.GetFullMessage()}"); } return(true); } catch (Exception ex) { if (firstException == null) { firstException = ex; goto retry; } // Character name might be in use or some other fault log.Error($"[DATABASE] SaveBiota 0x{biota.Id:X8}:{biota.GetProperty(PropertyString.Name)} failed first attempt with exception: {firstException}"); log.Error($"[DATABASE] SaveBiota 0x{biota.Id:X8}:{biota.GetProperty(PropertyString.Name)} failed second attempt with exception: {ex}"); return(false); } } finally { rwLock.ExitReadLock(); } } }
/// <summary> /// Restore a WorldObject from the database. /// </summary> public Portal(Biota biota) : base(biota) { SetEphemeralValues(); }
private static void DoPlayerEnterWorld(Session session, Character character, Biota playerBiota, PossessedBiotas possessedBiotas) { Player player; Player.HandleNoLogLandblock(playerBiota, out var playerLoggedInOnNoLogLandblock); var stripAdminProperties = false; var addAdminProperties = false; var addSentinelProperties = false; if (ConfigManager.Config.Server.Accounts.OverrideCharacterPermissions) { if (session.AccessLevel <= AccessLevel.Advocate) // check for elevated characters { if (playerBiota.WeenieType == WeenieType.Admin || playerBiota.WeenieType == WeenieType.Sentinel) // Downgrade weenie { character.IsPlussed = false; playerBiota.WeenieType = WeenieType.Creature; stripAdminProperties = true; } } else if (session.AccessLevel >= AccessLevel.Sentinel && session.AccessLevel <= AccessLevel.Envoy) { if (playerBiota.WeenieType == WeenieType.Creature || playerBiota.WeenieType == WeenieType.Admin) // Up/downgrade weenie { character.IsPlussed = true; playerBiota.WeenieType = WeenieType.Sentinel; addSentinelProperties = true; } } else // Developers and Admins { if (playerBiota.WeenieType == WeenieType.Creature || playerBiota.WeenieType == WeenieType.Sentinel) // Up/downgrade weenie { character.IsPlussed = true; playerBiota.WeenieType = WeenieType.Admin; addAdminProperties = true; } } } if (playerBiota.WeenieType == WeenieType.Admin) { player = new Admin(playerBiota, possessedBiotas.Inventory, possessedBiotas.WieldedItems, character, session); } else if (playerBiota.WeenieType == WeenieType.Sentinel) { player = new Sentinel(playerBiota, possessedBiotas.Inventory, possessedBiotas.WieldedItems, character, session); } else { player = new Player(playerBiota, possessedBiotas.Inventory, possessedBiotas.WieldedItems, character, session); } session.SetPlayer(player); if (stripAdminProperties) // continue stripping properties { player.CloakStatus = CloakStatus.Undef; player.Attackable = true; player.SetProperty(ACE.Entity.Enum.Properties.PropertyBool.DamagedByCollisions, true); player.AdvocateLevel = null; player.ChannelsActive = null; player.ChannelsAllowed = null; player.Invincible = false; player.Cloaked = null; player.IgnoreHouseBarriers = false; player.IgnorePortalRestrictions = false; player.SafeSpellComponents = false; player.ReportCollisions = true; player.ChangesDetected = true; player.CharacterChangesDetected = true; } if (addSentinelProperties || addAdminProperties) // continue restoring properties to default { WorldObject weenie; if (addAdminProperties) { weenie = Factories.WorldObjectFactory.CreateWorldObject(DatabaseManager.World.GetCachedWeenie("admin"), new ACE.Entity.ObjectGuid(ACE.Entity.ObjectGuid.Invalid.Full)); } else { weenie = Factories.WorldObjectFactory.CreateWorldObject(DatabaseManager.World.GetCachedWeenie("sentinel"), new ACE.Entity.ObjectGuid(ACE.Entity.ObjectGuid.Invalid.Full)); } if (weenie != null) { player.CloakStatus = CloakStatus.Off; player.Attackable = weenie.Attackable; player.SetProperty(ACE.Entity.Enum.Properties.PropertyBool.DamagedByCollisions, false); player.AdvocateLevel = weenie.GetProperty(ACE.Entity.Enum.Properties.PropertyInt.AdvocateLevel); player.ChannelsActive = (Channel?)weenie.GetProperty(ACE.Entity.Enum.Properties.PropertyInt.ChannelsActive); player.ChannelsAllowed = (Channel?)weenie.GetProperty(ACE.Entity.Enum.Properties.PropertyInt.ChannelsAllowed); player.Invincible = false; player.Cloaked = false; player.ChangesDetected = true; player.CharacterChangesDetected = true; } } // If the client is missing a location, we start them off in the starter town they chose if (session.Player.Location == null) { if (session.Player.Instantiation != null) { session.Player.Location = new Position(session.Player.Instantiation); } else { session.Player.Location = new Position(0xA9B40019, 84, 7.1f, 94, 0, 0, -0.0784591f, 0.996917f); // ultimate fallback } } session.Player.PlayerEnterWorld(); var success = LandblockManager.AddObject(session.Player, true); if (!success) { // send to lifestone, or fallback location var fixLoc = session.Player.Sanctuary ?? new Position(0xA9B40019, 84, 7.1f, 94, 0, 0, -0.0784591f, 0.996917f); log.Error($"WorldManager.DoPlayerEnterWorld: failed to spawn {session.Player.Name}, relocating to {fixLoc.ToLOCString()}"); session.Player.Location = new Position(fixLoc); LandblockManager.AddObject(session.Player, true); var actionChain = new ActionChain(); actionChain.AddDelaySeconds(5.0f); actionChain.AddAction(session.Player, () => { if (session != null && session.Player != null) { session.Player.Teleport(fixLoc); } }); actionChain.EnqueueChain(); } // These warnings are set by DDD_InterrogationResponse if ((session.DatWarnCell || session.DatWarnLanguage || session.DatWarnPortal) && PropertyManager.GetBool("show_dat_warning").Item) { var msg = PropertyManager.GetString("dat_warning_msg").Item; var chatMsg = new GameMessageSystemChat(msg, ChatMessageType.System); session.Network.EnqueueSend(chatMsg); } var popup_header = PropertyManager.GetString("popup_header").Item; var popup_motd = PropertyManager.GetString("popup_motd").Item; var popup_welcome = PropertyManager.GetString("popup_welcome").Item; if (character.TotalLogins <= 1) { session.Network.EnqueueSend(new GameEventPopupString(session, AppendLines(popup_header, popup_motd, popup_welcome))); } else if (!string.IsNullOrEmpty(popup_motd)) { session.Network.EnqueueSend(new GameEventPopupString(session, AppendLines(popup_header, popup_motd))); } var info = "Welcome to Asheron's Call\n powered by ACEmulator\n\nFor more information on commands supported by this server, type @acehelp\n"; session.Network.EnqueueSend(new GameMessageSystemChat(info, ChatMessageType.Broadcast)); var server_motd = PropertyManager.GetString("server_motd").Item; if (!string.IsNullOrEmpty(server_motd)) { session.Network.EnqueueSend(new GameMessageSystemChat($"{server_motd}\n", ChatMessageType.Broadcast)); } if (playerLoggedInOnNoLogLandblock) // see http://acpedia.org/wiki/Mount_Elyrii_Hive { session.Network.EnqueueSend(new GameMessageSystemChat("The currents of portal space cannot return you from whence you came. Your previous location forbids login.", ChatMessageType.Broadcast)); } }
private static void SetBiotaPopulatedCollections(Biota biota) { PopulatedCollectionFlags populatedCollectionFlags = 0; if (biota.BiotaPropertiesAnimPart != null && biota.BiotaPropertiesAnimPart.Count > 0) { populatedCollectionFlags |= PopulatedCollectionFlags.BiotaPropertiesAnimPart; } if (biota.BiotaPropertiesAttribute != null && biota.BiotaPropertiesAttribute.Count > 0) { populatedCollectionFlags |= PopulatedCollectionFlags.BiotaPropertiesAttribute; } if (biota.BiotaPropertiesAttribute2nd != null && biota.BiotaPropertiesAttribute2nd.Count > 0) { populatedCollectionFlags |= PopulatedCollectionFlags.BiotaPropertiesAttribute2nd; } if (biota.BiotaPropertiesBodyPart != null && biota.BiotaPropertiesBodyPart.Count > 0) { populatedCollectionFlags |= PopulatedCollectionFlags.BiotaPropertiesBodyPart; } if (biota.BiotaPropertiesBook != null) { populatedCollectionFlags |= PopulatedCollectionFlags.BiotaPropertiesBook; } if (biota.BiotaPropertiesBookPageData != null && biota.BiotaPropertiesBookPageData.Count > 0) { populatedCollectionFlags |= PopulatedCollectionFlags.BiotaPropertiesBookPageData; } if (biota.BiotaPropertiesBool != null && biota.BiotaPropertiesBool.Count > 0) { populatedCollectionFlags |= PopulatedCollectionFlags.BiotaPropertiesBool; } if (biota.BiotaPropertiesCreateList != null && biota.BiotaPropertiesCreateList.Count > 0) { populatedCollectionFlags |= PopulatedCollectionFlags.BiotaPropertiesCreateList; } if (biota.BiotaPropertiesDID != null && biota.BiotaPropertiesDID.Count > 0) { populatedCollectionFlags |= PopulatedCollectionFlags.BiotaPropertiesDID; } if (biota.BiotaPropertiesEmote != null && biota.BiotaPropertiesEmote.Count > 0) { populatedCollectionFlags |= PopulatedCollectionFlags.BiotaPropertiesEmote; } if (biota.BiotaPropertiesEnchantmentRegistry != null && biota.BiotaPropertiesEnchantmentRegistry.Count > 0) { populatedCollectionFlags |= PopulatedCollectionFlags.BiotaPropertiesEnchantmentRegistry; } if (biota.BiotaPropertiesEventFilter != null && biota.BiotaPropertiesEventFilter.Count > 0) { populatedCollectionFlags |= PopulatedCollectionFlags.BiotaPropertiesEventFilter; } if (biota.BiotaPropertiesFloat != null && biota.BiotaPropertiesFloat.Count > 0) { populatedCollectionFlags |= PopulatedCollectionFlags.BiotaPropertiesFloat; } if (biota.BiotaPropertiesGenerator != null && biota.BiotaPropertiesGenerator.Count > 0) { populatedCollectionFlags |= PopulatedCollectionFlags.BiotaPropertiesGenerator; } if (biota.BiotaPropertiesIID != null && biota.BiotaPropertiesIID.Count > 0) { populatedCollectionFlags |= PopulatedCollectionFlags.BiotaPropertiesIID; } if (biota.BiotaPropertiesInt != null && biota.BiotaPropertiesInt.Count > 0) { populatedCollectionFlags |= PopulatedCollectionFlags.BiotaPropertiesInt; } if (biota.BiotaPropertiesInt64 != null && biota.BiotaPropertiesInt64.Count > 0) { populatedCollectionFlags |= PopulatedCollectionFlags.BiotaPropertiesInt64; } if (biota.BiotaPropertiesPalette != null && biota.BiotaPropertiesPalette.Count > 0) { populatedCollectionFlags |= PopulatedCollectionFlags.BiotaPropertiesPalette; } if (biota.BiotaPropertiesPosition != null && biota.BiotaPropertiesPosition.Count > 0) { populatedCollectionFlags |= PopulatedCollectionFlags.BiotaPropertiesPosition; } if (biota.BiotaPropertiesSkill != null && biota.BiotaPropertiesSkill.Count > 0) { populatedCollectionFlags |= PopulatedCollectionFlags.BiotaPropertiesSkill; } if (biota.BiotaPropertiesSpellBook != null && biota.BiotaPropertiesSpellBook.Count > 0) { populatedCollectionFlags |= PopulatedCollectionFlags.BiotaPropertiesSpellBook; } if (biota.BiotaPropertiesString != null && biota.BiotaPropertiesString.Count > 0) { populatedCollectionFlags |= PopulatedCollectionFlags.BiotaPropertiesString; } if (biota.BiotaPropertiesTextureMap != null && biota.BiotaPropertiesTextureMap.Count > 0) { populatedCollectionFlags |= PopulatedCollectionFlags.BiotaPropertiesTextureMap; } if (biota.HousePermission != null && biota.HousePermission.Count > 0) { populatedCollectionFlags |= PopulatedCollectionFlags.HousePermission; } if (biota.BiotaPropertiesAllegiance != null && biota.BiotaPropertiesAllegiance.Count > 0) { populatedCollectionFlags |= PopulatedCollectionFlags.BiotaPropertiesAllegiance; } biota.PopulatedCollectionFlags = (uint)populatedCollectionFlags; }
/// <summary> /// Restore a WorldObject from the database. /// </summary> public Caster(Biota biota) : base(biota) { SetEphemeralValues(); }
/// <summary> /// Restore a WorldObject from the database. /// </summary> public Container(Biota biota) : base(biota) { if (Biota.TryRemoveProperty(PropertyBool.Open, BiotaDatabaseLock)) { ChangesDetected = true; } // This is a temporary fix for objects that were loaded with this PR when EncumbranceVal was not treated as ephemeral. 2020-03-28 // This can be removed later. if (Biota.PropertiesInt.ContainsKey(PropertyInt.EncumbranceVal)) { var weenie = DatabaseManager.World.GetCachedWeenie(biota.WeenieClassId); if (weenie != null && weenie.PropertiesInt.TryGetValue(PropertyInt.EncumbranceVal, out var value)) { if (biota.PropertiesInt[PropertyInt.EncumbranceVal] != value) { biota.PropertiesInt[PropertyInt.EncumbranceVal] = value; ChangesDetected = true; } } else { biota.PropertiesInt.Remove(PropertyInt.EncumbranceVal); ChangesDetected = true; } } // This is a temporary fix for objects that were loaded with this PR when Value was not treated as ephemeral. 2020-03-28 // This can be removed later. if (!(this is Creature) && Biota.PropertiesInt.ContainsKey(PropertyInt.Value)) { var weenie = DatabaseManager.World.GetCachedWeenie(biota.WeenieClassId); if (weenie != null && weenie.PropertiesInt.TryGetValue(PropertyInt.Value, out var value)) { if (biota.PropertiesInt[PropertyInt.Value] != value) { biota.PropertiesInt[PropertyInt.Value] = value; ChangesDetected = true; } } else { biota.PropertiesInt.Remove(PropertyInt.Value); ChangesDetected = true; } } InitializePropertyDictionaries(); SetEphemeralValues(true); // A player has their possessions passed via the ctor. All other world objects must load their own inventory if (!(this is Player) && !ObjectGuid.IsPlayer(ContainerId ?? 0)) { DatabaseManager.Shard.GetInventoryInParallel(biota.Id, false, biotas => { EnqueueAction(new ActionEventDelegate(() => SortBiotasIntoInventory(biotas))); }); } }
/// <summary> /// Restore a WorldObject from the database. /// </summary> public Key(Biota biota) : base(biota) { SetEphemeralValues(); }
/// <summary> /// Restore a WorldObject from the database. /// </summary> public Ammunition(Biota biota) : base(biota) { SetEphemeralValues(); }
/// <summary> /// Restore a WorldObject from the database. /// </summary> public Switch(Biota biota) : base(biota) { SetEphemeralValues(); }
/// <summary> /// Restore a WorldObject from the database. /// </summary> public Hooker(Biota biota) : base(biota) { SetEphemeralValues(); }
public static Biota CreateCopyAsBiota(this Weenie weenie, uint id) { var biota = new Biota(); biota.Id = id; biota.WeenieClassId = weenie.ClassId; biota.WeenieType = weenie.Type; if (weenie.WeeniePropertiesBook != null) { biota.BiotaPropertiesBook = new BiotaPropertiesBook(); biota.BiotaPropertiesBook.ObjectId = biota.Id; biota.BiotaPropertiesBook.MaxNumPages = weenie.WeeniePropertiesBook.MaxNumPages; biota.BiotaPropertiesBook.MaxNumCharsPerPage = weenie.WeeniePropertiesBook.MaxNumCharsPerPage; } foreach (var value in weenie.WeeniePropertiesAnimPart) { biota.BiotaPropertiesAnimPart.Add(new BiotaPropertiesAnimPart { ObjectId = biota.Id, Index = value.Index, AnimationId = value.AnimationId }); } foreach (var value in weenie.WeeniePropertiesAttribute) { biota.BiotaPropertiesAttribute.Add(new BiotaPropertiesAttribute { ObjectId = biota.Id, Type = value.Type, InitLevel = value.InitLevel, LevelFromCP = value.LevelFromCP, CPSpent = value.CPSpent, }); } foreach (var value in weenie.WeeniePropertiesAttribute2nd) { biota.BiotaPropertiesAttribute2nd.Add(new BiotaPropertiesAttribute2nd { ObjectId = biota.Id, Type = value.Type, InitLevel = value.InitLevel, LevelFromCP = value.LevelFromCP, CPSpent = value.CPSpent, CurrentLevel = value.CurrentLevel, }); } foreach (var value in weenie.WeeniePropertiesBodyPart) { biota.BiotaPropertiesBodyPart.Add(new BiotaPropertiesBodyPart { ObjectId = biota.Id, Key = value.Key, DType = value.DType, DVal = value.DVal, DVar = value.DVar, BaseArmor = value.BaseArmor, ArmorVsSlash = value.ArmorVsSlash, ArmorVsPierce = value.ArmorVsPierce, ArmorVsBludgeon = value.ArmorVsBludgeon, ArmorVsCold = value.ArmorVsCold, ArmorVsFire = value.ArmorVsFire, ArmorVsAcid = value.ArmorVsAcid, ArmorVsElectric = value.ArmorVsElectric, ArmorVsNether = value.ArmorVsNether, BH = value.BH, HLF = value.HLF, MLF = value.MLF, LLF = value.LLF, HRF = value.HRF, MRF = value.MRF, LRF = value.LRF, HLB = value.HLB, MLB = value.MLB, LLB = value.LLB, HRB = value.HRB, MRB = value.MRB, LRB = value.LRB, }); } foreach (var value in weenie.WeeniePropertiesBookPageData) { biota.BiotaPropertiesBookPageData.Add(new BiotaPropertiesBookPageData { ObjectId = biota.Id, PageId = value.PageId, AuthorId = value.AuthorId, AuthorName = value.AuthorName, AuthorAccount = value.AuthorAccount, IgnoreAuthor = value.IgnoreAuthor, PageText = value.PageText, }); } foreach (var value in weenie.WeeniePropertiesBool) { biota.BiotaPropertiesBool.Add(new BiotaPropertiesBool { ObjectId = biota.Id, Type = value.Type, Value = value.Value, }); } foreach (var value in weenie.WeeniePropertiesCreateList) { biota.BiotaPropertiesCreateList.Add(new BiotaPropertiesCreateList { ObjectId = biota.Id, DestinationType = value.DestinationType, WeenieClassId = value.WeenieClassId, StackSize = value.StackSize, Palette = value.Palette, Shade = value.Shade, TryToBond = value.TryToBond, }); } foreach (var value in weenie.WeeniePropertiesDID) { biota.BiotaPropertiesDID.Add(new BiotaPropertiesDID { ObjectId = biota.Id, Type = value.Type, Value = value.Value, }); } foreach (var value in weenie.WeeniePropertiesEmote) { var emote = new BiotaPropertiesEmote { ObjectId = biota.Id, Category = value.Category, Probability = value.Probability, WeenieClassId = value.WeenieClassId, Style = value.Style, Substyle = value.Substyle, Quest = value.Quest, VendorType = value.VendorType, MinHealth = value.MinHealth, MaxHealth = value.MaxHealth, }; foreach (var value2 in value.WeeniePropertiesEmoteAction) { var action = new BiotaPropertiesEmoteAction { // EmoteId is a foreign key to Emote.Id. // If we don't set this to a non-zero number, EF will not auto-set this for us when we add this biota to the database. // We set it to uint.MaxValue instead of 1 because 1 is more likely to be a valid foreign key. We don't want to enter a valid foreign key. // We just want to enter a value that forces EF to update the record with the correft foreign key. If this behavior changes in the future and we set it to 1, // we're more likely to run into an unnoticed issue (because 1 would not throw an exception and uint.MaxValue probably would). // We put this here instead of in ShardDatabase for efficiency. // It's possible this might be fixable with a attribute in the Emote or EmoteAction classes. // It's also possible we don't have the schema defined in a way that helps scaffolding identify the relationship. // Mag-nus 2018-08-04 EmoteId = uint.MaxValue, Order = value2.Order, Type = value2.Type, Delay = value2.Delay, Extent = value2.Extent, Motion = value2.Motion, Message = value2.Message, TestString = value2.TestString, Min = value2.Min, Max = value2.Max, Min64 = value2.Min64, Max64 = value2.Max64, MinDbl = value2.MinDbl, MaxDbl = value2.MaxDbl, Stat = value2.Stat, Display = value2.Display, Amount = value2.Amount, Amount64 = value2.Amount64, HeroXP64 = value2.HeroXP64, Percent = value2.Percent, SpellId = value2.SpellId, WealthRating = value2.WealthRating, TreasureClass = value2.TreasureClass, TreasureType = value2.TreasureType, PScript = value2.PScript, Sound = value2.Sound, DestinationType = value2.DestinationType, WeenieClassId = value2.WeenieClassId, StackSize = value2.StackSize, Palette = value2.Palette, Shade = value2.Shade, TryToBond = value2.TryToBond, ObjCellId = value2.ObjCellId, OriginX = value2.OriginX, OriginY = value2.OriginY, OriginZ = value2.OriginZ, AnglesW = value2.AnglesW, AnglesX = value2.AnglesX, AnglesY = value2.AnglesY, AnglesZ = value2.AnglesZ, }; emote.BiotaPropertiesEmoteAction.Add(action); } biota.BiotaPropertiesEmote.Add(emote); } foreach (var value in weenie.WeeniePropertiesEventFilter) { biota.BiotaPropertiesEventFilter.Add(new BiotaPropertiesEventFilter { ObjectId = biota.Id, Event = value.Event, }); } foreach (var value in weenie.WeeniePropertiesFloat) { biota.BiotaPropertiesFloat.Add(new BiotaPropertiesFloat { ObjectId = biota.Id, Type = value.Type, Value = value.Value, }); } foreach (var value in weenie.WeeniePropertiesGenerator) { biota.BiotaPropertiesGenerator.Add(new BiotaPropertiesGenerator { ObjectId = biota.Id, Probability = value.Probability, WeenieClassId = value.WeenieClassId, Delay = value.Delay, InitCreate = value.InitCreate, MaxCreate = value.MaxCreate, WhenCreate = value.WhenCreate, WhereCreate = value.WhereCreate, StackSize = value.StackSize, PaletteId = value.PaletteId, Shade = value.Shade, ObjCellId = value.ObjCellId, OriginX = value.OriginX, OriginY = value.OriginY, OriginZ = value.OriginZ, AnglesW = value.AnglesW, AnglesX = value.AnglesX, AnglesY = value.AnglesY, AnglesZ = value.AnglesZ, }); } foreach (var value in weenie.WeeniePropertiesIID) { biota.BiotaPropertiesIID.Add(new BiotaPropertiesIID { ObjectId = biota.Id, Type = value.Type, Value = value.Value, }); } foreach (var value in weenie.WeeniePropertiesInt) { biota.BiotaPropertiesInt.Add(new BiotaPropertiesInt { ObjectId = biota.Id, Type = value.Type, Value = value.Value, }); } foreach (var value in weenie.WeeniePropertiesInt64) { biota.BiotaPropertiesInt64.Add(new BiotaPropertiesInt64 { ObjectId = biota.Id, Type = value.Type, Value = value.Value, }); } foreach (var value in weenie.WeeniePropertiesPalette) { biota.BiotaPropertiesPalette.Add(new BiotaPropertiesPalette { ObjectId = biota.Id, SubPaletteId = value.SubPaletteId, Offset = value.Offset, Length = value.Length, }); } foreach (var value in weenie.WeeniePropertiesPosition) { biota.BiotaPropertiesPosition.Add(new BiotaPropertiesPosition { ObjectId = biota.Id, PositionType = value.PositionType, ObjCellId = value.ObjCellId, OriginX = value.OriginX, OriginY = value.OriginY, OriginZ = value.OriginZ, AnglesW = value.AnglesW, AnglesX = value.AnglesX, AnglesY = value.AnglesY, AnglesZ = value.AnglesZ, }); } foreach (var value in weenie.WeeniePropertiesSkill) { biota.BiotaPropertiesSkill.Add(new BiotaPropertiesSkill { ObjectId = biota.Id, Type = value.Type, LevelFromPP = value.LevelFromPP, SAC = value.SAC, PP = value.PP, InitLevel = value.InitLevel, ResistanceAtLastCheck = value.ResistanceAtLastCheck, LastUsedTime = value.LastUsedTime, }); } foreach (var value in weenie.WeeniePropertiesSpellBook) { biota.BiotaPropertiesSpellBook.Add(new BiotaPropertiesSpellBook { ObjectId = biota.Id, Spell = value.Spell, Probability = value.Probability, }); } foreach (var value in weenie.WeeniePropertiesString) { biota.BiotaPropertiesString.Add(new BiotaPropertiesString { ObjectId = biota.Id, Type = value.Type, Value = value.Value, }); } foreach (var value in weenie.WeeniePropertiesTextureMap) { biota.BiotaPropertiesTextureMap.Add(new BiotaPropertiesTextureMap { ObjectId = biota.Id, Index = value.Index, OldId = value.OldId, NewId = value.NewId, }); } return(biota); }
/// <summary> /// Restore a WorldObject from the database. /// </summary> public Admin(Biota biota, IEnumerable <ACE.Database.Models.Shard.Biota> inventory, IEnumerable <ACE.Database.Models.Shard.Biota> wieldedItems, Character character, Session session) : base(biota, inventory, wieldedItems, character, session) { SetEphemeralValues(); }
/// <summary> /// Restore a WorldObject from the database. /// </summary> public PKModifier(Biota biota) : base(biota) { SetEphemeralValues(); }
public bool SaveBiota(Biota biota, ReaderWriterLockSlim rwLock) { if (BiotaContexts.TryGetValue(biota, out var cachedContext)) { rwLock.EnterReadLock(); try { SetBiotaPopulatedCollections(biota); Exception firstException = null; retry: try { cachedContext.SaveChanges(); if (firstException != null) { log.Debug($"SaveBiota retry succeeded after initial exception of: {firstException.GetFullMessage()}"); } return(true); } catch (Exception ex) { if (firstException == null) { firstException = ex; goto retry; } // Character name might be in use or some other fault log.Error($"SaveBiota failed first attempt with exception: {firstException}"); log.Error($"SaveBiota failed second attempt with exception: {ex}"); return(false); } } finally { rwLock.ExitReadLock(); } } var context = new ShardDbContext(); BiotaContexts.Add(biota, context); rwLock.EnterReadLock(); try { SetBiotaPopulatedCollections(biota); context.Biota.Add(biota); Exception firstException = null; retry: try { context.SaveChanges(); if (firstException != null) { log.Debug($"SaveBiota retry succeeded after initial exception of: {firstException.GetFullMessage()}"); } return(true); } catch (Exception ex) { if (firstException == null) { firstException = ex; goto retry; } // Character name might be in use or some other fault log.Error($"SaveBiota failed first attempt with exception: {firstException}"); log.Error($"SaveBiota failed second attempt with exception: {ex}"); return(false); } } finally { rwLock.ExitReadLock(); } }
/// <summary> /// Restore a WorldObject from the database. /// </summary> public Door(Biota biota) : base(biota) { SetEphemeralValues(); }
/// <summary> /// Restore a WorldObject from the database. /// </summary> public ManaStone(Biota biota) : base(biota) { SetEphemeralValues(); }
/// <summary> /// Restore a WorldObject from the database. /// </summary> public SpellProjectile(Biota biota) : base(biota) { SetEphemeralValues(); }
public static void PurgeCharacter(ShardDbContext context, uint characterId, out int charactersPurged, out int playerBiotasPurged, out int possessionsPurged, string reason = null) { charactersPurged = 0; playerBiotasPurged = 0; possessionsPurged = 0; // First purge the inventory var inventoryBiotas = GetInventoryBiotas(context, characterId, true); foreach (var biota in inventoryBiotas) { context.Biota.Remove(biota); possessionsPurged++; } // Then the wielded items var wieldedGuids = GetWieldedGuids(context, characterId); foreach (var guid in wieldedGuids) { var stub = new Biota { Id = guid }; context.Biota.Attach(stub); context.Biota.Remove(stub); possessionsPurged++; } // Second to last, the payer biota if (context.Biota.Any(r => r.Id == characterId)) { var stub = new Biota { Id = characterId }; context.Biota.Attach(stub); context.Biota.Remove(stub); playerBiotasPurged++; } // Lastly, the character record var character = context.Character.FirstOrDefault(r => r.Id == characterId); if (character != null) { context.Character.Remove(character); charactersPurged++; } var message = $"[DATABASE][PURGE] Character 0x{characterId:X8}"; if (character != null) { message += $":{character.Name}, deleted on {Common.Time.GetDateTimeFromTimestamp(character.DeleteTime).ToLocalTime()}"; } message += $", and {possessionsPurged} of their possessions has been purged."; if (!String.IsNullOrWhiteSpace(reason)) { message += $" Reason: {reason}."; } log.Debug(message); try { context.SaveChanges(); } catch (Exception ex) { log.Error($"[DATABASE][PURGE] PurgeCharacter 0x{characterId:X8} failed with exception: {ex}"); } }
/// <summary> /// Restore a WorldObject from the database. /// </summary> public Bindstone(Biota biota) : base(biota) { SetEphemeralValues(); }
/// <summary> /// Restore a WorldObject from the database. /// </summary> public PetDevice(Biota biota) : base(biota) { SetEphemeralValues(); }
/// <summary> /// Restore a WorldObject from the database. /// </summary> public CombatPet(Biota biota) : base(biota) { SetEphemeralValues(); }
/// <summary> /// Restore a WorldObject from the database. /// Any properties tagged as Ephemeral will be removed from the biota. /// </summary> public static WorldObject CreateWorldObject(Biota biota) { var objWeenieType = (WeenieType)biota.WeenieType; switch (objWeenieType) { case WeenieType.Undef: return(null); case WeenieType.LifeStone: return(new Lifestone(biota)); case WeenieType.Door: return(new Door(biota)); case WeenieType.Portal: return(new Portal(biota)); case WeenieType.Book: return(new Book(biota)); case WeenieType.PKModifier: return(new PKModifier(biota)); case WeenieType.Cow: return(new Cow(biota)); case WeenieType.Creature: return(new Creature(biota)); case WeenieType.Container: return(new Container(biota)); case WeenieType.Scroll: return(new Scroll(biota)); case WeenieType.Vendor: return(new Vendor(biota)); case WeenieType.Coin: return(new Coin(biota)); case WeenieType.Key: return(new Key(biota)); case WeenieType.Food: return(new Food(biota)); case WeenieType.Gem: return(new Gem(biota)); case WeenieType.Game: return(new Game(biota)); case WeenieType.GamePiece: return(new GamePiece(biota)); case WeenieType.AllegianceBindstone: return(new Bindstone(biota)); case WeenieType.Clothing: return(new Clothing(biota)); case WeenieType.MeleeWeapon: return(new MeleeWeapon(biota)); case WeenieType.MissileLauncher: return(new MissileLauncher(biota)); case WeenieType.Ammunition: return(new Ammunition(biota)); case WeenieType.Missile: return(new Missile(biota)); case WeenieType.Corpse: return(new Corpse(biota)); case WeenieType.Chest: return(new Chest(biota)); case WeenieType.Stackable: return(new Stackable(biota)); case WeenieType.SpellComponent: return(new SpellComponent(biota)); case WeenieType.Switch: return(new Switch(biota)); case WeenieType.AdvocateFane: return(new AdvocateFane(biota)); case WeenieType.AdvocateItem: return(new AdvocateItem(biota)); case WeenieType.Healer: return(new Healer(biota)); case WeenieType.Lockpick: return(new Lockpick(biota)); case WeenieType.Caster: return(new Caster(biota)); case WeenieType.HotSpot: return(new Hotspot(biota)); case WeenieType.ManaStone: return(new ManaStone(biota)); case WeenieType.House: return(new House(biota)); case WeenieType.SlumLord: return(new SlumLord(biota)); case WeenieType.Storage: return(new Storage(biota)); case WeenieType.Hook: return(new Hook(biota)); case WeenieType.Hooker: return(new Hooker(biota)); case WeenieType.HousePortal: return(new WorldObjects.HousePortal(biota)); case WeenieType.SkillAlterationDevice: return(new SkillAlterationDevice(biota)); case WeenieType.PressurePlate: return(new PressurePlate(biota)); case WeenieType.PetDevice: return(new PetDevice(biota)); case WeenieType.Pet: return(new Pet(biota)); case WeenieType.CombatPet: return(new CombatPet(biota)); case WeenieType.Allegiance: return(new Allegiance(biota)); default: return(new GenericObject(biota)); } }
/// <summary> /// Restore a WorldObject from the database. /// </summary> public Food(Biota biota) : base(biota) { SetEphemeralValues(); }
/// <summary> /// Restore a WorldObject from the database. /// </summary> public Sentinel(Biota biota, IEnumerable <Biota> inventory, IEnumerable <Biota> wieldedItems, Session session) : base(biota, inventory, wieldedItems, session) { SetEphemeralValues(); }
private void UpdateBiota(ShardDbContext context, Biota existingBiota, Biota biota) { // This pattern is described here: https://docs.microsoft.com/en-us/ef/core/saving/disconnected-entities // You'll notice though that we're not using the recommended: context.Entry(existingEntry).CurrentValues.SetValues(newEntry); // It is EXTREMLY slow. 4x or more slower. I suspect because it uses reflection to find the properties that the object contains // Manually setting the properties like we do below is the best case scenario for performance. However, it also has risks. // If we add columns to the schema and forget to add those changes here, changes to the biota may not propagate to the database. // Mag-nus 2018-08-18 context.Entry(existingBiota).CurrentValues.SetValues(biota); foreach (var value in biota.BiotaPropertiesAnimPart) { BiotaPropertiesAnimPart existingValue = (value.Id == 0 ? null : existingBiota.BiotaPropertiesAnimPart.FirstOrDefault(r => r.Id == value.Id)); if (existingValue == null) { existingBiota.BiotaPropertiesAnimPart.Add(value); } else { existingValue.Index = value.Index; existingValue.AnimationId = value.AnimationId; existingValue.Order = value.Order; } } foreach (var value in existingBiota.BiotaPropertiesAnimPart) { if (!biota.BiotaPropertiesAnimPart.Any(p => p.Id == value.Id)) { context.BiotaPropertiesAnimPart.Remove(value); } } foreach (var value in biota.BiotaPropertiesAttribute) { BiotaPropertiesAttribute existingValue = existingBiota.BiotaPropertiesAttribute.FirstOrDefault(r => r.Type == value.Type); if (existingValue == null) { existingBiota.BiotaPropertiesAttribute.Add(value); } else { existingValue.InitLevel = value.InitLevel; existingValue.LevelFromCP = value.LevelFromCP; existingValue.CPSpent = value.CPSpent; } } foreach (var value in existingBiota.BiotaPropertiesAttribute) { if (!biota.BiotaPropertiesAttribute.Any(p => p.Type == value.Type)) { context.BiotaPropertiesAttribute.Remove(value); } } foreach (var value in biota.BiotaPropertiesAttribute2nd) { BiotaPropertiesAttribute2nd existingValue = existingBiota.BiotaPropertiesAttribute2nd.FirstOrDefault(r => r.Type == value.Type); if (existingValue == null) { existingBiota.BiotaPropertiesAttribute2nd.Add(value); } else { existingValue.InitLevel = value.InitLevel; existingValue.LevelFromCP = value.LevelFromCP; existingValue.CPSpent = value.CPSpent; existingValue.CurrentLevel = value.CurrentLevel; } } foreach (var value in existingBiota.BiotaPropertiesAttribute2nd) { if (!biota.BiotaPropertiesAttribute2nd.Any(p => p.Type == value.Type)) { context.BiotaPropertiesAttribute2nd.Remove(value); } } foreach (var value in biota.BiotaPropertiesBodyPart) { BiotaPropertiesBodyPart existingValue = (value.Id == 0 ? null : existingBiota.BiotaPropertiesBodyPart.FirstOrDefault(r => r.Id == value.Id)); if (existingValue == null) { existingBiota.BiotaPropertiesBodyPart.Add(value); } else { existingValue.Key = value.Key; existingValue.DType = value.DType; existingValue.DVal = value.DVal; existingValue.DVar = value.DVar; existingValue.BaseArmor = value.BaseArmor; existingValue.ArmorVsSlash = value.ArmorVsSlash; existingValue.ArmorVsPierce = value.ArmorVsPierce; existingValue.ArmorVsBludgeon = value.ArmorVsBludgeon; existingValue.ArmorVsCold = value.ArmorVsCold; existingValue.ArmorVsFire = value.ArmorVsFire; existingValue.ArmorVsAcid = value.ArmorVsAcid; existingValue.ArmorVsElectric = value.ArmorVsElectric; existingValue.ArmorVsNether = value.ArmorVsNether; existingValue.BH = value.BH; existingValue.HLF = value.HLF; existingValue.MLF = value.MLF; existingValue.LLF = value.LLF; existingValue.HRF = value.HRF; existingValue.MRF = value.MRF; existingValue.LRF = value.LRF; existingValue.HLB = value.HLB; existingValue.MLB = value.MLB; existingValue.LLB = value.LLB; existingValue.HRB = value.HRB; existingValue.MRB = value.MRB; existingValue.LRB = value.LRB; } } foreach (var value in existingBiota.BiotaPropertiesBodyPart) { if (!biota.BiotaPropertiesBodyPart.Any(p => p.Id == value.Id)) { context.BiotaPropertiesBodyPart.Remove(value); } } if (biota.BiotaPropertiesBook != null) { if (existingBiota.BiotaPropertiesBook == null) { existingBiota.BiotaPropertiesBook = biota.BiotaPropertiesBook; } else { existingBiota.BiotaPropertiesBook.MaxNumPages = biota.BiotaPropertiesBook.MaxNumPages; existingBiota.BiotaPropertiesBook.MaxNumCharsPerPage = biota.BiotaPropertiesBook.MaxNumCharsPerPage; } } else { if (existingBiota.BiotaPropertiesBook != null) { context.BiotaPropertiesBook.Remove(existingBiota.BiotaPropertiesBook); } } foreach (var value in biota.BiotaPropertiesBookPageData) { BiotaPropertiesBookPageData existingValue = (value.Id == 0 ? null : existingBiota.BiotaPropertiesBookPageData.FirstOrDefault(r => r.Id == value.Id)); if (existingValue == null) { existingBiota.BiotaPropertiesBookPageData.Add(value); } else { existingValue.PageId = value.PageId; existingValue.AuthorId = value.AuthorId; existingValue.AuthorName = value.AuthorName; existingValue.AuthorAccount = value.AuthorAccount; existingValue.IgnoreAuthor = value.IgnoreAuthor; existingValue.PageText = value.PageText; } } foreach (var value in existingBiota.BiotaPropertiesBookPageData) { if (!biota.BiotaPropertiesBookPageData.Any(p => p.Id == value.Id)) { context.BiotaPropertiesBookPageData.Remove(value); } } foreach (var value in biota.BiotaPropertiesBool) { BiotaPropertiesBool existingValue = existingBiota.BiotaPropertiesBool.FirstOrDefault(r => r.Type == value.Type); if (existingValue == null) { existingBiota.BiotaPropertiesBool.Add(value); } else { existingValue.Value = value.Value; } } foreach (var value in existingBiota.BiotaPropertiesBool) { if (!biota.BiotaPropertiesBool.Any(p => p.Type == value.Type)) { context.BiotaPropertiesBool.Remove(value); } } foreach (var value in biota.BiotaPropertiesCreateList) { BiotaPropertiesCreateList existingValue = (value.Id == 0 ? null : existingBiota.BiotaPropertiesCreateList.FirstOrDefault(r => r.Id == value.Id)); if (existingValue == null) { existingBiota.BiotaPropertiesCreateList.Add(value); } else { existingValue.DestinationType = value.DestinationType; existingValue.WeenieClassId = value.WeenieClassId; existingValue.StackSize = value.StackSize; existingValue.Palette = value.Palette; existingValue.Shade = value.Shade; existingValue.TryToBond = value.TryToBond; } } foreach (var value in existingBiota.BiotaPropertiesCreateList) { if (!biota.BiotaPropertiesCreateList.Any(p => p.Id == value.Id)) { context.BiotaPropertiesCreateList.Remove(value); } } foreach (var value in biota.BiotaPropertiesDID) { BiotaPropertiesDID existingValue = existingBiota.BiotaPropertiesDID.FirstOrDefault(r => r.Type == value.Type); if (existingValue == null) { existingBiota.BiotaPropertiesDID.Add(value); } else { existingValue.Value = value.Value; } } foreach (var value in existingBiota.BiotaPropertiesDID) { if (!biota.BiotaPropertiesDID.Any(p => p.Type == value.Type)) { context.BiotaPropertiesDID.Remove(value); } } foreach (var value in biota.BiotaPropertiesEmote) { BiotaPropertiesEmote existingValue = (value.Id == 0 ? null : existingBiota.BiotaPropertiesEmote.FirstOrDefault(r => r.Id == value.Id)); if (existingValue == null) { existingBiota.BiotaPropertiesEmote.Add(value); } else { existingValue.Category = value.Category; existingValue.Probability = value.Probability; existingValue.WeenieClassId = value.WeenieClassId; existingValue.Style = value.Style; existingValue.Substyle = value.Substyle; existingValue.Quest = value.Quest; existingValue.VendorType = value.VendorType; existingValue.MinHealth = value.MinHealth; existingValue.MaxHealth = value.MaxHealth; foreach (var value2 in value.BiotaPropertiesEmoteAction) { BiotaPropertiesEmoteAction existingValue2 = (value2.Id == 0 ? null : existingValue.BiotaPropertiesEmoteAction.FirstOrDefault(r => r.Id == value2.Id)); if (existingValue2 == null) { existingValue.BiotaPropertiesEmoteAction.Add(value2); } else { existingValue2.EmoteId = value2.EmoteId; existingValue2.Order = value2.Order; existingValue2.Type = value2.Type; existingValue2.Delay = value2.Delay; existingValue2.Extent = value2.Extent; existingValue2.Motion = value2.Motion; existingValue2.Message = value2.Message; existingValue2.TestString = value2.TestString; existingValue2.Min = value2.Min; existingValue2.Max = value2.Max; existingValue2.Min64 = value2.Min64; existingValue2.Max64 = value2.Max64; existingValue2.MinDbl = value2.MinDbl; existingValue2.MaxDbl = value2.MaxDbl; existingValue2.Stat = value2.Stat; existingValue2.Display = value2.Display; existingValue2.Amount = value2.Amount; existingValue2.Amount64 = value2.Amount64; existingValue2.HeroXP64 = value2.HeroXP64; existingValue2.Percent = value2.Percent; existingValue2.SpellId = value2.SpellId; existingValue2.WealthRating = value2.WealthRating; existingValue2.TreasureClass = value2.TreasureClass; existingValue2.TreasureType = value2.TreasureType; existingValue2.PScript = value2.PScript; existingValue2.Sound = value2.Sound; existingValue2.DestinationType = value2.DestinationType; existingValue2.WeenieClassId = value2.WeenieClassId; existingValue2.StackSize = value2.StackSize; existingValue2.Palette = value2.Palette; existingValue2.Shade = value2.Shade; existingValue2.TryToBond = value2.TryToBond; existingValue2.ObjCellId = value2.ObjCellId; existingValue2.OriginX = value2.OriginX; existingValue2.OriginY = value2.OriginY; existingValue2.OriginZ = value2.OriginZ; existingValue2.AnglesW = value2.AnglesW; existingValue2.AnglesX = value2.AnglesX; existingValue2.AnglesY = value2.AnglesY; existingValue2.AnglesZ = value2.AnglesZ; } } foreach (var value2 in value.BiotaPropertiesEmoteAction) { if (!existingValue.BiotaPropertiesEmoteAction.Any(p => p.Id == value2.Id)) { context.BiotaPropertiesEmoteAction.Remove(value2); } } } } foreach (var value in existingBiota.BiotaPropertiesEmote) { if (!biota.BiotaPropertiesEmote.Any(p => p.Id == value.Id)) { context.BiotaPropertiesEmote.Remove(value); } } foreach (var value in biota.BiotaPropertiesEnchantmentRegistry) { BiotaPropertiesEnchantmentRegistry existingValue = (value.ObjectId == 0 ? null : existingBiota.BiotaPropertiesEnchantmentRegistry.FirstOrDefault(r => r.SpellId == value.SpellId && r.LayerId == value.LayerId && r.CasterObjectId == value.CasterObjectId)); if (existingValue == null) { existingBiota.BiotaPropertiesEnchantmentRegistry.Add(value); } else { existingValue.EnchantmentCategory = value.EnchantmentCategory; existingValue.SpellId = value.SpellId; existingValue.LayerId = value.LayerId; existingValue.HasSpellSetId = value.HasSpellSetId; existingValue.SpellCategory = value.SpellCategory; existingValue.PowerLevel = value.PowerLevel; existingValue.StartTime = value.StartTime; existingValue.Duration = value.Duration; existingValue.CasterObjectId = value.CasterObjectId; existingValue.DegradeModifier = value.DegradeModifier; existingValue.DegradeLimit = value.DegradeLimit; existingValue.LastTimeDegraded = value.LastTimeDegraded; existingValue.StatModType = value.StatModType; existingValue.StatModKey = value.StatModKey; existingValue.StatModValue = value.StatModValue; existingValue.SpellSetId = value.SpellSetId; } } foreach (var value in existingBiota.BiotaPropertiesEnchantmentRegistry) { if (!biota.BiotaPropertiesEnchantmentRegistry.Any(p => p.SpellId == value.SpellId && p.LayerId == value.LayerId && p.CasterObjectId == value.CasterObjectId)) { context.BiotaPropertiesEnchantmentRegistry.Remove(value); } } foreach (var value in biota.BiotaPropertiesEventFilter) { BiotaPropertiesEventFilter existingValue = existingBiota.BiotaPropertiesEventFilter.FirstOrDefault(r => r.Event == value.Event); if (existingValue == null) { existingBiota.BiotaPropertiesEventFilter.Add(value); } } foreach (var value in existingBiota.BiotaPropertiesEventFilter) { if (!biota.BiotaPropertiesEventFilter.Any(p => p.Event == value.Event)) { context.BiotaPropertiesEventFilter.Remove(value); } } foreach (var value in biota.BiotaPropertiesFloat) { BiotaPropertiesFloat existingValue = existingBiota.BiotaPropertiesFloat.FirstOrDefault(r => r.Type == value.Type); if (existingValue == null) { existingBiota.BiotaPropertiesFloat.Add(value); } else { existingValue.Value = value.Value; } } foreach (var value in existingBiota.BiotaPropertiesFloat) { if (!biota.BiotaPropertiesFloat.Any(p => p.Type == value.Type)) { context.BiotaPropertiesFloat.Remove(value); } } foreach (var value in biota.BiotaPropertiesGenerator) { BiotaPropertiesGenerator existingValue = (value.Id == 0 ? null : existingBiota.BiotaPropertiesGenerator.FirstOrDefault(r => r.Id == value.Id)); if (existingValue == null) { existingBiota.BiotaPropertiesGenerator.Add(value); } else { existingValue.Probability = value.Probability; existingValue.WeenieClassId = value.WeenieClassId; existingValue.Delay = value.Delay; existingValue.InitCreate = value.InitCreate; existingValue.MaxCreate = value.MaxCreate; existingValue.WhenCreate = value.WhenCreate; existingValue.WhereCreate = value.WhereCreate; existingValue.StackSize = value.StackSize; existingValue.PaletteId = value.PaletteId; existingValue.Shade = value.Shade; existingValue.ObjCellId = value.ObjCellId; existingValue.OriginX = value.OriginX; existingValue.OriginY = value.OriginY; existingValue.OriginZ = value.OriginZ; existingValue.AnglesW = value.AnglesW; existingValue.AnglesX = value.AnglesX; existingValue.AnglesY = value.AnglesY; existingValue.AnglesZ = value.AnglesZ; } } foreach (var value in existingBiota.BiotaPropertiesGenerator) { if (!biota.BiotaPropertiesGenerator.Any(p => p.Id == value.Id)) { context.BiotaPropertiesGenerator.Remove(value); } } foreach (var value in biota.BiotaPropertiesIID) { BiotaPropertiesIID existingValue = existingBiota.BiotaPropertiesIID.FirstOrDefault(r => r.Type == value.Type); if (existingValue == null) { existingBiota.BiotaPropertiesIID.Add(value); } else { existingValue.Value = value.Value; } } foreach (var value in existingBiota.BiotaPropertiesIID) { if (!biota.BiotaPropertiesIID.Any(p => p.Type == value.Type)) { context.BiotaPropertiesIID.Remove(value); } } foreach (var value in biota.BiotaPropertiesInt) { BiotaPropertiesInt existingValue = existingBiota.BiotaPropertiesInt.FirstOrDefault(r => r.Type == value.Type); if (existingValue == null) { existingBiota.BiotaPropertiesInt.Add(value); } else { existingValue.Value = value.Value; } } foreach (var value in existingBiota.BiotaPropertiesInt) { if (!biota.BiotaPropertiesInt.Any(p => p.Type == value.Type)) { context.BiotaPropertiesInt.Remove(value); } } foreach (var value in biota.BiotaPropertiesInt64) { BiotaPropertiesInt64 existingValue = existingBiota.BiotaPropertiesInt64.FirstOrDefault(r => r.Type == value.Type); if (existingValue == null) { existingBiota.BiotaPropertiesInt64.Add(value); } else { existingValue.Value = value.Value; } } foreach (var value in existingBiota.BiotaPropertiesInt64) { if (!biota.BiotaPropertiesInt64.Any(p => p.Type == value.Type)) { context.BiotaPropertiesInt64.Remove(value); } } foreach (var value in biota.BiotaPropertiesPalette) { BiotaPropertiesPalette existingValue = (value.Id == 0 ? null : existingBiota.BiotaPropertiesPalette.FirstOrDefault(r => r.Id == value.Id)); if (existingValue == null) { existingBiota.BiotaPropertiesPalette.Add(value); } else { existingValue.SubPaletteId = value.SubPaletteId; existingValue.Offset = value.Offset; existingValue.Length = value.Length; } } foreach (var value in existingBiota.BiotaPropertiesPalette) { if (!biota.BiotaPropertiesPalette.Any(p => p.Id == value.Id)) { context.BiotaPropertiesPalette.Remove(value); } } foreach (var value in biota.BiotaPropertiesPosition) { BiotaPropertiesPosition existingValue = existingBiota.BiotaPropertiesPosition.FirstOrDefault(r => r.PositionType == value.PositionType); if (existingValue == null) { existingBiota.BiotaPropertiesPosition.Add(value); } else { existingValue.ObjCellId = value.ObjCellId; existingValue.OriginX = value.OriginX; existingValue.OriginY = value.OriginY; existingValue.OriginZ = value.OriginZ; existingValue.AnglesW = value.AnglesW; existingValue.AnglesX = value.AnglesX; existingValue.AnglesY = value.AnglesY; existingValue.AnglesZ = value.AnglesZ; } } foreach (var value in existingBiota.BiotaPropertiesPosition) { if (!biota.BiotaPropertiesPosition.Any(p => p.PositionType == value.PositionType)) { context.BiotaPropertiesPosition.Remove(value); } } foreach (var value in biota.BiotaPropertiesSkill) { BiotaPropertiesSkill existingValue = existingBiota.BiotaPropertiesSkill.FirstOrDefault(r => r.Type == value.Type); if (existingValue == null) { existingBiota.BiotaPropertiesSkill.Add(value); } else { existingValue.LevelFromPP = value.LevelFromPP; existingValue.SAC = value.SAC; existingValue.PP = value.PP; existingValue.InitLevel = value.InitLevel; existingValue.ResistanceAtLastCheck = value.ResistanceAtLastCheck; existingValue.LastUsedTime = value.LastUsedTime; } } foreach (var value in existingBiota.BiotaPropertiesSkill) { if (!biota.BiotaPropertiesSkill.Any(p => p.Type == value.Type)) { context.BiotaPropertiesSkill.Remove(value); } } foreach (var value in biota.BiotaPropertiesSpellBook) { BiotaPropertiesSpellBook existingValue = existingBiota.BiotaPropertiesSpellBook.FirstOrDefault(r => r.Spell == value.Spell); if (existingValue == null) { existingBiota.BiotaPropertiesSpellBook.Add(value); } else { existingValue.Probability = value.Probability; } } foreach (var value in existingBiota.BiotaPropertiesSpellBook) { if (!biota.BiotaPropertiesSpellBook.Any(p => p.Spell == value.Spell)) { context.BiotaPropertiesSpellBook.Remove(value); } } foreach (var value in biota.BiotaPropertiesString) { BiotaPropertiesString existingValue = existingBiota.BiotaPropertiesString.FirstOrDefault(r => r.Type == value.Type); if (existingValue == null) { existingBiota.BiotaPropertiesString.Add(value); } else { existingValue.Value = value.Value; } } foreach (var value in existingBiota.BiotaPropertiesString) { if (!biota.BiotaPropertiesString.Any(p => p.Type == value.Type)) { context.BiotaPropertiesString.Remove(value); } } foreach (var value in biota.BiotaPropertiesTextureMap) { BiotaPropertiesTextureMap existingValue = (value.Id == 0 ? null : existingBiota.BiotaPropertiesTextureMap.FirstOrDefault(r => r.Id == value.Id)); if (existingValue == null) { existingBiota.BiotaPropertiesTextureMap.Add(value); } else { existingValue.Index = value.Index; existingValue.OldId = value.OldId; existingValue.NewId = value.NewId; existingValue.Order = value.Order; } } foreach (var value in existingBiota.BiotaPropertiesTextureMap) { if (!biota.BiotaPropertiesTextureMap.Any(p => p.Id == value.Id)) { context.BiotaPropertiesTextureMap.Remove(value); } } foreach (var value in biota.HousePermission) { HousePermission existingValue = existingBiota.HousePermission.FirstOrDefault(r => r.HouseId == value.HouseId && r.PlayerGuid == value.PlayerGuid); if (existingValue == null) { existingBiota.HousePermission.Add(value); } else { existingValue.Storage = value.Storage; } } foreach (var value in existingBiota.HousePermission) { if (!biota.HousePermission.Any(p => p.HouseId == value.HouseId && p.PlayerGuid == value.PlayerGuid)) { context.HousePermission.Remove(value); } } }
/// <summary> /// Restore a WorldObject from the database. /// </summary> public Chest(Biota biota) : base(biota) { SetEphemeralValues(); }
public override bool RemoveBiota(Biota biota, ReaderWriterLockSlim rwLock) { if (BiotaContexts.TryGetValue(biota, out var cachedContext)) { BiotaContexts.Remove(biota); rwLock.EnterReadLock(); try { cachedContext.Biota.Remove(biota); Exception firstException = null; retry: try { cachedContext.SaveChanges(); if (firstException != null) { log.Debug($"[DATABASE] RemoveBiota 0x{biota.Id:X8}:{biota.GetProperty(PropertyString.Name)} retry succeeded after initial exception of: {firstException.GetFullMessage()}"); } return(true); } catch (Exception ex) { if (firstException == null) { firstException = ex; goto retry; } // Character name might be in use or some other fault log.Error($"[DATABASE] RemoveBiota 0x{biota.Id:X8}:{biota.GetProperty(PropertyString.Name)} failed first attempt with exception: {firstException}"); log.Error($"[DATABASE] RemoveBiota 0x{biota.Id:X8}:{biota.GetProperty(PropertyString.Name)} failed second attempt with exception: {ex}"); return(false); } } finally { rwLock.ExitReadLock(); cachedContext.Dispose(); } } if (!ObjectGuid.IsPlayer(biota.Id)) { using (var context = new ShardDbContext()) { var existingBiota = context.Biota .AsNoTracking() .FirstOrDefault(r => r.Id == biota.Id); if (existingBiota == null) { return(true); } rwLock.EnterWriteLock(); try { context.Biota.Remove(existingBiota); Exception firstException = null; retry: try { context.SaveChanges(); if (firstException != null) { log.Debug($"[DATABASE] RemoveBiota 0x{biota.Id:X8}:{biota.GetProperty(PropertyString.Name)} retry succeeded after initial exception of: {firstException.GetFullMessage()}"); } return(true); } catch (Exception ex) { if (firstException == null) { firstException = ex; goto retry; } // Character name might be in use or some other fault log.Error($"[DATABASE] RemoveBiota 0x{biota.Id:X8}:{biota.GetProperty(PropertyString.Name)} failed first attempt with exception: {firstException}"); log.Error($"[DATABASE] RemoveBiota 0x{biota.Id:X8}:{biota.GetProperty(PropertyString.Name)} failed second attempt with exception: {ex}"); return(false); } } finally { rwLock.ExitWriteLock(); } } } // If we got here, the biota didn't come from the database through this class. // Most likely, it doesn't exist in the database, so, no need to remove. return(true); }
/// <summary> /// Restore a WorldObject from the database. /// </summary> public GamePiece(Biota biota) : base(biota) { SetEphemeralValues(); }