コード例 #1
0
        internal async Task SendPlayerInfoAsync()
        {
            var list = new List <PlayerInfoAction>();

            foreach (Player player in this.Server.OnlinePlayers.Values)
            {
                var piaa = new PlayerInfoAddAction()
                {
                    Name        = player.Username,
                    Uuid        = player.Uuid,
                    Ping        = player.Ping,
                    Gamemode    = (int)Player.Gamemode,
                    DisplayName = ChatMessage.Simple(player.Username)
                };

                if (this.config.OnlineMode)
                {
                    var uuid = player.Uuid.ToString().Replace("-", "");
                    var skin = await MinecraftAPI.GetUserAndSkinAsync(uuid);

                    piaa.Properties.AddRange(skin.Properties);
                }

                list.Add(piaa);
            }

            await this.QueuePacketAsync(new PlayerInfo(0, list));
        }
コード例 #2
0
        public static async Task <string> DetectVersion(StorageFile resourcePackFile, bool onlyReleases = true)
        {
            if (resourcePackFile == null)
            {
                throw new ArgumentNullException(nameof(resourcePackFile));
            }

            Logger.WriteLine($"Detecting resource pack version of file {resourcePackFile.Name}.");

            var relations = await ResourceRelationService.GetOrCreateAsync();

            if (relations?.Count == 0)
            {
                throw new InvalidOperationException("Retrieved relation set is empty.");
            }

            if (!MinecraftService.IsInitialized)
            {
                await MinecraftService.InitializeAsync();
            }
            var versionCount = onlyReleases ? MinecraftAPI.Releases.ToDictionary(x => x.Id, x => 0) : MinecraftAPI.Versions.ToDictionary(x => x.Id, x => 0);

            using (var stream = await resourcePackFile.OpenStreamForReadAsync())
                using (var archive = new ZipArchive(stream, ZipArchiveMode.Read))
                {
                    foreach (var entry in archive.Entries.ToList())
                    {
                        var entryPath = entry.FullName.Replace("/", "\\");
                        foreach (var relation in relations)
                        {
                            foreach (var versionPathPair in relation)
                            {
                                if (versionPathPair.Value.Equals(entryPath) && versionCount.ContainsKey(versionPathPair.Key))
                                {
                                    versionCount[versionPathPair.Key]++;
                                }
                            }
                        }
                    }
                }

            var    maxCount = versionCount.Max(vp => vp.Value);
            var    mostNominatedVersions = versionCount.Where(r => r.Value == maxCount).Select(vp => vp.Key);
            string maxVersion            = null;

            foreach (var nominatedVersion in mostNominatedVersions)
            {
                if (maxVersion == null)
                {
                    maxVersion = nominatedVersion;
                }
                else
                {
                    maxVersion = MinecraftAPI.MaxVersion(maxVersion, nominatedVersion);
                }
            }
            return(maxVersion);
        }
コード例 #3
0
        public static async Task InitializeAsync()
        {
            Debug.WriteLine("Initializing MinecraftService...");

            var localDirectory = await ApplicationData.Current.LocalFolder.CreateFolderAsync("MinecraftApi", CreationCollisionOption.OpenIfExists);

            if (!MinecraftAPI.IsInitialized)
            {
                await MinecraftAPI.InitializeAsync(localDirectory.Path);
            }

            Debug.WriteLine("...MinecraftService initialized.");
        }
コード例 #4
0
        public static async Task<StorageFile> DownloadAsync(string version, DownloadOption option = DownloadOption.Default)
        {
            if (!MinecraftAPI.IsInitialized)
            {
                Debug.WriteLine($"MinecraftService is not initialized. Proceeds to initialize it.");
                await InitializeAsync();
            }
            if (!MinecraftAPI.Contains(version))
            {
                Debug.WriteLine($"Version {version} does not exist in available links.");
                return null;
            }

            if (await ContainsZip(version))
            {
                Debug.WriteLine($"Version {version} is already downloaded. No further steps required.");
                return null;
            }

            var uri = new Uri(MinecraftAPI.Get(version)?.Downloads.Client?.Url);

            var root = await GetOrCreateRootFolderAsync();
            var file = await root?.CreateFileAsync(version + ".zip", CreationCollisionOption.ReplaceExisting);

            try
            {
                BackgroundDownloader downloader = new BackgroundDownloader();
                DownloadOperation download = downloader?.CreateDownload(uri, file);
                Debug.WriteLine($"Downloading: {uri?.AbsolutePath}...");
                await download.StartAsync();
                Debug.WriteLine($"...Download completed: {uri?.AbsolutePath}");
            }
            catch (Exception e)
            {
                Debug.WriteLine($"Error when downloading {uri.AbsolutePath}:\n{e.Message}");
                return null;
            }

            await CreateResourceListAsync(version);

            if (option == DownloadOption.ExtractFiles)
                await Extract(version);

            return file;
        }
