Find solution to fix chat bugs and move to Avalonia

This commit is contained in:
Ilya 2021-02-25 16:40:08 +03:00
parent 10f45f6cca
commit 4306daf5a1
15 changed files with 1143 additions and 3 deletions

13
.idea/.idea.MafiaGame/.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,13 @@
# Default ignored files
/shelf/
/workspace.xml
# Rider ignored files
/.idea.MafiaGame.iml
/modules.xml
/contentModel.xml
/projectSettingsUpdater.xml
# Datasource local storage ignored files
/../../../../../../../../../../../:\Users\Ilya\Source\Repos\C#\MafiaGame\MafiaGame\.idea\.idea.MafiaGame\.idea/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/

8
MafiaClient/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
.idea/
.vscode/
.vs/
bin/
obj/
*.user

7
MafiaClient/App.axaml Normal file
View File

@ -0,0 +1,7 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="MafiaClient.App">
<Application.Styles>
<FluentTheme Mode="Light"/>
</Application.Styles>
</Application>

65
MafiaClient/App.axaml.cs Normal file
View File

@ -0,0 +1,65 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using DiscordRPC;
using DiscordRPC.Logging;
using DiscordRPC.Message;
namespace MafiaClient
{
public class App : Application
{
public override void Initialize()
{
Instance = this;
AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
_rpcClient = new DiscordRpcClient("800016130097152000", autoEvents: true);
_rpcClient.RegisterUriScheme();
_rpcClient.Logger = new ConsoleLogger() { Level = LogLevel.Warning };
_rpcClient.OnJoinRequested += RpcClientOnOnJoinRequested;
_rpcClient.OnJoin += RpcClientOnOnJoin;
_rpcClient.SetSubscription(EventType.Join | EventType.JoinRequest);
_rpcClient.Initialize();
_rpcClient.SetPresence(new RichPresence()
{
State = "Запуск игры..."
});
desktop.MainWindow = new MainWindow();
Settings.Initialize();
Settings.Save();
}
base.OnFrameworkInitializationCompleted();
}
public static App Instance;
private DiscordRpcClient _rpcClient;
public ServerConnection Connection;
public DiscordRpcClient GetRpcClient()
{
return _rpcClient;
}
private void RpcClientOnOnJoin(object sender, JoinMessage args)
{
string secret = args.Secret;
Connection = new ServerConnection(secret.Replace("/join", ""));
}
private void RpcClientOnOnJoinRequested(object sender, JoinRequestMessage args)
{
_rpcClient.Respond(args, true);
}
}
}

View File

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="0.10.0" />
<PackageReference Include="Avalonia.Desktop" Version="0.10.0" />
<PackageReference Include="Avalonia.Diagnostics" Version="0.10.0" />
<PackageReference Include="DiscordRichPresence" Version="1.0.175" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MafiaCommon\MafiaCommon.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,7 @@
namespace MafiaClient
{
public class MainConfig
{
public string Nick = "the Player";
}
}

View File

