Exemple #1
0
        public static async Task <Player> Instantiate(IRakConnection connection, Zone zone, ObjectId id)
        {
            // Set up a cancellation token for the connection disconnecting.
            // This may happen before the object starts.
            var cancellationToken = new CancellationTokenSource();

            connection.Disconnected += (disconnectionReason) =>
            {
                cancellationToken.Cancel();
                return(Task.CompletedTask);
            };

            // Create base game object
            var instance = Instantiate <Player>(
                zone,
                position: zone.SpawnPosition,
                rotation: zone.SpawnRotation,
                scale: 1,
                objectId: id,
                lot: 1
                );

            await instance.LoadAsync(connection, cancellationToken.Token);

            return(instance);
        }
Exemple #2
0
        public async Task RenameCharacter(CharacterRenameRequest packet, IRakConnection connection)
        {
            var session = UchuServer.SessionCache.GetSession(connection.EndPoint);

            await using var ctx = new UchuContext();

            // Check if the name already exists and return proper response if so
            if (ctx.Characters.Any(c => c.Name == packet.Name || c.CustomName == packet.Name))
            {
                connection.Send(new CharacterRenameResponse
                {
                    ResponseId = CharacterRenamingResponse.NameAlreadyInUse
                }
                                );

                return;
            }

            // If the name is free, update accordingly and notify the client
            var chr = await ctx.Characters.FindAsync(packet.CharacterId);

            chr.CustomName   = packet.Name;
            chr.NameRejected = false;
            chr.LastActivity = DateTimeOffset.Now.ToUnixTimeSeconds();

            await ctx.SaveChangesAsync();

            connection.Send(new CharacterRenameResponse
            {
                ResponseId = CharacterRenamingResponse.Success
            }
                            );

            await SendCharacterList(connection, session.UserId);
        }
        public static void Send(this IRakConnection @this, ISerializable serializable)
        {
            if (@this == null)
            {
                throw new ArgumentNullException(nameof(@this),
                                                ResourceStrings.RakConnectionExtensions_Send_ConnectionNullException);
            }
            if (serializable == null)
            {
                throw new ArgumentNullException(nameof(serializable),
                                                ResourceStrings.RakConnectionExtensions_Send_StreamNullException);
            }
            Logger.Debug($"Sending {serializable}");

            using var stream = new MemoryStream();
            using var writer = new BitWriter(stream);

            writer.Write(serializable);

            try
            {
                @this.Send(stream.ToArray());
            }
            catch (IOException e)
            {
                Logger.Error(e);
            }
        }
Exemple #4
0
        public async Task RenameCharacter(CharacterRenameRequest packet, IRakConnection connection)
        {
            var session = Server.SessionCache.GetSession(connection.EndPoint);

            await using var ctx = new UchuContext();

            if (ctx.Characters.Any(c => c.Name == packet.Name || c.CustomName == packet.Name))
            {
                connection.Send(new CharacterRenameResponse
                {
                    ResponseId = CharacterRenamingResponse.NameAlreadyInUse
                }
                                );

                return;
            }

            var chr = await ctx.Characters.FindAsync(packet.CharacterId);

            chr.CustomName   = packet.Name;
            chr.NameRejected = false;
            chr.LastActivity = DateTimeOffset.Now.ToUnixTimeSeconds();

            await ctx.SaveChangesAsync();

            connection.Send(new CharacterRenameResponse
            {
                ResponseId = CharacterRenamingResponse.Success
            }
                            );

            await SendCharacterList(connection, session.UserId);
        }