コード例 #5
0
 /// <summary>
 /// 开始下载
 /// </summary>
 public void Download(DownloadingEventHandler eve)
 {
     percent = 0;
     DownloadProgressRefreshed(this, new EventArgs());
     if (MinecraftVersion == null)
     {
         throw new Exception("Minecraft Version Can't be NULL");
     }
     else
     {
         MinecraftProfile profile = MinecraftProfile.GetFromVersion(MinecraftVersion, VersionName);
         profile.SaveToLocalPath();
         profile.InstallVersion((float f) =>
         {
             eve(f * (1f - ((float)APIVersions.Count / 10f)));
         });
         if (APIVersions.Count == 0)
         {
         }
         else
         {
             int count = APIVersions.Values.Count;
             int dldd  = 0;
             foreach (var api in APIVersions.Values)
             {
                 MinecraftAPI mcapi = api.GetMinecraftAPI();
                 mcapi.profile = profile;
                 profile.APIConfig.InstallAPI(mcapi, (float f) =>
                 {
                     eve((1f - ((float)APIVersions.Count / 10f)) + (float)(f / 10f) + (float)(dldd / 10f));
                 });
                 dldd++;
             }
         }
     }
 }
コード例 #6
0
        public async Task StartConnectionAsync()
        {
            while (!Cancellation.IsCancellationRequested && this.tcp.Connected)
            {
                Packet packet = await this.GetNextPacketAsync();

                if (this.State == ClientState.Play && packet.data.Length < 1)
                {
                    this.Disconnect();
                }

                switch (this.State)
                {
                case ClientState.Status:     // Server ping/list
                    switch (packet.id)
                    {
                    case 0x00:
                        var status = new ServerStatus(Server);
                        await this.SendPacketAsync(new RequestResponse(status));

                        break;

                    case 0x01:
                        await this.SendPacketAsync(new PingPong(packet.data));

                        this.Disconnect();
                        break;
                    }
                    break;

                case ClientState.Handshaking:
                    if (packet.id == 0x00)
                    {
                        if (packet == null)
                        {
                            throw new InvalidOperationException();
                        }

                        var handshake = await PacketSerializer.FastDeserializeAsync <Handshake>(packet.data);

                        var nextState = handshake.NextState;

                        if (nextState != ClientState.Status && nextState != ClientState.Login)
                        {
                            this.Logger.LogDebug($"Client sent unexpected state ({(int)nextState}), forcing it to disconnect");
                            await this.DisconnectAsync(ChatMessage.Simple("you seem suspicious"));
                        }

                        this.State = nextState;
                        this.Logger.LogInformation($"Handshaking with client (protocol: {handshake.Version}, server: {handshake.ServerAddress}:{handshake.ServerPort})");
                    }
                    else
                    {
                        // Handle legacy ping
                    }
                    break;

                case ClientState.Login:
                    switch (packet.id)
                    {
                    default:
                        this.Logger.LogError("Client in state Login tried to send an unimplemented packet. Forcing it to disconnect.");
                        await this.DisconnectAsync("Unknown Packet Id.");

                        break;

                    case 0x00:
                        var loginStart = await PacketSerializer.FastDeserializeAsync <LoginStart>(packet.data);

                        string username = config.MulitplayerDebugMode ? $"Player{Globals.Random.Next(1, 999)}" : loginStart.Username;

                        this.Logger.LogDebug($"Received login request from user {loginStart.Username}");

                        await this.Server.DisconnectIfConnectedAsync(username);

                        if (this.config.OnlineMode)
                        {
                            var user = await MinecraftAPI.GetUserAsync(loginStart.Username);

                            this.Player = new Player(Guid.Parse(user.Id), loginStart.Username, this)
                            {
                                World = this.Server.World
                            };

                            this.packetCryptography.GenerateKeyPair();

                            var values = this.packetCryptography.GeneratePublicKeyAndToken();

                            this.randomToken = values.randomToken;

                            await this.SendPacketAsync(new EncryptionRequest(values.publicKey, this.randomToken));

                            break;
                        }

                        this.Player = new Player(UUIDFactory.CreateUUID(3, 1, $"OfflinePlayer:{username}"), username, this)
                        {
                            World = this.Server.World
                        };

                        //await this.SetCompression();
                        await this.ConnectAsync();

                        break;

                    case 0x01:
                        var encryptionResponse = PacketSerializer.FastDeserialize <EncryptionResponse>(packet.data);

                        this.sharedKey = this.packetCryptography.Decrypt(encryptionResponse.SharedSecret);
                        var decryptedToken = this.packetCryptography.Decrypt(encryptionResponse.VerifyToken);

                        if (!decryptedToken.SequenceEqual(this.randomToken))
                        {
                            await this.DisconnectAsync("Invalid token..");

                            break;
                        }

                        var serverId = sharedKey.Concat(this.packetCryptography.PublicKey).ToArray().MinecraftShaDigest();

                        JoinedResponse response = await MinecraftAPI.HasJoined(this.Player.Username, serverId);

                        if (response is null)
                        {
                            this.Logger.LogWarning($"Failed to auth {this.Player.Username}");
                            await this.DisconnectAsync("Unable to authenticate..");

                            break;
                        }

                        this.encryptionEnabled = true;
                        this.minecraftStream   = new AesStream(this.debugStream ?? (Stream)this.tcp.GetStream(), this.sharedKey);

                        //await this.SetCompression();
                        await ConnectAsync();

                        break;

                    case 0x02:
                        // Login Plugin Response
                        break;
                    }
                    break;

                case ClientState.Play:

                    //await this.Logger.LogDebugAsync($"Received Play packet with Packet ID 0x{packet.id.ToString("X")}");

                    await PacketHandler.HandlePlayPackets(packet, this);

                    break;
                }

                //await Task.Delay(50);
            }

            Logger.LogInformation($"Disconnected client");

            if (this.State == ClientState.Play)
            {
                await this.Server.Events.InvokePlayerLeaveAsync(new PlayerLeaveEventArgs(this.Player));
            }

            if (tcp.Connected)
            {
                this.tcp.Close();

                if (this.Player != null)
                {
                    this.Server.OnlinePlayers.TryRemove(this.Player.Uuid, out var _);
                }
            }
        }