@ -0,0 +1,336 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="MafiaClient.MainWindow"
Title="MafiaClient"
Closing="Window_OnClosing">
<Grid>
<Grid x:Name="MainMenu" IsVisible="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="30*"></ColumnDefinition>
<ColumnDefinition Width="20*"></ColumnDefinition>
<ColumnDefinition Width="30*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="15*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="20*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Text="RMafia" FontSize="45" Grid.Row="1" Grid.Column="2" HorizontalAlignment="Center"></TextBlock>
<Button Grid.Row="3" Grid.Column="2" Click="Play_OnClick" FontSize="25" HorizontalAlignment="Stretch">
<Viewbox>
<TextBlock Text="Играть"></TextBlock>
</Viewbox>
</Button>
<Button Grid.Row="5" Grid.Column="2" FontSize="25" Click="Settings_OnClick" HorizontalAlignment="Stretch">
<Viewbox>
<TextBlock Text="Параметры"></TextBlock>
</Viewbox>
</Button>
<Button Grid.Row="7" Grid.Column="2" Click="Exit_OnClick" FontSize="25" HorizontalAlignment="Stretch">
<Viewbox>
<TextBlock Text="Выход"></TextBlock>
</Viewbox>
</Button>
</Grid>
<Grid x:Name="IpInput" IsVisible="False">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30*"></ColumnDefinition>
<ColumnDefinition Width="40*"></ColumnDefinition>
<ColumnDefinition Width="30*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="30*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="15*"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Text="Введите IP" FontSize="35" Grid.Column="1" Grid.Row="1" HorizontalAlignment="Center"></TextBlock>
<TextBox Grid.Column="1" Grid.Row="3" x:Name="IpBox" FontSize="30"></TextBox>
<Button Grid.Column="1" Grid.Row="5" Click="ConnectToServer_OnClick" x:Name="IpInputGuiConnect" HorizontalAlignment="Stretch">
<Viewbox>
<TextBlock Text="Подключиться" FontSize="25"></TextBlock>
</Viewbox>
</Button>
<Button Grid.Column="1" Grid.Row="7" Click="Back_OnClick" x:Name="IpInputGuiBack" HorizontalAlignment="Stretch">
<Viewbox>
<TextBlock Text="Назад" FontSize="25"></TextBlock>
</Viewbox>
</Button>
</Grid>
<Grid x:Name="SettingsGui" IsVisible="False">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="5*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Text="Ник:" FontSize="25" Grid.Column="1" Grid.Row="1" HorizontalAlignment="Right"></TextBlock>
<TextBox Grid.Column="2" Grid.ColumnSpan="2" Grid.Row="1" FontSize="25" x:Name="NickBox" TextInput="NickBox_OnTextInput"></TextBox>
<Button Grid.Column="4" Grid.ColumnSpan="3" Grid.Row="11" Click="SettingsBack_OnClick" HorizontalAlignment="Stretch">
<Viewbox>
<TextBlock Text="Назад" FontSize="25"></TextBlock>
</Viewbox>
</Button>
</Grid>
<Grid x:Name="GameQueue" IsVisible="False" KeyUp="GameQueue_OnKeyUp">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="5*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Text="Ожидаем старта" FontSize="30" Grid.Column="1" Grid.ColumnSpan="3" Grid.Row="1" HorizontalAlignment="Center"></TextBlock>
<TextBlock x:Name="QueueOnline" Grid.Column="1" Grid.ColumnSpan="3" Grid.Row="3" HorizontalAlignment="Center"></TextBlock>
<ScrollViewer Grid.Column="5" Grid.ColumnSpan="5" Grid.Row="1" Grid.RowSpan="8" x:Name="QueueChatViewer">
<ItemsRepeater x:Name="QueueChat"></ItemsRepeater>
</ScrollViewer>
<TextBox Grid.Column="5" Grid.ColumnSpan="4" Grid.Row="9" TextWrapping="Wrap" x:Name="QueueChatInput"></TextBox>
<Button Grid.Column="9" Grid.Row="9" Click="GameQueueChatSend_OnClick" HorizontalAlignment="Stretch">
<Viewbox>
<TextBlock Text="Отправить!"></TextBlock>
</Viewbox>
</Button>
<Button Grid.Column="1" Grid.ColumnSpan="3" Grid.Row="9" Click="GameQueueLeave_OnClick" HorizontalAlignment="Stretch">
<Viewbox>
<TextBlock Text="Выйти"></TextBlock>
</Viewbox>
</Button>
</Grid>
<Grid x:Name="DisconnectScreen" IsVisible="False">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*"></ColumnDefinition>
<ColumnDefinition Width="25*"></ColumnDefinition>
<ColumnDefinition Width="40*"></ColumnDefinition>
<ColumnDefinition Width="25*"></ColumnDefinition>
<ColumnDefinition Width="5*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="35*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Text="Отключён от сервера" FontSize="30" Grid.Column="2" Grid.Row="1" HorizontalAlignment="Center"></TextBlock>
<TextBlock Grid.Column="1" Grid.ColumnSpan="3" Grid.Row="3" x:Name="ReasonText" FontSize="25" HorizontalAlignment="Center" TextWrapping="Wrap"></TextBlock>
<Button Grid.Column="2" Grid.Row="6" Click="Back_OnClick" HorizontalAlignment="Stretch">
<Viewbox>
<TextBlock Text="Назад" FontSize="25"></TextBlock>
</Viewbox>
</Button>
</Grid>
<Grid x:Name="GameVotingPassive" IsVisible="False">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="5*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Grid.Row="1" Grid.Column="2" Grid.ColumnSpan="7" HorizontalAlignment="Center" FontSize="30" x:Name="GameVotingPassiveRole"></TextBlock>
<TextBlock Grid.Row="5" Grid.Column="2" Grid.ColumnSpan="7" Text="Спи спокойно, пока можешь" HorizontalAlignment="Center" FontSize="30"></TextBlock>
</Grid>
<Grid x:Name="GameVotingActive" IsVisible="False" KeyUp="GameVotingActive_OnKeyUp">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="5*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Grid.Row="1" Grid.Column="2" Grid.ColumnSpan="7" HorizontalAlignment="Center" FontSize="30" x:Name="GameVotingActiveRole"></TextBlock>
<ListBox Grid.Column="5" Grid.ColumnSpan="5" Grid.Row="2" Grid.RowSpan="8" x:Name="GameVotingActiveChat"></ListBox>
<TextBox Grid.Column="5" Grid.ColumnSpan="4" Grid.Row="10" TextWrapping="Wrap" x:Name="GameVotingActiveChatInput"></TextBox>
<Button Grid.Column="9" Grid.Row="10" Click="GameVotingActiveChatSend_OnClick" HorizontalAlignment="Stretch">
<Viewbox>
<TextBlock Text="Отправить!"></TextBlock>
</Viewbox>
</Button>
<ListBox Grid.Column="1" Grid.ColumnSpan="3" Grid.Row="2" Grid.RowSpan="8" x:Name="GameVotingActiveSelect" DoubleTapped="GameVotingActiveSelect_OnMouseDoubleClick" SelectionMode="Single"></ListBox>
</Grid>
<Grid x:Name="GameEndScreen" IsVisible="False">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*"></ColumnDefinition>
<ColumnDefinition Width="25*"></ColumnDefinition>
<ColumnDefinition Width="40*"></ColumnDefinition>
<ColumnDefinition Width="25*"></ColumnDefinition>
<ColumnDefinition Width="5*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="35*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock x:Name="GameEndScreenWon" Grid.Column="2" Grid.Row="1" FontSize="30" HorizontalAlignment="Center"></TextBlock>
<TextBlock x:Name="GameEndScreenRoles" FontSize="25" Grid.Column="1" Grid.ColumnSpan="3" Grid.Row="3" HorizontalAlignment="Center" TextWrapping="Wrap"></TextBlock>
<Button Grid.Column="2" Grid.Row="6" Click="GameEndScreenBack_OnClick" HorizontalAlignment="Stretch">
<Viewbox>
<TextBlock Text="Назад" FontSize="25"></TextBlock>
</Viewbox>
</Button>
</Grid>
<Grid x:Name="GameDay" IsVisible="False" KeyUp="GameDayWait_OnKeyUp">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="10*"></ColumnDefinition>
<ColumnDefinition Width="5*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="10*"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock FontSize="30" x:Name="GameDayHotBar" Text="Обсуждай и думай" Grid.Row="1" Grid.Column="2" Grid.ColumnSpan="7" HorizontalAlignment="Center" TextAlignment="Center"></TextBlock>
<ListBox Grid.Column="5" Grid.ColumnSpan="5" Grid.Row="2" Grid.RowSpan="8" x:Name="GameDayChat"></ListBox>
<TextBox Grid.Column="5" Grid.ColumnSpan="4" Grid.Row="10" TextWrapping="Wrap" x:Name="GameDayChatInput"></TextBox>
<Button Grid.Column="9" Grid.Row="10" Click="GameDayChatSend_OnClick" HorizontalAlignment="Stretch">
<Viewbox>
<TextBlock Text="Отправить!"></TextBlock>
</Viewbox>
</Button>
<ListBox Grid.Column="1" Grid.ColumnSpan="3" Grid.Row="2" Grid.RowSpan="8" x:Name="GameDaySelect" DoubleTapped="GameDaySelect_OnMouseDoubleClick" SelectionMode="Single"></ListBox>
</Grid>
</Grid>
</Window>