Exemple #5
0
        public async Task JoinWorld(JoinWorldRequest packet, IRakConnection connection)
        {
            UchuServer.SessionCache.SetCharacter(connection.EndPoint, packet.CharacterId);

            await using var ctx = new UchuContext();
            var character = await ctx.Characters.FirstAsync(c => c.Id == packet.CharacterId);

            character.LastActivity = DateTimeOffset.Now.ToUnixTimeSeconds();
            await ctx.SaveChangesAsync();

            var zone        = (ZoneId)character.LastZone;
            var requestZone = (ZoneId)(zone == 0 ? 1000 : zone);

            // We don't want to lock up the server on a world server request, as it may take time.
            var _ = Task.Run(async() =>
            {
                // Request world server.
                var server = await ServerHelper.RequestWorldServerAsync(UchuServer, requestZone);
                if (server == default)
                {
                    // If there's no server available, error
                    var session = UchuServer.SessionCache.GetSession(connection.EndPoint);
                    await SendCharacterList(connection, session.UserId);

                    return;
                }

                // Send to world server.
                connection.Send(new ServerRedirectionPacket
                {
                    Address = UchuServer.Host,
                    Port    = (ushort)server.Port
                });
            });
        }
        public async Task ClientLoadCompleteHandler(ClientLoadCompletePacket packet, IRakConnection connection)
        {
            Logger.Information($"{connection.EndPoint}'s client load completed...");

            var session = UchuServer.SessionCache.GetSession(connection.EndPoint);

            await using var ctx = new UchuContext();
            var character = await ctx.Characters
                            .Include(c => c.Flags)
                            .Include(c => c.Items)
                            .Include(c => c.User)
                            .Include(c => c.Missions)
                            .ThenInclude(m => m.Tasks)
                            .ThenInclude(m => m.Values)
                            .SingleAsync(c => c.Id == session.CharacterId);

            var zoneId = (ZoneId)character.LastZone;

            if (zoneId == 0)
            {
                zoneId = 1000;

                character.LastZone = zoneId;

                await ctx.SaveChangesAsync();
            }

            Logger.Information("[55%] Setting session zone.");
            UchuServer.SessionCache.SetZone(connection.EndPoint, zoneId);

            // Zone should already be initialized at this point.
            Logger.Information("[55%] Getting zone from worldserver.");
            var zone = await((WorldUchuServer)UchuServer).GetZoneAsync(zoneId);

            // Send the character init XML data for this world to the client
            Logger.Information("[55%] Sending XML client info.");
            await SendCharacterXmlDataToClient(character, connection, session);

            Logger.Information("[55%] Constructing player.");
            var player = await Player.ConstructAsync(character, connection, zone);

            Logger.Information("[55%] Checking rocket landing conditions.");
            if (character.LandingByRocket)
            {
                Logger.Information("[55%] Player landed by rocket, saving changes.");
                character.LandingByRocket = false;
                await ctx.SaveChangesAsync();
            }

            Logger.Information("[55%] Player is ready to join world.");
            player.Message(new PlayerReadyMessage {
                Associate = player
            });

            Logger.Information("[55%] Server is done loading object.");
            player.Message(new DoneLoadingObjectsMessage {
                Associate = player
            });
        }
Exemple #7
0
 public static Player FindPlayer(this UchuServer @this, IRakConnection connection)
 {
     if (connection == null)
     {
         return(null);
     }
     return(((WorldUchuServer)@this).Zones.SelectMany(z => z.Players).FirstOrDefault(
                player => player.Connection.EndPoint.Equals(connection.EndPoint)
                ));
 }
        public static void Send(this IRakConnection @this, ISerializable serializable)
        {
            Logger.Information($"Sending {serializable}");

            using var stream = new MemoryStream();
            using var writer = new BitWriter(stream);

            writer.Write(serializable);

            @this.Send(stream.ToArray());
        }
