private void Connect(ConInfo conInfo) { var client = conInfo.Client; var acc = conInfo.Account; var gameId = conInfo.GameId; if (conInfo.Reconnecting) { ReconInfo rInfo; if (!_recon.TryRemove(acc.AccountId, out rInfo)) { client.SendFailure("Invalid reconnect.", Failure.MessageWithDisconnect); return; } if (!gameId.Equals(rInfo.Destination)) { client.SendFailure("Invalid reconnect destination.", Failure.MessageWithDisconnect); return; } if (!conInfo.Key.SequenceEqual(rInfo.Key)) { client.SendFailure("Invalid reconnect key.", Failure.MessageWithDisconnect); return; } } else { if (gameId != World.Test) { gameId = World.Nexus; } } if (!client.Manager.Database.AcquireLock(acc)) { // disconnect current connected client (if any) var otherClients = client.Manager.Clients.Keys .Where(c => c == client || c.Account != null && (c.Account.AccountId == acc.AccountId)); foreach (var otherClient in otherClients) { otherClient.Disconnect(); } // try again... if (!client.Manager.Database.AcquireLock(acc)) { client.SendFailure("Account in Use (" + client.Manager.Database.GetLockTime(acc)?.ToString("%s") + " seconds until timeout)"); return; } } acc.Reload(); // make sure we have the latest data client.Account = acc; // connect client to realm manager if (!client.Manager.TryConnect(client)) { client.SendFailure("Failed to connect"); return; } var world = client.Manager.GetWorld(gameId); // make test worlds if (gameId == World.Test && acc.Rank >= 50) { world = new Test(); _manager.AddWorld(world); } if (world == null || world.Deleted) { client.SendPacket(new Text() { BubbleTime = 0, NumStars = -1, Name = "*Error*", Txt = "World does not exist." }); world = client.Manager.GetWorld(World.Nexus); } if (world is Test && !(world as Test).JsonLoaded && acc.Rank < 50) //to-do: client.Manager.Resources.Settings.EditorMinRank { client.SendFailure("Only players with a rank of 50 and above can make test maps.", Failure.MessageWithDisconnect); return; } if (world.IsLimbo) { world = world.GetInstance(client); } if (!world.AllowedAccess(client)) { if (!world.Persist && world.TotalConnects <= 0) { client.Manager.RemoveWorld(world); } client.SendPacket(new Text() { BubbleTime = 0, NumStars = -1, Name = "*Error*", Txt = "Access denied" }); if (!(world is Nexus)) { world = client.Manager.GetWorld(World.Nexus); } else { client.Disconnect(); return; } } if (world is Test && !(world as Test).JsonLoaded) { // save map var mapFolder = $"{_manager.Config.serverSettings.logFolder}/maps"; if (!Directory.Exists(mapFolder)) { Directory.CreateDirectory(mapFolder); } File.WriteAllText($"{mapFolder}/{acc.Name}_{DateTime.Now.Ticks}.jm", conInfo.MapInfo); (world as Test).LoadJson(conInfo.MapInfo); var dreamName = client.Account.Name.ToLower().EndsWith("s") ? client.Account.Name + "' Dream World" : client.Account.Name + "'s Dream World"; world.SBName = dreamName; world.Name = dreamName; //client.Manager.Monitor.AddPortal(world.Id); } var seed = (uint)((long)Environment.TickCount * conInfo.GUID.GetHashCode()) % uint.MaxValue; client.Random = new wRandom(seed); client.TargetWorld = world.Id; var now = (Int32)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds; if (acc.GuildId > 0 && now - acc.LastSeen > 1800) { client.Manager.Chat.GuildAnnounce(acc, acc.Name + " has joined the game"); } acc.RefreshLastSeen(); acc.FlushAsync(); // send out map info var mapSize = Math.Max(world.Map.Width, world.Map.Height); client.SendPacket(new MapInfo() { Music = world.Music, Width = mapSize, Height = mapSize, Name = world.Name, DisplayName = world.SBName, Seed = seed, Background = world.Background, Difficulty = world.Difficulty, AllowPlayerTeleport = world.AllowTeleport, ShowDisplays = world.ShowDisplays, }); // send out account lock/ignore list client.SendPacket(new AccountList() { AccountListId = 0, // locked list AccountIds = client.Account.LockList .Select(i => i.ToString()) .ToArray() }); client.SendPacket(new AccountList() { AccountListId = 1, // ignore list AccountIds = client.Account.IgnoreList .Select(i => i.ToString()) .ToArray() }); client.State = ProtocolState.Handshaked; _connecting.TryAdd(client, DateTime.Now.AddSeconds(ConnectingTTL)); }