partial void DeleteZone(Zone instance);
partial void UpdateZone(Zone instance);
partial void InsertZone(Zone instance);
/// <summary>Initializes all data for a zone - spawns, zone points, AA, etc.</summary> private bool Init(ushort zoneId, ZoneInstanceType ziType) { // Load the zone along with associated zone points, spawns, spawn groups, spawn group entries and NPCs. // TODO: Probably will want to load this differently when zone state persistance is in (join to a state table for spawns?) DataLoadOptions dlo = new DataLoadOptions(); dlo.LoadWith<Zone>(z => z.ZonePoints); dlo.LoadWith<Zone>(z => z.Doors); dlo.LoadWith<Zone>(z => z.Spawns); dlo.LoadWith<Internals.Data.Spawn>(s => s.SpawnGroup); dlo.LoadWith<SpawnGroup>(sg => sg.SpawnGroupEntries); dlo.AssociateWith<SpawnGroup>(sg => sg.SpawnGroupEntries.OrderBy(sge => sge.Chance)); // sort the spawnGroupEntries by chance dlo.LoadWith<SpawnGroupEntry>(sge => sge.Npc); dlo.LoadWith<Npc>(npc => npc.Loot); dlo.LoadWith<Loot>(l => l.LootEntries); dlo.LoadWith<LootEntry>(le => le.LootDrops); dlo.LoadWith<LootDrop>(ld => ld.Item); // TODO: can we trim how much of an item comes back? using (EmuDataContext dbCtx = new EmuDataContext()) { dbCtx.ObjectTrackingEnabled = false; // only loading referential data dbCtx.LoadOptions = dlo; // TODO: use profiler to make sure we get it all in one call //dbCtx.Log = new Log4NetWriter(typeof(ZoneServer)); _zone = dbCtx.Zones.Single(z => z.ZoneID == zoneId); } this.Zone.InitNewZoneStruct(); _instanceType = ziType; // Load map & water map _map = new Map(); _waterMap = new WaterMap(); try { if (!_map.LoadMapFromFile(_zone.ShortName)) return false; if (!_waterMap.LoadMapFromFile(_zone.ShortName)) _waterMap = null; } catch (Exception e) { _log.Error("Error during map loading", e); } _mobMgr.Init(); // Must be done prior to any doors, mobs or player init if (_zone.Doors.Count > 0) { foreach (Door d in _zone.Doors) d.EntityId = GetNewEntityId(); // Assign each door an entity Id _log.InfoFormat("Loaded {0} doors", _zone.Doors.Count); } else _log.Warn("No doors loaded"); // TODO: Load Spawn Conditions SpawnTimerCallback(null); // Load spawns NOW _log.InfoFormat("Loaded {0} Spawn", _mobMgr.MobCount); // TODO: Implement zone state persistance // TODO: Load corpses // TODO: Load traps // TODO: Load ground spawns // TODO: Load objects (tradeskill containers, maybe books, etc.) _maxSpellId = WorldSvc.GetMaxSpellId(); if (_maxSpellId == 0) _log.Error("Max SpellId equals zero. Problem with spell loading in world?"); // TODO: Load blocked spells // TODO: Load guilds, factions, titles, AA, Tributes, corpse timers? // TODO: Load merchant data // TODO: Load petition data // TODO: Load graveyard // TODO: Load timezone data // TODO: Implement server time keeping in world and then sync up here (see end of orig Init and bootup routines) // Just before we finish, start up the various timers _spawnTimer.Change(30000, SPAWN_TIMER_INTERVAL); // We've already populated the spawn list, so wait a bit _spawnQueueTimer.Change(5000, SPAWN_QUEUE_TIMER_INTERVAL); // wait 5 sec before worrying about queued spawn packets _doorTimer.Change(10000, DOOR_TIMER_INTERVAL); // wait 10 sec before worrying about doors // Initialize weather timer if (_zone.Weather <= 3 && _zone.Weather > 0) { Random rand = new Random(); _weatherTimer.Change(0, (rand.Next(1800, 7200) + 30) * 2000); } return true; }
/// <summary>Called when the client is allowed to zone. Handles all which must happen when a client zones out.</summary> internal void ZoneClient(ZoneChange zc, Zone targetZone, float destX, float destY, float destZ, float destH, byte ignoreRestrictions, Client client) { this.SendLogoutPackets(client); _mobMgr.RemoveFromAllHateLists(client.ZonePlayer); // TODO: clear aggro for pet, if present _log.DebugFormat("{0} is ATTEMPTING to zone to {1} ({2}) {3}x {4}y {5}z", client.ZonePlayer.Name, targetZone.ShortName, targetZone.ZoneID, destX, destY, destZ); ZoneChange zcOut = new ZoneChange(); if (targetZone.ZoneID == this.Zone.ZoneID) { // Zoning to same zone (maybe a bind point, etc.) zcOut.ZoneID = this.Zone.ZoneID; zcOut.Success = (int)ZoneError.Success; client.ZonePlayer.X = destX; client.ZonePlayer.Y = destY; client.ZonePlayer.Z = destZ; client.ZonePlayer.Heading = destH; _log.InfoFormat("{0} is zoning to same zone {1}x {2}y {3}z (no error)", client.ZonePlayer.Name, destX, destY, destZ); AddClientAuth(client.IPEndPoint.Address.ToString(), true); // add to expected clients list } else { // Send a ZTZ to World ZoneToZone ztz = new ZoneToZone(); ztz.CharName = client.ZonePlayer.Name; ztz.CharId = client.ZonePlayer.ID; ztz.ClientIp = client.IPEndPoint.Address.ToString(); ztz.CurrentZoneId = this.Zone.ZoneID; ztz.RequestedZoneId = targetZone.ZoneID; ztz.AccountStatus = client.ZonePlayer.AccountStatus; ztz.IgnoreRestrictions = ignoreRestrictions; int ztzResult = WorldSvc.ZoneToZone(ztz); if (ztzResult > 0) { // problems zcOut.Success = (int)ZoneError.NotReady; client.ZonePlayer.ZoneId = this.Zone.ZoneID; // client isn't zoning after all, so set the id back to this zone _log.InfoFormat("{0} is zoning to same zone {1}x {2}y {3}z due to error code {4} when asking world to zone", client.ZonePlayer.Name, destX, destY, destZ, ztzResult); client.ZonePlayer.MsgMgr.SendSpecialMessage(MessageType.Default, string.Format("There was a problem zoning. Code {0}.", ztzResult)); } else { zcOut.Init(); Buffer.BlockCopy(Encoding.ASCII.GetBytes(client.ZonePlayer.Name), 0, zcOut.CharName, 0, client.ZonePlayer.Name.Length); zcOut.ZoneID = targetZone.ZoneID; zcOut.Success = (int)ZoneError.Success; client.ZonePlayer.X = destX; client.ZonePlayer.Y = destY; client.ZonePlayer.Z = destZ; client.ZonePlayer.Heading = destH; client.ZonePlayer.ZoneId = targetZone.ZoneID; _log.InfoFormat("{0} is zoning to {1} ({2}) {3}x {4}y {5}z", client.ZonePlayer.Name, targetZone.ShortName, targetZone.ZoneID, destX, destY, destZ); // TODO: for ignoreRestrictions of 3, get safe coords for target zone } } client.ZonePlayer.ZoneMode = ZoneMode.Unsolicited; // reset the zoneMode client.ZonePlayer.Save(); // this forced save ensures the correct zone info is available to world when zoning the client EQApplicationPacket<ZoneChange> zcPack = new EQApplicationPacket<ZoneChange>(AppOpCode.ZoneChange, zcOut); client.SendApplicationPacket(zcPack); }
/// <summary>Unloads all data associated with the zone. Used when dynamic zone is shut down.</summary> private void Unload() { _staleAuthRemovalTimer.Change(Timeout.Infinite, Timeout.Infinite); _shutdownTimer.Change(Timeout.Infinite, Timeout.Infinite); _spawnTimer.Change(Timeout.Infinite, Timeout.Infinite); _spawnQueueTimer.Change(Timeout.Infinite, Timeout.Infinite); _weatherTimer.Change(Timeout.Infinite, Timeout.Infinite); _doorTimer.Change(Timeout.Infinite, Timeout.Infinite); _zone = null; _map = null; _waterMap = null; _mobMgr.Clear(); }