Exemple #9
0
        public async Task ValidateClientHandler(SessionInfoPacket packet, IRakConnection connection)
        {
            Logger.Information($"{connection.EndPoint}'s validating client for world!");

            if (!Server.SessionCache.IsKey(packet.SessionKey))
            {
                await connection.CloseAsync();

                Logger.Warning($"{connection} attempted to connect with an invalid session key");
                return;
            }

            Server.SessionCache.RegisterKey(connection.EndPoint, packet.SessionKey);
            var session = Server.SessionCache.GetSession(connection.EndPoint);

            await using var ctx = new UchuContext();

            // Try to find the player, disconnect if the player is invalid
            var character = await ctx.Characters.FindAsync(session.CharacterId);

            if (character == null)
            {
                Logger.Warning(
                    $"{connection} attempted to connect to world with an invalid character {session.CharacterId}"
                    );

                connection.Send(new DisconnectNotifyPacket
                {
                    DisconnectId = DisconnectId.CharacterNotFound
                });

                return;
            }

            // Initialize zone for player
            var zoneId = (ZoneId)character.LastZone;

            if (zoneId == ZoneId.VentureExplorerCinematic)
            {
                zoneId = ZoneId.VentureExplorer;
            }

            var worldServer = (WorldServer)Server;
            var zone        = await worldServer.GetZoneAsync(zoneId);

            Server.SessionCache.SetZone(connection.EndPoint, zoneId);

            connection.Send(new WorldInfoPacket
            {
                ZoneId        = zoneId,
                Checksum      = zone.Checksum,
                SpawnPosition = zone.ZoneInfo.LuzFile.SpawnPoint
            });
        }
Exemple #10
0
        public void ValidateClient(SessionInfoPacket packet, IRakConnection connection)
        {
            if (!Server.SessionCache.IsKey(packet.SessionKey))
            {
                Task.Run(connection.CloseAsync);
                Logger.Warning($"{connection} attempted to connect with an invalid session key");
                return;
            }

            Server.SessionCache.RegisterKey(connection.EndPoint, packet.SessionKey);
        }
Exemple #11
0
        public async Task ValidateClient(SessionInfoPacket packet, IRakConnection connection)
        {
            if (packet == null)
            {
                throw new ArgumentNullException(nameof(packet),
                                                ResourceStrings.ClientHandler_ValidateClient_PacketNullException);
            }

            await UchuServer.ValidateUserAsync(connection, packet.Username, packet.SessionKey)
            .ConfigureAwait(false);
        }
Exemple #12
0
        private static async Task SendCharacterList(IRakConnection connection, long userId)
        {
            await using var ctx = new UchuContext();

            var user = await ctx.Users.Include(u => u.Characters).ThenInclude(c => c.Items)
                       .SingleAsync(u => u.UserId == userId);

            var charCount = user.Characters.Count;
            var chars     = new CharacterListResponse.Character[charCount];

            user.Characters.Sort((u2, u1) =>
                                 DateTimeOffset.Compare(DateTimeOffset.FromUnixTimeSeconds(u1.LastActivity),
                                                        DateTimeOffset.FromUnixTimeSeconds(u2.LastActivity)));

            for (var i = 0; i < charCount; i++)
            {
                var chr = user.Characters[i];

                var items = chr.Items.Where(itm => itm.IsEquipped).Select(itm => (uint)itm.LOT).ToArray();
                chars[i] = new CharacterListResponse.Character
                {
                    CharacterId    = chr.CharacterId,
                    Name           = chr.Name,
                    UnnaprovedName = chr.CustomName,
                    NameRejected   = chr.NameRejected,
                    FreeToPlay     = chr.FreeToPlay,
                    ShirtColor     = (uint)chr.ShirtColor,
                    ShirtStyle     = (uint)chr.ShirtStyle,
                    PantsColor     = (uint)chr.PantsColor,
                    HairStyle      = (uint)chr.HairStyle,
                    HairColor      = (uint)chr.HairColor,
                    Lh             = (uint)chr.Lh,
                    Rh             = (uint)chr.Rh,
                    EyebrowStyle   = (uint)chr.EyebrowStyle,
                    EyeStyle       = (uint)chr.EyeStyle,
                    MouthStyle     = (uint)chr.MouthStyle,
                    LastZone       = (ZoneId)chr.LastZone,
                    LastInstance   = (ushort)chr.LastInstance,
                    LastClone      = (uint)chr.LastClone,
                    LastActivity   = (ulong)chr.LastActivity,
                    ItemCount      = (ushort)items.Length,
                    Items          = items
                };
            }

            connection.Send(new CharacterListResponse
            {
                CharacterCount = (byte)charCount,
                CharacterIndex = (byte)user.CharacterIndex,
                Characters     = chars
            });

            Logger.Debug($"Sent character list to {connection}");
        }
        public async Task ValidateClientHandler(SessionInfoPacket packet, IRakConnection connection)
        {
            Logger.Information($"{connection.EndPoint}'s validating client for world!");

            var verified = await UchuServer.ValidateUserAsync(connection, packet.Username, packet.SessionKey);

            if (!verified)
            {
                return;
            }

            var session = UchuServer.SessionCache.GetSession(connection.EndPoint);

            await using var ctx = new UchuContext();

            // Try to find the player, disconnect if the player is invalid
            var character = await ctx.Characters.FindAsync(session.CharacterId);

            if (character == null)
            {
                Logger.Warning(
                    $"{connection} attempted to connect to world with an invalid character {session.CharacterId}"
                    );

                connection.Send(new DisconnectNotifyPacket
                {
                    DisconnectId = DisconnectId.CharacterNotFound
                });

                return;
            }

            // Initialize zone for player
            var zoneId = (ZoneId)character.LastZone;

            if (zoneId == 0)
            {
                zoneId = 1000;
            }

            var worldServer = (WorldUchuServer)UchuServer;
            var zone        = await worldServer.GetZoneAsync(zoneId);

            UchuServer.SessionCache.SetZone(connection.EndPoint, zoneId);

            connection.Send(new WorldInfoPacket
            {
                ZoneId        = zoneId,
                Checksum      = zone.Checksum,
                SpawnPosition = zone.SpawnPosition
            });
        }
