/// <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>Handles a client zoning from one zone server to another. This is sent from a zone server.</summary> /// <returns>0 = success, 1 = max clients reached, 2 = zone locked, 3 = general fubar error.</returns> public int ZoneToZone(ZoneToZone ztz) { _log.InfoFormat("ZoneToZone request for {0}: current zone is {1}, target zone is {2}", ztz.CharName, ztz.CurrentZoneId, ztz.RequestedZoneId); // TODO: add checks for appropriate ignoring of zone restrictions and the bypass of ExpectNewClient calls this would require // Try to fetch the zone process ZoneProcess zp = GetZoneProcess(ztz.RequestedZoneId); if (zp == null) return 3; // couldn't boot the zone for some reason, check the logs TODO: return different codes for No server free, zone full, etc. int retCode = zp.ZoneService.ExpectNewClient(ztz.CharId, ztz.ClientIp, ztz.IsLocalNet); if (retCode > 0) { _log.ErrorFormat("Attempt to zone to {0} failed with error code {1}", ztz.RequestedZoneId, retCode); return retCode; } _log.InfoFormat("ExpectNewClient successful for zone {0} during a ZoneToZone request", ztz.RequestedZoneId); // Update the who info for this client _authClientsLock.EnterWriteLock(); try { ClientWho cw = _authClients[ztz.ClientIp]; cw.ZoneId = ztz.RequestedZoneId; } catch (Exception e) { _log.Error("Error updating who information.", e); } finally { _authClientsLock.ExitWriteLock(); } _log.DebugFormat("Who info updated for {0}", ztz.CharName); return 0; }