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));
}