View File

@ -0,0 +1,304 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using DiscordRPC;
using MafiaCommon;
using Button = Avalonia.Controls.Button;
namespace MafiaClient
{
public class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
#if DEBUG
this.AttachDevTools();
#endif
_mainWindow = this;
App.Instance.GetRpcClient().SetPresence(new RichPresence()
{
State = "В главном меню"
});
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
private static MainWindow _mainWindow;
public static MainWindow Instance => _mainWindow;
public void HideAll()
{
this.Find<Grid>("MainMenu").IsVisible = false;
this.Find<Grid>("SettingsGui").IsVisible = false;
this.Find<Grid>("IpInput").IsVisible = false;
this.Find<Grid>("GameQueue").IsVisible = false;
this.Find<Grid>("DisconnectScreen").IsVisible = false;
this.Find<Grid>("GameVotingPassive").IsVisible = false;
this.Find<Grid>("GameVotingActive").IsVisible = false;
this.Find<Grid>("GameEndScreen").IsVisible = false;
this.Find<Grid>("GameDay").IsVisible = false;
}
private void IpInputEnable(bool enable)
{
this.FindControl<Button>("IpInputGuiBack").IsEnabled = enable;
this.FindControl<Button>("IpInputGuiConnect").IsEnabled = enable;
this.FindControl<TextBox>("IpBox").IsEnabled = enable;
}
private void Exit_OnClick(object sender, RoutedEventArgs e)
{
Close();
}
private void Play_OnClick(object sender, RoutedEventArgs e)
{
IpInputEnable(true);
HideAll();
this.Find<Grid>("IpInput").IsVisible = true;
App.Instance.GetRpcClient().SetPresence(new RichPresence()
{
State = "Выбирает сервер"
});
}
private void ConnectToServer_OnClick(object sender, RoutedEventArgs e)
{
String ip = this.FindControl<TextBox>("IpBox").Text ?? "";
App.Instance.GetRpcClient().SetPresence(new RichPresence()
{
State = "Присоединяется к серверу"
});
IpInputEnable(false);
Thread thread = new Thread(() =>
{
App.Instance.Connection = new ServerConnection(ip);
});
thread.Start();
}
private void Back_OnClick(object sender, RoutedEventArgs e)
{
HideAll();
this.Find<Grid>("MainMenu").IsVisible = true;
App.Instance.GetRpcClient().SetPresence(new RichPresence()
{
State = "В главном меню"
});
}
private void SettingsBack_OnClick(object sender, RoutedEventArgs e)
{
Settings.Save();
HideAll();
this.Find<Grid>("MainMenu").IsVisible = true;
App.Instance.GetRpcClient().SetPresence(new RichPresence()
{
State = "В главном меню"
});
}
private void Settings_OnClick(object sender, RoutedEventArgs e)
{
HideAll();
this.Find<Grid>("SettingsGui").IsVisible = true;
this.FindControl<TextBox>("NickBox").Text = Settings.Config().Nick;
}
private void NickBox_OnTextInput(object sender, TextInputEventArgs e)
{
Settings.Config().Nick = this.FindControl<TextBox>("NickBox").Text;
}
public void ShowGameQueueScreen()
{
HideAll();
this.Find<Grid>("GameQueue").IsVisible = true;
}
public void ShowDisconnectScreen(string reason)
{
this.Find<TextBlock>("ReasonText").Text = reason;
HideAll();
this.Find<Grid>("DisconnectScreen").IsVisible = true;
}
private void GameQueue_OnKeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
GameQueueChatSend_OnClick(null, null);
}
}
private void GameQueueChatSend_OnClick(object sender, RoutedEventArgs e)
{
if (this.FindControl<TextBox>("QueueChatInput").Text != null)
{
if (this.FindControl<TextBox>("QueueChatInput").Text.Trim() != "")
{
App.Instance.Connection.SendMessage(ChatType.Queue,
this.FindControl<TextBox>("QueueChatInput").Text);
this.FindControl<TextBox>("QueueChatInput").Clear();
}
}
}
public void ShowVotingPassive(string name)
{
HideAll();
this.Find<Grid>("GameVotingPassive").IsVisible = true;
this.Find<TextBlock>("GameVotingPassiveRole").Text = name;
}
public void ShowVotingActive(string name)
{
HideAll();
this.Find<Grid>("GameVotingActive").IsVisible = true;
this.Find<TextBlock>("GameVotingPassiveRole").Text = name;
}
private void GameVotingActiveChatSend_OnClick(object sender, RoutedEventArgs e)
{
if (this.FindControl<TextBox>("GameVotingActiveChatInput").Text != null)
{
if (this.FindControl<TextBox>("GameVotingActiveChatInput").Text.Trim() != "")
{
App.Instance.Connection.SendMessage(ChatType.Active,
this.FindControl<TextBox>("GameVotingActiveChatInput").Text);
this.FindControl<TextBox>("GameVotingActiveChatInput").Clear();
}
}
}
private void GameVotingActive_OnKeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
GameVotingActiveChatSend_OnClick(null, null);
}
}
public void ShowGameEnd(bool isWon, List<PlayerRole> playerRoles)
{
this.Find<TextBlock>("GameEndScreenWon").Text = isWon ? "Ты победил!" : "Ты проиграл!";
string text = "";
foreach (PlayerRole playerRole in playerRoles)
{
string role = "Роль";
switch (playerRole.Role)
{
case Role.Citizen:
role = "Мирный житель";
break;
case Role.Mafia:
role = "Мафия";
break;
case Role.Don:
role = "Дон";
break;
}
text += playerRole.Name + " - " + role + Environment.NewLine;
}
this.Find<TextBlock>("GameEndScreenRoles").Text = text;
HideAll();
this.Find<Grid>("GameEndScreen").IsVisible = true;
}
private void GameEndScreenBack_OnClick(object sender, RoutedEventArgs e)
{
HideAll();
this.Find<Grid>("GameQueue").IsVisible = true;
}
private void GameQueueLeave_OnClick(object sender, RoutedEventArgs e)
{
App.Instance.Connection.Disconnect();
HideAll();
this.Find<Grid>("MainMenu").IsVisible = true;
App.Instance.GetRpcClient().SetPresence(new RichPresence()
{
State = "В главном меню"
});
}
private void GameVotingActiveSelect_OnMouseDoubleClick(object sender, RoutedEventArgs e)
{
ListBoxItem selected = (ListBoxItem)(this.FindControl<ListBox>("GameVotingActiveSelect").SelectedItem);
App.Instance.Connection.Vote(Convert.ToInt32(((string)selected.Content).Split(")")[0]));
}
private void GameDayWait_OnKeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
GameDayChatSend_OnClick(null, null);
}
}
private void GameDayChatSend_OnClick(object sender, RoutedEventArgs e)
{
if (this.FindControl<TextBox>("GameDayChatInput").Text != null)
{
if (this.FindControl<TextBox>("GameDayChatInput").Text.Trim() != "")
{
App.Instance.Connection.SendMessage(ChatType.Day,
this.FindControl<TextBox>("GameDayChatInput").Text);
this.FindControl<TextBox>("GameDayChatInput").Clear();
}
}
}
private void GameDaySelect_OnMouseDoubleClick(object sender, RoutedEventArgs e)
{
ListBoxItem selected = (ListBoxItem)(this.FindControl<ListBox>("GameDaySelect").SelectedItem);
App.Instance.Connection.Vote(Convert.ToInt32(((string)selected.Content).Split(")")[0]));
}
public void ShowDay(bool voting, Role role, List<Player> players)
{
this.FindControl<ListBox>("GameDaySelect").IsEnabled = voting;
List<ListBoxItem> items = new List<ListBoxItem>();
foreach (Player player in players)
{
items.Add(new ListBoxItem {Content = player.Id.ToString() + ") " + player.Name});
}
this.FindControl<ListBox>("GameDaySelect").Items = items;
if (role == Role.Died)
{
this.Find<TextBlock>("GameDayHotBar").Text = "Коли умер, жди";
}
else
{
this.Find<TextBlock>("GameDayHotBar").Text = voting ? "Голосуй и молись" : "Обсуждай и думай";
}
this.Find<Grid>("GameDay").IsVisible = true;
}
private void Window_OnClosing(object? sender, CancelEventArgs e)
{
App.Instance.GetRpcClient().Dispose();
}
}
}