コード例 #7
0
ファイル: Client.cs プロジェクト: GerjanVlot/Obsidian
        public async Task StartConnectionAsync()
        {
            while (!Cancellation.IsCancellationRequested && this.Tcp.Connected)
            {
                Packet packet = this.Compressed ? await this.GetNextCompressedPacketAsync() : await this.GetNextPacketAsync();

                Packet returnPacket;

                if (this.State == ClientState.Play && packet.PacketData.Length < 1)
                {
                    this.Disconnect();
                }

                switch (this.State)
                {
                case ClientState.Status:     //server ping/list
                    switch (packet.PacketId)
                    {
                    case 0x00:
                        var status = new ServerStatus(OriginServer);
                        await PacketHandler.CreateAsync(new RequestResponse(status), this.MinecraftStream);

                        break;

                    case 0x01:
                        await PacketHandler.CreateAsync(new PingPong(packet.PacketData), this.MinecraftStream);

                        this.Disconnect();
                        break;
                    }
                    break;

                case ClientState.Handshaking:
                    if (packet.PacketId == 0x00)
                    {
                        if (packet == null)
                        {
                            throw new InvalidOperationException();
                        }

                        var handshake = await PacketHandler.CreateAsync(new Handshake(packet.PacketData));

                        var nextState = handshake.NextState;

                        if (nextState != ClientState.Status && nextState != ClientState.Login)
                        {
                            this.Logger.LogDebug($"Client sent unexpected state ({(int)nextState}), forcing it to disconnect");
                            await this.DisconnectAsync(Chat.ChatMessage.Simple("you seem suspicious"));
                        }

                        this.State = nextState;
                        this.Logger.LogMessage($"Handshaking with client (protocol: {handshake.Version}, server: {handshake.ServerAddress}:{handshake.ServerPort})");
                    }
                    else
                    {
                        //Handle legacy ping stuff
                    }
                    break;

                case ClientState.Login:
                    switch (packet.PacketId)
                    {
                    default:
                        this.Logger.LogError("Client in state Login tried to send an unimplemented packet. Forcing it to disconnect.");
                        await this.DisconnectAsync(ChatMessage.Simple("Unknown Packet Id."));

                        break;

                    case 0x00:
                        var loginStart = await PacketHandler.CreateAsync(new LoginStart(packet.PacketData));

                        string username = loginStart.Username;

                        if (Config.MulitplayerDebugMode)
                        {
                            username = $"Player{new Random().Next(1, 999)}";
                            this.Logger.LogDebug($"Overriding username from {loginStart.Username} to {username}");
                        }

                        this.Logger.LogDebug($"Received login request from user {loginStart.Username}");

                        if (this.OriginServer.CheckPlayerOnline(username))
                        {
                            await this.OriginServer.Clients.FirstOrDefault(c => c.Player.Username == username).DisconnectAsync(Chat.ChatMessage.Simple("Logged in from another location"));
                        }

                        if (this.Config.OnlineMode)
                        {
                            var users = await MinecraftAPI.GetUsersAsync(new string[] { loginStart.Username });

                            var uid = users.FirstOrDefault();

                            var uuid = Guid.Parse(uid.Id);
                            this.Player = new Player(uuid, loginStart.Username, this);

                            PacketCryptography.GenerateKeyPair();

                            var pubKey = PacketCryptography.PublicKeyToAsn();

                            this.Token = PacketCryptography.GetRandomToken();

                            returnPacket = await PacketHandler.CreateAsync(new EncryptionRequest(pubKey, this.Token), this.MinecraftStream);

                            break;
                        }

                        this.Player = new Player(Guid.NewGuid(), username, this);
                        await ConnectAsync(this.Player.Uuid);

                        break;

                    case 0x01:
                        var encryptionResponse = await PacketHandler.CreateAsync(new EncryptionResponse(packet.PacketData));

                        JoinedResponse response;

                        this.SharedKey = PacketCryptography.Decrypt(encryptionResponse.SharedSecret);

                        var dec2 = PacketCryptography.Decrypt(encryptionResponse.VerifyToken);

                        var dec2Base64 = Convert.ToBase64String(dec2);

                        var tokenBase64 = Convert.ToBase64String(this.Token);

                        if (!dec2Base64.Equals(tokenBase64))
                        {
                            await this.DisconnectAsync(Chat.ChatMessage.Simple("Invalid token.."));

                            break;
                        }

                        var encodedKey = PacketCryptography.PublicKeyToAsn();

                        var serverId = PacketCryptography.MinecraftShaDigest(SharedKey.Concat(encodedKey).ToArray());

                        response = await MinecraftAPI.HasJoined(this.Player.Username, serverId);

                        if (response is null)
                        {
                            this.Logger.LogWarning($"Failed to auth {this.Player.Username}");
                            await this.DisconnectAsync(Chat.ChatMessage.Simple("Unable to authenticate.."));

                            break;
                        }
                        this.EncryptionEnabled = true;
                        this.MinecraftStream   = new AesStream(this.Tcp.GetStream(), this.SharedKey);

                        await ConnectAsync(new Guid(response.Id));

                        break;

                    case 0x02:
                        // Login Plugin Response
                        break;
                    }
                    break;

                case ClientState.Play:

                    ///this.Logger.LogDebugAsync($"Received Play packet with Packet ID 0x{packet.PacketId.ToString("X")}");

                    await PacketHandler.HandlePlayPackets(packet, this);

                    break;
                }
            }

            Logger.LogMessage($"Disconnected client");

            if (this.IsPlaying)
            {
                await this.OriginServer.Events.InvokePlayerLeave(new PlayerLeaveEventArgs(this));
            }

            this.OriginServer.Broadcast(string.Format(this.Config.LeaveMessage, this.Player.Username));

            this.Player = null;

            if (Tcp.Connected)
            {
                this.Tcp.Close();
            }
        }