private void DoClick(HUDKeypad source, HUDKeypad.HUDKeypadEventArgs args)
        {
            if (CharIndex >= 8)
            {
                return;
            }

            CharDisp[CharIndex].Character = args.Character;

            CharIndex++;
            if (CharIndex == 8)
            {
                var code = new string(Enumerable.Range(0, 8).Select(i => CharDisp[i].Character).ToArray());

                var d = KiddieCryptography.SpiralHexDecode(code);

                for (int i = 0; i < 8; i++)
                {
                    CharDisp[i].Background = CharDisp[i].Background.WithColor(FlatColors.Concrete);
                }

                Server.JoinSession(d.Item1, d.Item2);
            }
        }
        public override void OnInitialize()
        {
            base.OnInitialize();

            AddElement(new HUDLabel
            {
                TextAlignment    = HUDAlignment.CENTER,
                Alignment        = HUDAlignment.TOPLEFT,
                RelativePosition = new FPoint(0, 0),
                Size             = new FSize(WIDTH, 100),

                Font     = Textures.HUDFontBold,
                FontSize = 64,

                L10NText  = L10NImpl.STR_MENU_CAP_LOBBY,
                TextColor = FlatColors.Clouds,
            });

            AddElement(new MultiplayerConnectionStateControl(_server)
            {
                Alignment        = HUDAlignment.TOPLEFT,
                RelativePosition = new FPoint(16, 16)
            });

            if (_server.ConnType == MultiplayerConnectionType.PROXY)
            {
                var gridDisplay = new HUDFixedUniformGrid
                {
                    Alignment        = HUDAlignment.TOPCENTER,
                    RelativePosition = new FPoint(0, 100),
                    GridWidth        = 8,
                    GridHeight       = 1,
                    ColumnWidth      = 84,
                    RowHeight        = 84,
                    Padding          = 16,
                };
                AddElement(gridDisplay);

                for (int i = 0; i < 8; i++)
                {
                    CharDisp[i] = new HUDCharacterControl(1)
                    {
                        Background = HUDBackgroundDefinition.CreateSimpleOutline(FlatColors.Clouds, Color.Black, 4f),

                        TextPadding = 2,
                        TextColor   = Color.Black
                    };

                    gridDisplay.AddElement(i, 0, CharDisp[i]);
                }

                var scode = KiddieCryptography.SpiralHexEncode(_server.SessionID, _server.SessionSecret);
                for (int i = 0; i < 8; i++)
                {
                    if (i < scode.Length)
                    {
                        CharDisp[i].Character = scode[i];
                    }
                }

                AddOperation(new CharacterControlWaveOperation(CharDisp));

                AddElement(new HUDLabel
                {
                    TextAlignment    = HUDAlignment.BOTTOMRIGHT,
                    Alignment        = HUDAlignment.BOTTOMRIGHT,
                    RelativePosition = new FPoint(16, FOOTER_HEIGHT + 16),
                    Size             = new FSize(320, 128),
                    MaxWidth         = 320,
                    WordWrap         = HUDWordWrap.WrapByWordTrusted,

                    Font     = Textures.HUDFontRegular,
                    FontSize = 32,

                    L10NText  = L10NImpl.STR_MENU_MP_LOBBYINFO,
                    TextColor = ColorMath.Blend(FlatColors.Clouds, FlatColors.Background, 0.5f),
                });
            }

            AddElement(new HUDLabel
            {
                TextAlignment    = HUDAlignment.CENTERLEFT,
                Alignment        = HUDAlignment.TOPLEFT,
                RelativePosition = new FPoint(INFO_C1_LEFT, 208 + 0 * 32),
                Size             = new FSize(INFO_C1_WIDTH, 32),
                Font             = Textures.HUDFontRegular,
                FontSize         = 32,
                L10NText         = L10NImpl.STR_MENU_MP_LOBBY_PING,
                TextColor        = FlatColors.Clouds,
            });

            AddElement(new HUDLabel
            {
                TextAlignment    = HUDAlignment.CENTERLEFT,
                Alignment        = HUDAlignment.TOPLEFT,
                RelativePosition = new FPoint(INFO_C1_LEFT, 208 + 1 * 32),
                Size             = new FSize(INFO_C1_WIDTH, 32),
                Font             = Textures.HUDFontRegular,
                FontSize         = 32,
                L10NText         = L10NImpl.STR_MENU_MP_LOBBY_USER,
                TextColor        = FlatColors.Clouds,
            });

            AddElement(new HUDLabel
            {
                TextAlignment    = HUDAlignment.CENTERLEFT,
                Alignment        = HUDAlignment.TOPLEFT,
                RelativePosition = new FPoint(INFO_C1_LEFT, 208 + 2 * 32),
                Size             = new FSize(INFO_C1_WIDTH, 32),
                Font             = Textures.HUDFontRegular,
                FontSize         = 32,
                L10NText         = L10NImpl.STR_MENU_MP_LOBBY_LEVEL,
                TextColor        = FlatColors.Clouds,
            });

            AddElement(new HUDLabel
            {
                TextAlignment    = HUDAlignment.CENTERLEFT,
                Alignment        = HUDAlignment.TOPLEFT,
                RelativePosition = new FPoint(INFO_C1_LEFT, 208 + 3 * 32),
                Size             = new FSize(INFO_C1_WIDTH, 32),
                Font             = Textures.HUDFontRegular,
                FontSize         = 32,
                L10NText         = L10NImpl.STR_MENU_MP_LOBBY_MUSIC,
                TextColor        = FlatColors.Clouds,
            });

            AddElement(new HUDLabel
            {
                TextAlignment    = HUDAlignment.CENTERLEFT,
                Alignment        = HUDAlignment.TOPLEFT,
                RelativePosition = new FPoint(INFO_C1_LEFT, 208 + 4 * 32),
                Size             = new FSize(INFO_C1_WIDTH, 32),
                Font             = Textures.HUDFontRegular,
                FontSize         = 32,
                L10NText         = L10NImpl.STR_MENU_MP_LOBBY_SPEED,
                TextColor        = FlatColors.Clouds,
            });

            AddElement(new HUDLabel
            {
                TextAlignment    = HUDAlignment.CENTERLEFT,
                Alignment        = HUDAlignment.TOPLEFT,
                RelativePosition = new FPoint(INFO_C1_LEFT, 208 + 5 * 32),
                Size             = new FSize(INFO_C1_WIDTH, 32),
                Font             = Textures.HUDFontRegular,
                FontSize         = 32,
                L10NText         = L10NImpl.STR_MENU_MP_LOBBY_COLOR,
                TextColor        = FlatColors.Clouds,
            });



            AddElement(new HUDLambdaLabel
            {
                TextAlignment    = HUDAlignment.CENTERLEFT,
                Alignment        = HUDAlignment.TOPLEFT,
                RelativePosition = new FPoint(INFO_C2_LEFT, 208 + 0 * 32),
                Size             = new FSize(INFO_C2_WIDTH, 32),
                MaxWidth         = INFO_C2_WIDTH,
                Font             = Textures.HUDFontRegular,
                FontSize         = 32,
                Lambda           = () => $"{(int)(_server.ProxyPing.Value * 1000)}ms",
                WordWrap         = HUDWordWrap.Ellipsis,
                TextColor        = FlatColors.Clouds,
            });

            AddElement(new HUDLambdaLabel
            {
                TextAlignment    = HUDAlignment.CENTERLEFT,
                Alignment        = HUDAlignment.TOPLEFT,
                RelativePosition = new FPoint(INFO_C2_LEFT, 208 + 1 * 32),
                Size             = new FSize(INFO_C2_WIDTH, 32),
                MaxWidth         = INFO_C2_WIDTH,
                Font             = Textures.HUDFontRegular,
                FontSize         = 32,
                Lambda           = () => $"{_server.SessionCount} / {_server.SessionCapacity}",
                WordWrap         = HUDWordWrap.Ellipsis,
                TextColor        = FlatColors.Clouds,
            });

            AddElement(new HUDLabel
            {
                TextAlignment    = HUDAlignment.CENTERLEFT,
                Alignment        = HUDAlignment.TOPLEFT,
                RelativePosition = new FPoint(INFO_C2_LEFT, 208 + 2 * 32),
                Size             = new FSize(INFO_C2_WIDTH, 32),
                MaxWidth         = INFO_C2_WIDTH,
                Font             = Textures.HUDFontRegular,
                FontSize         = 32,
                Text             = Levels.LEVELS[_server.LevelID].FullName,
                WordWrap         = HUDWordWrap.Ellipsis,
                TextColor        = FlatColors.Clouds,
            });

            AddElement(new HUDLabel
            {
                TextAlignment    = HUDAlignment.CENTERLEFT,
                Alignment        = HUDAlignment.TOPLEFT,
                RelativePosition = new FPoint(INFO_C2_LEFT, 208 + 3 * 32),
                Size             = new FSize(INFO_C2_WIDTH, 32),
                MaxWidth         = INFO_C2_WIDTH,
                Font             = Textures.HUDFontRegular,
                FontSize         = 32,
                Text             = (_server.MusicIndex + 1).ToString(),
                WordWrap         = HUDWordWrap.Ellipsis,
                TextColor        = FlatColors.Clouds,
            });

            AddElement(new HUDLabel
            {
                TextAlignment    = HUDAlignment.CENTERLEFT,
                Alignment        = HUDAlignment.TOPLEFT,
                RelativePosition = new FPoint(INFO_C2_LEFT, 208 + 4 * 32),
                Size             = new FSize(INFO_C2_WIDTH, 32),
                MaxWidth         = INFO_C2_WIDTH,
                Font             = Textures.HUDFontRegular,
                FontSize         = 32,
                Text             = Fmt(_server.Speed),
                WordWrap         = HUDWordWrap.Ellipsis,
                TextColor        = FlatColors.Clouds,
            });

            AddElement(new HUDLabel
            {
                TextAlignment    = HUDAlignment.CENTERLEFT,
                Alignment        = HUDAlignment.TOPLEFT,
                RelativePosition = new FPoint(INFO_C2_LEFT, 208 + 5 * 32),
                Size             = new FSize(INFO_C2_WIDTH, 32),
                MaxWidth         = INFO_C2_WIDTH,
                Font             = Textures.HUDFontRegular,
                FontSize         = 32,
                L10NText         = Fraction.NAME_PLAYER,
                WordWrap         = HUDWordWrap.Ellipsis,
                TextColor        = Fraction.COLOR_PLAYER,
            });



            AddElement(new HUDRectangle(0)
            {
                Alignment = HUDAlignment.BOTTOMRIGHT,
                Size      = new FSize(WIDTH, FOOTER_HEIGHT),

                Definition = HUDBackgroundDefinition.CreateRounded(FlatColors.BackgroundHUD2, 16, false, false, true, true),
            });

            AddElement(new HUDTextButton(2)
            {
                Alignment        = HUDAlignment.BOTTOMLEFT,
                RelativePosition = new FPoint(0.5f * GDConstants.TILE_WIDTH, 0.5f * GDConstants.TILE_WIDTH),
                Size             = new FSize(6.5f * GDConstants.TILE_WIDTH, 1.0f * GDConstants.TILE_WIDTH),

                L10NText      = L10NImpl.STR_MENU_DISCONNECT,
                TextColor     = Color.White,
                Font          = Textures.HUDFontBold,
                FontSize      = 55,
                TextAlignment = HUDAlignment.CENTER,
                TextPadding   = 8,

                BackgroundNormal  = HUDBackgroundDefinition.CreateRoundedBlur(FlatColors.Asbestos, 16),
                BackgroundPressed = HUDBackgroundDefinition.CreateRoundedBlur(FlatColors.MidnightBlue, 16),

                Click = OnClickCancel,
            });

            AddElement(_btnStart = new HUDTextButton(2)
            {
                Alignment        = HUDAlignment.BOTTOMRIGHT,
                RelativePosition = new FPoint(0.5f * GDConstants.TILE_WIDTH, 0.5f * GDConstants.TILE_WIDTH),
                Size             = new FSize(5.5f * GDConstants.TILE_WIDTH, 1.0f * GDConstants.TILE_WIDTH),

                L10NText      = L10NImpl.STR_MENU_MP_START,
                TextColor     = Color.White,
                Font          = Textures.HUDFontBold,
                FontSize      = 55,
                TextAlignment = HUDAlignment.CENTER,
                TextPadding   = 8,

                BackgroundNormal  = HUDBackgroundDefinition.CreateRoundedBlur(FlatColors.Emerald, 16),
                BackgroundPressed = HUDBackgroundDefinition.CreateRoundedBlur(FlatColors.Nephritis, 16),

                IsVisible = false,

                Click = OnClickStart,
            });
        }