Exemple #14
0
        public async Task JoinWorld(JoinWorldRequest packet, IRakConnection connection)
        {
            Server.SessionCache.SetCharacter(connection.EndPoint, packet.CharacterId);

            await using var ctx = new UchuContext();

            var character = await ctx.Characters.FirstAsync(c => c.CharacterId == packet.CharacterId);

            character.LastActivity = DateTimeOffset.Now.ToUnixTimeSeconds();

            await ctx.SaveChangesAsync();

            var zone = (ZoneId)character.LastZone;

            var requestZone = zone == ZoneId.VentureExplorerCinematic ? ZoneId.VentureExplorer : zone;

            //
            // We don't want to lock up the server on a world server request, as it may take time.
            //

            var _ = Task.Run(async() =>
            {
                //
                // Request world server.
                //

                var server = await ServerHelper.RequestWorldServerAsync(requestZone);

                if (server == default)
                {
                    //
                    // Error
                    //

                    var session = Server.SessionCache.GetSession(connection.EndPoint);

                    await SendCharacterList(connection, session.UserId);

                    return;
                }

                //
                // Send to world server.
                //

                connection.Send(new ServerRedirectionPacket
                {
                    Address = Server.GetHost(),
                    Port    = (ushort)server.Port
                });
            });
        }
        public static void Send(this IRakConnection @this, MemoryStream stream)
        {
            if (@this == null)
            {
                throw new ArgumentNullException(nameof(@this),
                                                ResourceStrings.RakConnectionExtensions_Send_ConnectionNullException);
            }
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream),
                                                ResourceStrings.RakConnectionExtensions_Send_StreamNullException);
            }

            @this.Send(stream.ToArray());
        }
        public void Handshake(HandshakePacket packet, IRakConnection connection)
        {
            if (packet.GameVersion != 171022)
            {
                Logger.Warning($"Handshake attempted with client of Game version: {packet.GameVersion}");
                return;
            }

            const int port = 21836;

            connection.Send(new HandshakePacket
            {
                ConnectionType = Server.Port == port ? 0x01u : 0x04u,
                Address        = Server.GetHost()
            });
        }
        /// <summary>
        /// Sends the character initialization packet for a character to the current connection
        /// </summary>
        /// <param name="character">The character to generate the initialization data for</param>
        /// <param name="connection">The connection to send the initialization data to</param>
        /// <param name="session">The session cache for the connection</param>
        private async Task SendCharacterXmlDataToClient(Character character, IRakConnection connection, Session session)
        {
            // Get the XML data for this character for the initial character packet
            var xmlData = GenerateCharacterXmlData(character);

            await using var ms     = new MemoryStream();
            await using var writer = new StreamWriter(ms, Encoding.UTF8);
            Serializer.Serialize(writer, xmlData);

            var bytes = ms.ToArray();
            var xml   = new byte[bytes.Length - 3];

            Buffer.BlockCopy(bytes, 3, xml, 0, bytes.Length - 3);

            var ldf = new LegoDataDictionary
            {
Exemple #18
0
        public async Task ClientMailPacketHandler(ClientMailPacket packet, IRakConnection connection)
        {
            var player = UchuServer.FindPlayer(connection);

            if (player == default)
            {
                Logger.Error($"Could not find player for: {connection}");
                return;
            }

            switch (packet.Id)
            {
            case ClientMailPacketId.Send:
                await SendHandler(packet.MailStruct as MailSend, player);

                break;

            case ClientMailPacketId.DataRequest:
                await DataRequestHandler(player);

                break;

            case ClientMailPacketId.AttachmentCollected:
                await AttachmentCollectHandler(packet.MailStruct as MailAttachmentCollected, player);

                break;

            case ClientMailPacketId.Delete:
                await DeleteHandler(packet.MailStruct as MailDelete, player);

                break;

            case ClientMailPacketId.Read:
                await ReadHandler(packet.MailStruct as MailRead, player);

                break;

            case ClientMailPacketId.NotificationRequest:
                await NotificationRequestHandler(player);

                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
Exemple #19
0
        public async Task CharacterList(CharacterListRequest packet, IRakConnection connection)
        {
            // Remove the player from the zone.
            var session = UchuServer.SessionCache.GetSession(connection.EndPoint);

            if (UchuServer is WorldUchuServer worldUchuServer)
            {
                var player = worldUchuServer.FindPlayer(connection);
                if (player != null)
                {
                    await player.DestroyAsync();
                }
            }

            // Send the character list.
            await SendCharacterList(connection, session.UserId);
        }
Exemple #20
0
        public void FriendsListRequestHandler(GetFriendListPacket packet, IRakConnection connection)
        {
            var session = Server.SessionCache.GetSession(connection.EndPoint);
            var zone    = ((WorldServer)Server).Zones.FirstOrDefault(z => (int)z.ZoneId == session.ZoneId);

            if (zone == default)
            {
                Logger.Error($"Invalid ZoneId for {connection}");
                return;
            }

            using var ctx = new UchuContext();
            var character = ctx.Characters.First(c => c.CharacterId == session.CharacterId);

            var relations = ctx.Friends.Where(f =>
                                              f.FriendId == character.CharacterId || f.FriendTwoId == character.CharacterId
                                              ).ToArray();

            var friends = new List <FriendListPacket.Friend>();

            foreach (var characterFriend in relations)
            {
                if (!characterFriend.IsAccepted)
                {
                    continue;
                }

                var friendId = characterFriend.FriendTwoId == character.CharacterId
                    ? characterFriend.FriendId
                    : characterFriend.FriendTwoId;

                var friend = ctx.Characters.First(c => c.CharacterId == friendId);

                var player = zone.Players.FirstOrDefault(p => p.ObjectId == friend.CharacterId);
                friends.Add(new FriendListPacket.Friend
                {
                    IsBestFriend  = characterFriend.IsBestFriend,
                    IsFreeToPlay  = friend.FreeToPlay,
                    IsOnline      = player != default,
                    PlayerId      = player?.ObjectId ?? -1,
                    PlayerName    = friend.Name,
                    ZoneId        = (ZoneId)friend.LastZone,
                    WorldClone    = (uint)friend.LastClone,
                    WorldInstance = (ushort)friend.LastInstance
                });
        /// <summary>
        /// Sends a struct (packet) to a given connection.
        /// </summary>
        /// <param name="this">RakNet connection to send over.</param>
        /// <param name="packet">Packet to send.</param>
        /// <typeparam name="T">Type of the packet.</typeparam>
        /// <exception cref="ArgumentNullException">Connection is null.</exception>
        public static void Send <T>(this IRakConnection @this, T packet) where T : struct
        {
            if (@this == null)
            {
                throw new ArgumentNullException(nameof(@this),
                                                ResourceStrings.RakConnectionExtensions_Send_ConnectionNullException);
            }
            Logger.Debug($"Sending {packet}");

            try
            {
                @this.Send(StructPacketParser.WritePacket(packet).ToArray());
            }
            catch (IOException e)
            {
                Logger.Error(e);
            }
        }
        public async Task PositionHandler(PositionUpdatePacket packet, IRakConnection connection)
        {
            var player = Server.FindPlayer(connection);

            if (player?.Transform == default)
            {
                Logger.Warning($"{connection} is not logged in but sent a Position Update packet.");
                return;
            }

            //
            // The server is a slave to the position update packets it gets from the client right now.
            //

            player.Transform.Position = packet.Position;
            player.Transform.Rotation = packet.Rotation;

            var physics = player.GetComponent <ControllablePhysicsComponent>();

            physics.HasPosition = true;

            physics.IsOnGround = packet.IsOnGround;
            physics.NegativeAngularVelocity = packet.NegativeAngularVelocity;

            physics.HasVelocity = packet.HasVelocity;

            physics.Velocity = packet.Velocity;

            physics.HasAngularVelocity = packet.HasAngularVelocity;

            physics.AngularVelocity = packet.AngularVelocity;

            physics.Platform = default; //player.Zone.GameObjects.FirstOrDefault(g => g.ObjectId == packet.PlatformObjectId);

            physics.PlatformPosition = packet.PlatformPosition;

            Zone.SendSerialization(player, player.Zone.Players.Where(
                                       p => p != player
                                       ).ToArray());

            player.UpdateView();

            await player.OnPositionUpdate.InvokeAsync(packet.Position, packet.Rotation);
        }
Exemple #23
0
        public async Task DeleteCharacter(CharacterDeleteRequest packet, IRakConnection connection)
        {
            await using var ctx = new UchuContext();

            try
            {
                ctx.Characters.Remove(await ctx.Characters.FindAsync(packet.CharacterId));
                await ctx.SaveChangesAsync();

                connection.Send(new CharacterDeleteResponse());
            }
            catch (Exception e)
            {
                Logger.Error($"Character deletion failed for {connection}'s character {packet.CharacterId}\n{e}");
                connection.Send(new CharacterDeleteResponse {
                    Success = false
                });
            }
        }
Exemple #24
0
        public void Handshake(HandshakePacket packet, IRakConnection connection)
        {
            if (packet == null)
            {
                throw new ArgumentNullException(nameof(packet),
                                                ResourceStrings.GeneralHandler_Handshake_PacketNullException);
            }

            if (packet.GameVersion != 171022)
            {
                Logger.Warning($"Handshake attempted with client of Game version: {packet.GameVersion}");
            }

            connection.Send(new HandshakePacket
            {
                ConnectionType = UchuServer.Port == UchuServer.Config.Networking.AuthenticationPort ? 0x01u : 0x04u,
                Address        = UchuServer.Host
            });
        }
Exemple #25
0
        public void AddConnection(IRakConnection connection)
        {
            if (!_connections.TryAdd(connection.EndPoint, connection))
            {
                return;
            }

            foreach (var replica in _replicas.Keys)
            {
                SendConstruction(replica, false, new[] { connection.EndPoint });
            }

            connection.Disconnected += reason =>
            {
                _connections.TryRemove(connection.EndPoint, out _);

                return(Task.CompletedTask);
            };
        }
Exemple #26
0
        public async Task FriendsListRequestHandler(GetFriendListPacket packet, IRakConnection connection)
        {
            var session = UchuServer.SessionCache.GetSession(connection.EndPoint);
            var zone    = ((WorldUchuServer)UchuServer).Zones.FirstOrDefault(z => (int)z.ZoneId == session.ZoneId);

            if (zone == default)
            {
                Logger.Error($"Invalid ZoneId for {connection}");
                return;
            }

            await using var ctx = new UchuContext();
            var character = await ctx.Characters.FirstAsync(c => c.Id == session.CharacterId);

            var relations = await ctx.Friends.Where(f =>
                                                    f.FriendA == character.Id || f.FriendB == character.Id
                                                    ).ToArrayAsync();

            var friends = new List <FriendListPacket.Friend>();

            foreach (var characterFriend in relations)
            {
                var friendId = characterFriend.FriendA == character.Id
                    ? characterFriend.FriendB
                    : characterFriend.FriendA;

                var friend = ctx.Characters.First(c => c.Id == friendId);

                var player = zone.Players.FirstOrDefault(p => p.Id == friend.Id);

                friends.Add(new FriendListPacket.Friend
                {
                    IsBestFriend  = characterFriend.BestFriend,
                    IsFreeToPlay  = friend.FreeToPlay,
                    IsOnline      = player != default,
                    PlayerId      = player?.Id ?? -1,
                    PlayerName    = friend.Name,
                    ZoneId        = (ZoneId)friend.LastZone,
                    WorldClone    = (uint)friend.LastClone,
                    WorldInstance = (ushort)friend.LastInstance
                });
Exemple #27
0
        public async Task PositionHandler(PositionUpdatePacket packet, IRakConnection connection)
        {
            var player = UchuServer.FindPlayer(connection);

            if (player?.Transform == default)
            {
                return;
            }

            // The server is a slave to the position update packets it gets from the client right now.
            player.Transform.Position = packet.Position;
            player.Transform.Rotation = packet.Rotation;

            var physics = player.GetComponent <ControllablePhysicsComponent>();

            physics.HasPosition = true;

            physics.IsOnGround = packet.IsOnGround;
            physics.NegativeAngularVelocity = packet.NegativeAngularVelocity;

            physics.HasVelocity = (packet.Velocity != Vector3.Zero);

            physics.Velocity = packet.Velocity;

            physics.HasAngularVelocity = (packet.AngularVelocity != Vector3.Zero);

            physics.AngularVelocity = packet.AngularVelocity;

            physics.Platform = packet.PlatformObjectId;

            physics.PlatformPosition = packet.PlatformPosition;

            Zone.SendSerialization(player, player.Zone.Players.Where(
                                       p => p != player
                                       ).ToArray());

            player.UpdateView();

            await player.OnPositionUpdate.InvokeAsync(packet.Position, packet.Rotation);
        }
Exemple #28
0
        public void Handshake(HandshakePacket packet, IRakConnection connection)
        {
            if (packet == null)
            {
                throw new ArgumentNullException(nameof(packet),
                                                ResourceStrings.GeneralHandler_Handshake_PacketNullException);
            }

            if (packet.GameVersion != 171022)
            {
                Logger.Warning($"Handshake attempted with client of Game version: {packet.GameVersion}");
            }

            // TODO: Use resource / setting
            const int port = 21836;

            connection.Send(new HandshakePacket
            {
                ConnectionType = UchuServer.Port == port ? 0x01u : 0x04u,
                Address        = UchuServer.Host
            });
        }
        public async Task AddFriendRequestHandler(AddFriendRequestPacket packet, IRakConnection connection)
        {
            var session = Server.SessionCache.GetSession(connection.EndPoint);
            var zone    = ((WorldServer)Server).Zones.FirstOrDefault(z => z.ZoneId == session.ZoneId);

            if (zone == default)
            {
                Logger.Error($"Invalid ZoneId for {connection}");
                return;
            }

            var player = zone.Players.First(p => p.Connection.Equals(connection));

            await using var ctx = new UchuContext();

            var friend = await ctx.Characters.FirstOrDefaultAsync(c => c.Name == packet.PlayerName);

            if (friend == default)
            {
                Logger.Information(
                    $"{player.Name} is trying to be friends with a none existent player {packet.PlayerName}"
                    );

                player.Message(new NotifyFriendRequestResponsePacket
                {
                    PlayerName = packet.PlayerName,
                    Response   = ServerFriendRequestResponse.InvalidName
                });

                return;
            }

            var character = ctx.Characters.First(c => c.Id == session.CharacterId);

            var alreadyFriends = await ctx.Friends.Where(f =>
                                                         f.FriendA == character.Id || f.FriendB == character.Id
                                                         ).AnyAsync();

            if (alreadyFriends)
            {
                player.Message(new NotifyFriendRequestResponsePacket
                {
                    PlayerName = packet.PlayerName,
                    Response   = ServerFriendRequestResponse.AlreadyFriends
                });

                return;
            }

            var isPending = await ctx.FriendRequests.Where(f =>
                                                           f.Sender == character.Id && f.Receiver == friend.Id
                                                           ).AnyAsync();

            if (isPending)
            {
                player.Message(new NotifyFriendRequestResponsePacket
                {
                    PlayerName = packet.PlayerName,
                    Response   = ServerFriendRequestResponse.PendingApproval
                });

                return;
            }

            var request = new FriendRequest
            {
                Sender     = character.Id,
                Receiver   = friend.Id,
                BestFriend = packet.IsRequestingBestFriend
            };

            await ctx.FriendRequests.AddAsync(request);
        }
Exemple #30
0
        public async Task LoginRequestHandler(ClientLoginInfoPacket packet, IRakConnection connection)
        {
            await using var ctx = new UchuContext();

            var info = new ServerLoginInfoPacket
            {
                CharacterInstanceAddress = Server.GetHost(),
                CharacterInstancePort    = ushort.MaxValue,
                ChatInstanceAddress      = Server.GetHost(),
                ChatInstancePort         = 2004
            };

            var characterSpecification = await ServerHelper.GetServerByType(ServerType.Character);

            if (characterSpecification == default)
            {
                info.LoginCode = LoginCode.InsufficientPermissions;
                info.Error     = new ServerLoginInfoPacket.ErrorMessage
                {
                    Message = "No character server instance is running. Please try again later."
                };
            }
            else
            {
                info.CharacterInstancePort = (ushort)characterSpecification.Port;

                if (!await ctx.Users.AnyAsync(u => u.Username == packet.Username))
                {
                    info.LoginCode = LoginCode.InsufficientPermissions;
                    info.Error     = new ServerLoginInfoPacket.ErrorMessage
                    {
                        Message = "We have no records of that Username and Password combination. Please try again."
                    };
                }
                else
                {
                    var user = await ctx.Users.SingleAsync(u => u.Username == packet.Username);

                    if (user != null && BCrypt.Net.BCrypt.EnhancedVerify(packet.Password, user.Password))
                    {
                        if (user.Banned)
                        {
                            info.LoginCode = LoginCode.InsufficientPermissions;
                            info.Error     = new ServerLoginInfoPacket.ErrorMessage
                            {
                                Message = $"This account has been banned by an admin. Reason:\n{user.BannedReason ?? "Unknown"}"
                            };
                        }
                        else if (!string.IsNullOrWhiteSpace(user.CustomLockout))
                        {
                            info.LoginCode = LoginCode.InsufficientPermissions;
                            info.Error     = new ServerLoginInfoPacket.ErrorMessage
                            {
                                Message = user.CustomLockout
                            };
                        }
                        else
                        {
                            var key = Server.SessionCache.CreateSession(user.UserId);

                            info.LoginCode = LoginCode.Success;
                            info.UserKey   = key;

                            //
                            // I don't intend, nor do I see anyone else, using these.
                            // Except maybe FirstTimeOnSubscription for the fancy screen.
                            //

                            info.FreeToPlay = user.FreeToPlay;
                            info.FirstLoginWithSubscription = user.FirstTimeOnSubscription;

                            //
                            // No longer the first time on subscription
                            //

                            user.FirstTimeOnSubscription = false;

                            await ctx.SaveChangesAsync();
                        }
                    }
                    else
                    {
                        info.LoginCode = LoginCode.InsufficientPermissions;
                        info.Error     = new ServerLoginInfoPacket.ErrorMessage
                        {
                            Message = "We have no records of that Username and Password combination. Please try again."
                        };
                    }
                }
            }

            connection.Send(info);
        }