22
MafiaClient/Program.cs Normal file
View File

@ -0,0 +1,22 @@
using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
namespace MafiaClient
{
class Program
{
// Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
public static void Main(string[] args) => BuildAvaloniaApp()
.StartWithClassicDesktopLifetime(args);
// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
.LogToTrace();
}
}

View File

@ -0,0 +1,323 @@
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using Avalonia.Controls;
using Avalonia.Threading;
using DiscordRPC;
using MafiaCommon.Packets;
using MafiaCommon;
namespace MafiaClient
{
public class ServerConnection
{
private readonly String _host = "localhost";
private readonly int _port = 25743;
private readonly Socket _socket;
private readonly Thread _thread;
private bool _breakFlag;
private bool _connected;
public ServerConnection(String ip)
{
if (ip.Contains(':'))
{
_host = ip.Split(":")[0];
_port = Convert.ToInt32(ip.Split(":")[1]);
}
else if (_host.Length != 0)
{
_host = ip;
}
_thread = new Thread(ServerListener);
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
_socket.Connect(_host, _port);
}
catch (Exception e)
{
Dispatcher.UIThread.InvokeAsync(() => { MainWindow.Instance.ShowDisconnectScreen(e.Message); });
return;
}
_socket.Send(PacketConverter.ToBytes(new ConnectPacket(Settings.Config().Nick)));
_thread.IsBackground = true;
_thread.Start();
_connected = true;
}
public void AddMessageToChat(String chatName, ListBoxItem message)
{
ItemsRepeater listBoxes = MainWindow.Instance.Find<ItemsRepeater>(chatName);
if (listBoxes.Items == null || listBoxes.Items.GetType() != typeof(List<ListBoxItem>))
{
List<ListBoxItem> items = new List<ListBoxItem>();
items.Add(message);
listBoxes.Items = items;
}
else
{
List<ListBoxItem> items = (List<ListBoxItem>) listBoxes.Items;
List<ListBoxItem> list = new List<ListBoxItem>();
list.AddRange(items);
list.Add(message);
listBoxes.Items = list;
}
MainWindow.Instance.FindControl<ScrollViewer>("QueueChatViewer").ScrollToEnd();
}
public void SendMessage(ChatType chatType, string text)
{
_socket.Send(PacketConverter.ToBytes(new MessageSendPacket(chatType, text)));
}
public void Disconnect()
{
_connected = false;
_socket.Send(PacketConverter.ToBytes(new DisconnectPlayerPacket()));
_thread.Interrupt();
_socket.Close();
}
public void Vote(int id)
{
_socket.Send(PacketConverter.ToBytes(new VotePacket(id)));
}
private void ServerListener()
{
while (!_breakFlag)
{
StringBuilder builder = new StringBuilder();
byte[] data = new byte[256];
try
{
do
{
var bytes = _socket.Receive(data);
builder.Append(Encoding.UTF8.GetString(data, 0, bytes));
} while (_socket.Available > 0);
}
catch (Exception e)
{
_socket.Close();
if (_connected)
{
MainWindow.Instance.HideAll();
MainWindow.Instance.ShowDisconnectScreen(e.Message);
_connected = false;
}
_breakFlag = true;
}
if (!_breakFlag)
{
Console.WriteLine(builder.ToString());
List<Packet> packets = PacketConverter.ToPacket(builder.ToString());
foreach (Packet packet in packets)
{
WorkPacket(packet);
}
}
}
}
private void WorkPacket(Packet packet)
{
Dispatcher.UIThread.InvokeAsync(() =>
{
switch (packet.PacketType)
{
case PacketType.Welcome:
MainWindow.Instance.Find<TextBlock>("QueueOnline").Text = ((WelcomePacket) packet).Players +
"/" +
((WelcomePacket) packet).MaxPlayers;
MainWindow.Instance.ShowGameQueueScreen();
Party party = new Party
{
ID = _host + ":" + _port,
Size = ((WelcomePacket) packet).Players,
Max = ((WelcomePacket) packet).MaxPlayers
};
Secrets secrets = new Secrets
{
JoinSecret = _host + ":" + _port + "/join",
SpectateSecret = _host + ":" + _port + "/spectate"
};
App.Instance.GetRpcClient().SetPresence(new RichPresence()
{
State = ((WelcomePacket) packet).ServerName,
Party = party,
Secrets = secrets,
Timestamps = Timestamps.Now,
Details = "Ожидание старта"
});
break;
case PacketType.Disconnect:
MainWindow.Instance.ShowDisconnectScreen(((DisconnectPacket) packet).Reason);
_breakFlag = true;
break;
case PacketType.PlayerConnected:
MainWindow.Instance.Find<TextBlock>("QueueOnline").Text =
((PlayerConnectedPacket) packet).Players + "/" +
((PlayerConnectedPacket) packet).MaxPlayers;
try
{
App.Instance.GetRpcClient().UpdatePartySize(((PlayerConnectedPacket) packet).Players);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
break;
case PacketType.PlayerDisconnected:
MainWindow.Instance.Find<TextBlock>("QueueOnline").Text =
((PlayerDisconnectedPacket) packet).Players + "/" +
((PlayerDisconnectedPacket) packet).MaxPlayers;
try
{
App.Instance.GetRpcClient().UpdatePartySize(((PlayerDisconnectedPacket) packet).Players);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
break;
case PacketType.ServerShutdown:
MainWindow.Instance.ShowDisconnectScreen("Сервер выключен: " +
((ServerShutdownPacket) packet).Reason);
_breakFlag = true;
break;
case PacketType.MessageReceivePacket:
ListBoxItem message = new ListBoxItem();
if (((MessageReceivePacket) packet).IsSystem)
{
message.Content = ((MessageReceivePacket) packet).Text;
}
else
{
message.Content = ((MessageReceivePacket) packet).Author + ": " +
((MessageReceivePacket) packet).Text;
}
switch (((MessageReceivePacket) packet).ChatType)
{
case ChatType.Queue:
AddMessageToChat("QueueChat",message);
break;
case ChatType.Active:
AddMessageToChat("GameVotingActiveChat",message);
break;
case ChatType.Day:
AddMessageToChat("GameDayChat",message);
break;
}
break;
case PacketType.GameStartPacket:
List<Player> players = ((GameStartPacket) packet).Players;
switch (((GameStartPacket) packet).Role)
{
case Role.Citizen:
MainWindow.Instance.HideAll();
MainWindow.Instance.ShowVotingPassive("Ты Мирный Житель");
break;
case Role.Don:
MainWindow.Instance.HideAll();
List<ListBoxItem> items = new List<ListBoxItem>();
MainWindow.Instance.ShowVotingActive("Ты Дон, выбери кого убить!");
foreach (Player player in players)
{
ListBoxItem item = new ListBoxItem
{
Content = player.Id.ToString() + ") " + player.Name
};
items.Add(item);
}
MainWindow.Instance.FindControl<ListBox>("GameVotingActiveSelect").Items = items;
break;
case Role.Mafia:
MainWindow.Instance.HideAll();
items = new List<ListBoxItem>();
MainWindow.Instance.ShowVotingActive("Ты Мафия, выбери кого убить!");
foreach (Player player in players)
{
ListBoxItem item = new ListBoxItem
{
Content = player.Id.ToString() + ") " + player.Name
};
items.Add(item);
}
MainWindow.Instance.FindControl<ListBox>("GameVotingActiveSelect").Items = items;
break;
}
App.Instance.GetRpcClient().UpdateDetails("Ночь");
break;
case PacketType.EndGame:
MainWindow.Instance.ShowGameEnd(((EndGamePacket) packet).IsWon,
((EndGamePacket) packet).PlayerRoles);
App.Instance.GetRpcClient().UpdateDetails("Ожидание старта");
break;
case PacketType.GameStateChanged:
MainWindow.Instance.HideAll();
players = ((GameStageChangedPacket) packet).Players;
switch (((GameStageChangedPacket) packet).GameState)
{
case GameState.Day:
MainWindow.Instance.ShowDay(false, ((GameStageChangedPacket) packet).Role, players);
App.Instance.GetRpcClient().UpdateDetails("День");
break;
case GameState.VotingDay:
MainWindow.Instance.ShowDay(true, ((GameStageChangedPacket) packet).Role, players);
App.Instance.GetRpcClient().UpdateDetails("Голосование!");
break;
case GameState.VotingNight:
switch (((GameStageChangedPacket) packet).Role)
{
case Role.Citizen:
case Role.Died:
String rol = ((GameStageChangedPacket) packet).Role == Role.Citizen
? "Мирный житель"
: "Мёртв";
MainWindow.Instance.ShowVotingPassive("Ты " + rol + "!");
break;
case Role.Mafia:
case Role.Don:
rol = ((GameStageChangedPacket) packet).Role == Role.Mafia
? "Мафия"
: "Дон";
List<ListBoxItem> items = new List<ListBoxItem>();
MainWindow.Instance.ShowVotingActive("Ты " + rol + ", выбери кого убить!");
foreach (Player player in players)
{
ListBoxItem item = new ListBoxItem
{
Content = player.Id.ToString() + ") " + player.Name
};
items.Add(item);
}
MainWindow.Instance.FindControl<ListBox>("GameVotingActiveSelect").Items = items;
break;
}
break;
}
break;
}
});
}
}
}

33
MafiaClient/Settings.cs Normal file
View File

@ -0,0 +1,33 @@
using System.IO;
using Newtonsoft.Json;
namespace MafiaClient
{
public class Settings
{
private static MainConfig _config;
public static MainConfig Config()
{
return _config;
}
public static void Initialize()
{
try
{
_config = JsonConvert.DeserializeObject<MainConfig>(File.ReadAllText("config.json"));
}
catch (FileNotFoundException)
{
_config = new MainConfig();
File.Create("config.json").Close();
}
}
public static void Save()
{
File.WriteAllText("config.json",JsonConvert.SerializeObject(_config,Formatting.Indented));
}
}
}

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>

View File

@ -6,6 +6,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MafiaServer", "MafiaServer\
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MafiaCommon", "MafiaCommon\MafiaCommon.csproj", "{F2F93699-D38E-4416-84C3-7455BAEEB5E0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MafiaClient", "MafiaClient\MafiaClient.csproj", "{20AEF294-7ED4-4205-92A5-69E043AC1607}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -24,5 +26,9 @@ Global
{F2F93699-D38E-4416-84C3-7455BAEEB5E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F2F93699-D38E-4416-84C3-7455BAEEB5E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F2F93699-D38E-4416-84C3-7455BAEEB5E0}.Release|Any CPU.Build.0 = Release|Any CPU
{20AEF294-7ED4-4205-92A5-69E043AC1607}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{20AEF294-7ED4-4205-92A5-69E043AC1607}.Debug|Any CPU.Build.0 = Debug|Any CPU
{20AEF294-7ED4-4205-92A5-69E043AC1607}.Release|Any CPU.ActiveCfg = Release|Any CPU
{20AEF294-7ED4-4205-92A5-69E043AC1607}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

View File

@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net5.0-windows</TargetFramework>
<UseWPF>true</UseWPF>
</PropertyGroup>

View File

@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>