Esempio n. 1
0
        public static async Task Main(string[] args)
        {
            var service = new GameService(50001);

            TcpMonitor.StartWritingToLog();
            await service.BeginHandling();
        }
Esempio n. 2
0
        private async void HandleConnection(TcpClient socket)
        {
            TcpMonitor.OnTcpClientConnect(socket);
            byte[] key = new byte[16];
            _random.NextBytes(key);
            var stream = socket.GetStream();
            await stream.WriteAsync(key);

            common.EncryptedStream clientKey = new common.EncryptedStream(key);
            common.EncryptedStream serverKey = new common.EncryptedStream(key);

            Func <Hpmv.SessionResponse, Task> SendResponse = async(Hpmv.SessionResponse response) =>
            {
                // Console.WriteLine(response.ToString());
                byte[] outBuf = response.ToByteArray();
                if (outBuf.Length > 65535)
                {
                    throw new Exception("Server message length too long");
                }
                byte[] lenBuf = BitConverter.GetBytes((ushort)outBuf.Length);
                serverKey.Transform(lenBuf, 2);
                serverKey.Transform(outBuf, outBuf.Length);
                await stream.WriteAsync(lenBuf);

                await stream.WriteAsync(outBuf);
            };

            byte[]   buffer = new byte[65536];
            GameData game   = null;

            try
            {
                while (true)
                {
                    await stream.ReadNBytes(buffer, 0, 2);

                    clientKey.Transform(buffer, 2);
                    ushort length = BitConverter.ToUInt16(buffer, 0);
                    await stream.ReadNBytes(buffer, 0, length);

                    clientKey.Transform(buffer, length);
                    Hpmv.SessionRequest request = Hpmv.SessionRequest.Parser.ParseFrom(buffer, 0, length);
                    // Console.WriteLine("Request: " + request.ToString());
                    switch (request.RequestCase)
                    {
                    case Hpmv.SessionRequest.RequestOneofCase.Login:
                    {
                        var      user     = request.Login.Username;
                        var      pass     = request.Login.Password;
                        GameData gameTemp = null;
                        lock (_games)
                        {
                            if (!_games.ContainsKey(user))
                            {
                                CreateGame(user, pass);
                            }
                            gameTemp = _games[user];
                        }

                        if (gameTemp.password != pass)
                        {
                            await SendResponse(new Hpmv.SessionResponse()
                                {
                                    Login = new Hpmv.LoginResponse()
                                    {
                                        Successful = false
                                    },
                                    Message = "Invalid password."
                                });

                            break;
                        }
                        if (!await gameTemp.mutex.WaitAsync(0))
                        {
                            await SendResponse(new Hpmv.SessionResponse()
                                {
                                    Login = new Hpmv.LoginResponse()
                                    {
                                        Successful = false
                                    },
                                    Message = "This account is already logged in."
                                });

                            break;
                        }
                        if (DateTime.Now < gameTemp.lastLogoff.AddSeconds(20))
                        {
                            gameTemp.mutex.Release();
                            await SendResponse(new Hpmv.SessionResponse()
                                {
                                    Login = new Hpmv.LoginResponse()
                                    {
                                        Successful = false
                                    },
                                    Message = "You may only login to the same account again after 20 seconds of cooldown."
                                });

                            break;
                        }
                        game = gameTemp;
                        var response = new Hpmv.SessionResponse()
                        {
                            Login = new Hpmv.LoginResponse()
                            {
                                Successful = true,
                                Player     = CalculatePlayerInfo(game.player)
                            }
                        };
                        response.Login.Inventory.AddRange(game.inventory);
                        await SendResponse(response);

                        break;
                    }

                    case Hpmv.SessionRequest.RequestOneofCase.Battle:
                    {
                        if (game == null)
                        {
                            throw new Exception("Not logged in");
                        }
                        var level = request.Battle.MonsterLevel;
                        if (level < game.player.Level - 1 || level > game.player.Level + 2)
                        {
                            throw new Exception("Invalid level " + level);
                        }
                        var monsterHp     = 50 + level * 20;
                        var monsterAttack = 5 + level * 1;
                        var playerAttack  = game.player.Level + game.inventory[0].Items.Select((i) => i.Attack).Sum();
                        var resp          = new Hpmv.BattleResponse();
                        for (int i = 0; i < 32; i++)
                        {
                            if (game.player.Hp <= monsterAttack)
                            {
                                break;
                            }
                            monsterHp -= playerAttack;
                            if (monsterHp <= 0)
                            {
                                break;
                            }
                            game.player.Hp -= monsterAttack;
                            resp.Rounds.Add(new Hpmv.BattleResponse.Types.OneRound {
                                    SelfHp = game.player.Hp, MonsterHp = monsterHp
                                });
                        }
                        resp.Victory = monsterHp <= 0;
                        if (resp.Victory)
                        {
                            resp.GainedExperience   = (level + 1 - game.player.Level) * (level + 20);
                            resp.GainedCoins        = 10 + (level + 1 - game.player.Level) * level / 10;
                            game.player.Experience += resp.GainedExperience;
                            var calculated = CalculatePlayerInfo(game.player);
                            if (game.player.Experience >= calculated.ExperienceTillNextLevel)
                            {
                                game.player.Level++;
                                game.player.Experience -= calculated.ExperienceTillNextLevel;
                            }
                            game.player.Money += resp.GainedCoins;
                        }
                        resp.NewInfo = CalculatePlayerInfo(game.player);
                        await SendResponse(new Hpmv.SessionResponse()
                            {
                                Battle = resp
                            });

                        break;
                    }

                    case Hpmv.SessionRequest.RequestOneofCase.ItemUse:
                    {
                        if (game == null)
                        {
                            throw new Exception("Not logged in");
                        }
                        int index = request.ItemUse.ItemIndex;
                        if (index < 0 || index >= game.inventory[0].Items.Count)
                        {
                            throw new Exception("No such item");
                        }
                        var item     = game.inventory[0].Items[index];
                        var response = new Hpmv.ItemUseResponse();
                        if (item.HpRestore > 0)
                        {
                            game.player.Hp = Math.Min(CalculatePlayerInfo(game.player).MaxHp, game.player.Hp + item.HpRestore);
                        }
                        response.NewHp = game.player.Hp;
                        if (item.Id == 8)
                        {
                            response.Message = "Congratulations! Here is the server-side flag: _is_f0R_Th3_13373sT}   The client-side flag is clearly written on a piece of paper that was lost by the shopkeeper some time ago. If only you could find it...";
                        }
                        await SendResponse(new Hpmv.SessionResponse()
                            {
                                ItemUse = response
                            });

                        break;
                    }

                    case Hpmv.SessionRequest.RequestOneofCase.InventoryMove:
                    {
                        if (game == null)
                        {
                            throw new Exception("Not logged in");
                        }
                        int            fromInventory = request.InventoryMove.FromInventory;
                        int            toInventory   = request.InventoryMove.ToInventory;
                        Hpmv.Inventory from          = game.inventory[fromInventory].Clone();
                        Hpmv.Inventory to            = game.inventory[toInventory].Clone();
                        var            item          = from.Items[request.InventoryMove.ItemIndex];
                        from.Items.RemoveAt(request.InventoryMove.ItemIndex);
                        to.Items.Add(item);
                        long costDelta = 0;
                        foreach (var cost in item.MoveCosts)
                        {
                            if (cost.Inventory == fromInventory && cost.Out)
                            {
                                costDelta += cost.Cost;
                            }
                            if (cost.Inventory == toInventory && !cost.Out)
                            {
                                costDelta += cost.Cost;
                            }
                        }
                        if (costDelta + game.player.Money >= 0 && to.Items.Count <= to.TotalCapacity)
                        {
                            game.player.Money            += costDelta;
                            game.inventory[fromInventory] = from;
                            game.inventory[toInventory]   = to;
                        }
                        var response = new Hpmv.InventoryMoveResponse();
                        response.FromInventory  = game.inventory[fromInventory];
                        response.ToInventory    = game.inventory[toInventory];
                        response.NewPlayerMoney = game.player.Money;
                        await SendResponse(new Hpmv.SessionResponse()
                            {
                                InventoryMove = response
                            });

                        break;
                    }
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Session error: " + e.Message);
            }
            finally
            {
                if (game != null)
                {
                    game.lastLogoff = DateTime.Now;
                    game.mutex.Release();
                }
            }
            socket.Close();
            TcpMonitor.OnTcpClientDisconnect(socket);
        }