first commit

This commit is contained in:
Beyhan Oğur
2026-09-03 04:45:36 +03:00
commit d5f52cc3d3
1038 changed files with 169579 additions and 0 deletions
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
</configuration>
+318
View File
@@ -0,0 +1,318 @@
<Application x:Class="ClassicAssist.Launcher.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ClassicAssist.Launcher"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<DrawingImage x:Key="PlayIcon">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V512 H512 V0 H0 Z">
<GeometryDrawing Brush="#FFDEECF1"
Geometry="F1 M512,512z M0,0z M256,512C115.390625,512 0,396.609375 0,256 0,115.390625 115.390625,0 256,0 396.609375,0 512,115.390625 512,256 512,396.609375 396.609375,512 256,512z M256,512" />
<GeometryDrawing Brush="#FFC6E2E7"
Geometry="F1 M512,512z M0,0z M512,256C512,115.390625,396.609375,0,256,0L256,512C396.609375,512,512,396.609375,512,256z M512,256" />
<GeometryDrawing Brush="#FF384949"
Geometry="F1 M512,512z M0,0z M181,107.976562L181,404.023438 403.039062,256z M181,107.976562" />
<GeometryDrawing Brush="#FF293939"
Geometry="F1 M512,512z M0,0z M256,354.023438L403.039062,256 256,157.976562z M256,354.023438" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="RefreshButton">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V512 H512 V0 H0 Z">
<GeometryDrawing Brush="#FF32D736"
Geometry="F1 M512,512z M0,0z M443.5,15.099C441.7,3.1,426.7,-2.001,418.001,6.7L387.1,37.599C347.5,13.599 302.5,0 256,0 116.499,0 3.6,110.2 0,249.399 0,257.199 5.4,263.8 12.9,264.699L73.9,273.398C82.9,274.599 91,267.7 91,258.398 90.399,213.698 107.199,172 138.701,140.2 169.9,108.399 211.601,91 256,91 278.2,91 300.399,95.499 320.501,104.2L290.799,133.9C282.1,142.599,287.199,157.599,299.2,159.399L447.7,180.7C457.599,182.2,466.3,173.5,464.8,163.6L443.5,15.099z" />
<GeometryDrawing Brush="#FFFD003A"
Geometry="F1 M512,512z M0,0z M499.1,248.5L438.1,239.799C430,238.9 421,245.799 421,256 421,346.899 346.901,421 256,421 233.8,421 211.901,416.499 191.8,407.8L220.601,378.999C229.3,370.3,224.201,355.3,211.902,353.8L63.401,332.5C53.801,331,45.1,339.399,46.601,349.3L67.9,497.8C69.401,510.099,84.401,515.201,93.101,506.499L124.901,474.699C164.5,498.399 209.5,512 256,512 394.9,512 507.8,402.4 512,263.8 512,256 506.6,249.399 499.1,248.5z" />
<GeometryDrawing Brush="#FF10BB67"
Geometry="F1 M512,512z M0,0z M320.501,104.2C300.399,95.499,278.2,91,256,91L256,0C302.5,0,347.5,13.599,387.1,37.599L418.001,6.7C426.7,-2.001,441.7,3.1,443.5,15.099L464.801,163.599C466.301,173.5,457.599,182.199,447.701,180.699L299.201,159.398C287.2,157.598,282.101,142.598,290.8,133.899L320.501,104.2z" />
<GeometryDrawing Brush="#FFE50027"
Geometry="F1 M512,512z M0,0z M512,263.8C507.8,402.4,394.9,512,256,512L256,421C346.901,421 421,346.899 421,256 421,245.799 430,238.9 438.1,239.799L499.1,248.5C506.6,249.399,512,256,512,263.8z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="AddIcon">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V512 H512 V0 H0 Z">
<DrawingGroup Opacity="1">
<DrawingGroup Opacity="1">
<GeometryDrawing Brush="#FF000000"
Geometry="F1 M512,512z M0,0z M492,236L276,236 276,20C276,8.954 267.046,0 256,0 244.954,0 236,8.954 236,20L236,236 20,236C8.954,236 0,244.954 0,256 0,267.046 8.954,276 20,276L236,276 236,492C236,503.046 244.954,512 256,512 267.046,512 276,503.046 276,492L276,276 492,276C503.046,276 512,267.046 512,256 512,244.954 503.046,236 492,236z" />
</DrawingGroup>
</DrawingGroup>
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="RemoveIcon">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V512.001 H512.001 V0 H0 Z">
<DrawingGroup Opacity="1">
<DrawingGroup Opacity="1">
<GeometryDrawing Brush="#FF000000"
Geometry="F1 M512.001,512.001z M0,0z M294.111,256.001L504.109,46.003C514.632,35.479 514.632,18.417 504.109,7.894 493.585,-2.63 476.522,-2.63 465.999,7.894L256,217.892 46.002,7.894C35.478,-2.63 18.416,-2.63 7.893,7.894 -2.63,18.418 -2.631,35.48 7.893,46.003L217.891,256.001 7.893,465.999C-2.631,476.523 -2.631,493.585 7.893,504.108 18.417,514.632 35.479,514.631 46.002,504.108L256,294.11 465.997,504.108C476.521,514.632 493.584,514.631 504.107,504.108 514.63,493.584 514.63,476.522 504.107,465.999L294.111,256.001z" />
</DrawingGroup>
</DrawingGroup>
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="RefreshIcon">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V512 H512 V0 H0 Z">
<GeometryDrawing Brush="#FF000000"
Geometry="F1 M512,512z M0,0z M61.496094,279.609375C60.507812,271.375 60,263.195312 60,256 60,148.597656 148.597656,60 256,60 306.097656,60 353,80.199219 387.5,111.699219L370.199219,129.300781C366.300781,133.199219 364.800781,138.898438 366.300781,144.300781 368.101562,149.398438 372.300781,153.300781 377.699219,154.5 380.71875,155.105469 479.914062,187.070312 473.597656,185.800781 481.632812,188.476562 493.515625,179.90625 491.300781,168.101562 490.691406,165.078125 468.730469,54.886719 470,61.199219 468.800781,55.800781 464.898438,51.300781 459.5,49.800781 454.402344,48.300781 448.699219,49.800781 444.800781,53.699219L430.101562,68.097656C384.800781,25.800781 322.597656,0 256,0 115.300781,0 5.6843418860808E-14,115.300781 5.6843418860808E-14,256L5.6843418860808E-14,256.597656C5.6843418860808E-14,265.054688 0.386719000000057,271.589844 0.835938000000057,276.589844 1.43359400000006,283.214844 6.31640600000006,288.640625 12.8398440000001,289.949219L43.6562500000001,296.109375C53.6875000000001,298.117188,62.7070310000001,289.707031,61.4960940000001,279.609375z M61.496094,279.609375" />
<GeometryDrawing Brush="#FF000000"
Geometry="F1 M512,512z M0,0z M499.25,222.027344L468.34375,215.730469C458.300781,213.683594 449.21875,222.101562 450.453125,232.246094 451.523438,241 452,249.511719 452,256 452,363.398438 363.402344,452 256,452 205.902344,452 159,431.800781 124.5,400L141.800781,382.699219C145.699219,378.800781 147.199219,373.101562 145.699219,367.699219 143.898438,362.597656 139.699219,358.699219 134.300781,357.5 131.28125,356.890625 32.085938,324.929688 38.402344,326.199219 33.300781,325.300781 28.199219,326.800781 24.902344,330.398438 21.300781,333.699219 19.800781,339.097656 20.699219,343.898438 21.308594,346.917969 43.273438,456.109375 42.003906,449.796875 43.199219,455.199219 47.101562,459.699219 52.5,461.195312 58.761719,462.765625 63.988281,460.867188 67.199219,457.296875L81.601562,442.898438C126.898438,485.199219 189.101562,512 256,512 396.699219,512 512,396.699219 512,256L512,255.097656C512,248.449219 511.757812,241.921875 511.203125,235.433594 510.632812,228.804688 505.769531,223.359375 499.25,222.027344z M499.25,222.027344" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="OptionsIcon">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,-76 V436 H512 V0 H-76 Z">
<DrawingGroup.Transform>
<TranslateTransform X="0" Y="76" />
</DrawingGroup.Transform>
<DrawingGroup Opacity="1">
<GeometryDrawing Brush="#FF1B5C91"
Geometry="F1 M512,512z M0,0z M0,44.59375L512,44.59375 512,74.59375 0,74.59375z M0,44.59375" />
<GeometryDrawing Brush="#FF1B5C91"
Geometry="F1 M512,512z M0,0z M0,165.09375L512,165.09375 512,195.09375 0,195.09375z M0,165.09375" />
<GeometryDrawing Brush="#FF1B5C91"
Geometry="F1 M512,512z M0,0z M0,290.574219L512,290.574219 512,320.574219 0,320.574219z M0,290.574219" />
</DrawingGroup>
<GeometryDrawing Brush="#FF0E2E4B"
Geometry="F1 M512,512z M0,0z M264.410156,290.574219L512,290.574219 512,320.574219 264.410156,320.574219z M264.410156,290.574219" />
<GeometryDrawing Brush="#FFFB4C2E"
Geometry="F1 M512,512z M0,0z M96.152344,125.484375C66.042969,125.484375 41.546875,149.980469 41.546875,180.09375 41.546875,210.203125 66.042969,234.699219 96.152344,234.699219 126.265625,234.699219 150.761719,210.203125 150.761719,180.09375 150.761719,149.980469 126.265625,125.484375 96.152344,125.484375z M96.152344,125.484375" />
<GeometryDrawing Brush="#FFFDBF00"
Geometry="F1 M512,512z M0,0z M264.410156,250.964844C234.296875,250.964844 209.800781,275.464844 209.800781,305.574219 209.800781,335.683594 234.296875,360.183594 264.410156,360.183594 294.519531,360.183594 319.019531,335.683594 319.019531,305.574219 319.019531,275.464844 294.519531,250.964844 264.410156,250.964844z M264.410156,250.964844" />
<GeometryDrawing Brush="#FFFF9100"
Geometry="F1 M512,512z M0,0z M264.410156,250.964844L264.410156,360.183594C294.519531,360.183594 319.019531,335.6875 319.019531,305.574219 319.019531,275.464844 294.519531,250.964844 264.410156,250.964844z M264.410156,250.964844" />
<GeometryDrawing Brush="#FF0E2E4B"
Geometry="F1 M512,512z M0,0z M264.410156,44.59375L512,44.59375 512,74.59375 264.410156,74.59375z M264.410156,44.59375" />
<GeometryDrawing Brush="#FF0E2E4B"
Geometry="F1 M512,512z M0,0z M264.410156,165.09375L512,165.09375 512,195.09375 264.410156,195.09375z M264.410156,165.09375" />
<GeometryDrawing Brush="#FF00D7DF"
Geometry="F1 M512,512z M0,0z M373.828125,0C343.71875,0 319.21875,24.496094 319.21875,54.609375 319.21875,84.71875 343.71875,109.21875 373.828125,109.21875 403.941406,109.21875 428.4375,84.71875 428.4375,54.609375 428.4375,24.496094 403.941406,0 373.828125,0z M373.828125,0" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
<SolidColorBrush x:Key="ToolBarHorizontalBackground" Color="#FFEEF5FD" />
<SolidColorBrush x:Key="ToolBarToggleButtonVerticalBackground" Color="#FFEEF5FD" />
<SolidColorBrush x:Key="ToolBarButtonHover" Color="#210080FF" />
<SolidColorBrush x:Key="ToolBarGripper" Color="#FF6D6D6D" />
<Style x:Key="ToolBarVerticalOverflowButtonStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="MinHeight" Value="0" />
<Setter Property="MinWidth" Value="0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border x:Name="Bd" SnapsToDevicePixels="true" CornerRadius="0,0,3,3"
Background="{TemplateBinding Background}">
<Canvas Width="7" VerticalAlignment="Bottom" SnapsToDevicePixels="true"
Margin="2,7,2,2" Height="6" HorizontalAlignment="Right">
<Path Data="M 1.5 1 L 1.5 6" Stroke="White" />
<Path Data="M 0.5 0 L 0.5 5" Stroke="{TemplateBinding Foreground}" />
<Path Data="M 3.5 0.5 L 7 3.5 L 4 6.5 Z" Fill="White" />
<Path Data="M 3 -0.5 L 6 2.5 L 3 5.5 Z" Fill="{TemplateBinding Foreground}" />
</Canvas>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" TargetName="Bd"
Value="{StaticResource ToolBarButtonHover}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter Property="Background" TargetName="Bd"
Value="{StaticResource ToolBarButtonHover}" />
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{StaticResource ToolBarGripper}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding Source={x:Static SystemParameters.HighContrast}}" Value="true">
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />
</DataTrigger>
</Style.Triggers>
</Style>
<SolidColorBrush x:Key="ToolBarVerticalBackground" Color="#FFEEF5FD" />
<SolidColorBrush x:Key="ToolBarToggleButtonHorizontalBackground" Color="#FFEEF5FD" />
<Style x:Key="ToolBarHorizontalOverflowButtonStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="MinHeight" Value="0" />
<Setter Property="MinWidth" Value="0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border x:Name="Bd" SnapsToDevicePixels="true" CornerRadius="0,3,3,0"
Background="{TemplateBinding Background}">
<Canvas Width="6" VerticalAlignment="Bottom" SnapsToDevicePixels="true"
Margin="7,2,2,2" Height="7" HorizontalAlignment="Right">
<Path Data="M 1 1.5 L 6 1.5" Stroke="White" />
<Path Data="M 0 0.5 L 5 0.5" Stroke="{TemplateBinding Foreground}" />
<Path Data="M 0.5 4 L 6.5 4 L 3.5 7 Z" Fill="White" />
<Path Data="M -0.5 3 L 5.5 3 L 2.5 6 Z" Fill="{TemplateBinding Foreground}" />
</Canvas>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" TargetName="Bd"
Value="{StaticResource ToolBarButtonHover}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter Property="Background" TargetName="Bd"
Value="{StaticResource ToolBarButtonHover}" />
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{StaticResource ToolBarGripper}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding Source={x:Static SystemParameters.HighContrast}}" Value="true">
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />
</DataTrigger>
</Style.Triggers>
</Style>
<SolidColorBrush x:Key="ToolBarMenuBorder" Color="#FFB6BDC5" />
<SolidColorBrush x:Key="ToolBarSubMenuBackground" Color="#FFEEF5FD" />
<Style x:Key="ToolBarThumbStyle" TargetType="{x:Type Thumb}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Border SnapsToDevicePixels="True" Padding="{TemplateBinding Padding}"
Background="Transparent">
<Rectangle>
<Rectangle.Fill>
<DrawingBrush ViewboxUnits="Absolute" ViewportUnits="Absolute"
Viewport="0,0,4,4" Viewbox="0,0,4,4" TileMode="Tile">
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="White" Geometry="M 1 1 L 1 3 L 3 3 L 3 1 z" />
<GeometryDrawing Brush="{StaticResource ToolBarGripper}"
Geometry="M 0 0 L 0 2 L 2 2 L 2 0 z" />
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Rectangle.Fill>
</Rectangle>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Cursor" Value="SizeAll" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ToolBarMainPanelBorderStyle" TargetType="{x:Type Border}">
<Setter Property="Margin" Value="0,0,11,0" />
<Setter Property="CornerRadius" Value="3,3,3,3" />
<Style.Triggers>
<DataTrigger Binding="{Binding Source={x:Static SystemParameters.HighContrast}}" Value="true">
<Setter Property="CornerRadius" Value="0,0,0,0" />
</DataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="ToolBarStyle1" TargetType="{x:Type ToolBar}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToolBar}">
<Grid x:Name="Grid" Margin="3,1,1,1" SnapsToDevicePixels="true">
<Grid x:Name="OverflowGrid" HorizontalAlignment="Right">
<ToggleButton x:Name="OverflowButton" ClickMode="Press" FocusVisualStyle="{x:Null}"
IsChecked="{Binding IsOverflowOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
IsEnabled="{TemplateBinding HasOverflowItems}"
Style="{StaticResource ToolBarHorizontalOverflowButtonStyle}" />
<Popup x:Name="OverflowPopup" AllowsTransparency="true" Focusable="false"
IsOpen="{Binding IsOverflowOpen, RelativeSource={RelativeSource TemplatedParent}}"
PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}"
Placement="Bottom" StaysOpen="false">
<Border x:Name="ToolBarSubMenuBorder"
BorderBrush="{StaticResource ToolBarMenuBorder}"
BorderThickness="1"
Background="{StaticResource ToolBarSubMenuBackground}"
RenderOptions.ClearTypeHint="Enabled">
<ToolBarOverflowPanel x:Name="PART_ToolBarOverflowPanel"
KeyboardNavigation.DirectionalNavigation="Cycle"
FocusVisualStyle="{x:Null}" Focusable="true"
Margin="2"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
KeyboardNavigation.TabNavigation="Cycle"
WrapWidth="200" />
</Border>
</Popup>
</Grid>
<Border x:Name="MainPanelBorder" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}"
Style="{StaticResource ToolBarMainPanelBorderStyle}" HorizontalAlignment="Left"
Margin="0" Width="532.6">
<DockPanel KeyboardNavigation.TabIndex="1" KeyboardNavigation.TabNavigation="Local">
<Thumb x:Name="ToolBarThumb" Margin="-3,-1,0,0" Padding="6,5,1,6"
Style="{StaticResource ToolBarThumbStyle}" Width="10"
Visibility="Collapsed" />
<ContentPresenter x:Name="ToolBarHeader" ContentSource="Header"
HorizontalAlignment="Center" Margin="4,0,4,0"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="Center" />
<ToolBarPanel x:Name="PART_ToolBarPanel" IsItemsHost="true" Margin="0,1,2,2"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</DockPanel>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsOverflowOpen" Value="true">
<Setter Property="IsEnabled" TargetName="ToolBarThumb" Value="false" />
</Trigger>
<Trigger Property="Header" Value="{x:Null}">
<Setter Property="Visibility" TargetName="ToolBarHeader" Value="Collapsed" />
</Trigger>
<Trigger Property="ToolBarTray.IsLocked" Value="true">
<Setter Property="Visibility" TargetName="ToolBarThumb" Value="Collapsed" />
</Trigger>
<Trigger Property="Orientation" Value="Vertical">
<Setter Property="Margin" TargetName="Grid" Value="1,3,1,1" />
<Setter Property="Style" TargetName="OverflowButton"
Value="{StaticResource ToolBarVerticalOverflowButtonStyle}" />
<Setter Property="Height" TargetName="ToolBarThumb" Value="10" />
<Setter Property="Width" TargetName="ToolBarThumb" Value="Auto" />
<Setter Property="Margin" TargetName="ToolBarThumb" Value="-1,-3,0,0" />
<Setter Property="Padding" TargetName="ToolBarThumb" Value="5,6,6,1" />
<Setter Property="Margin" TargetName="ToolBarHeader" Value="0,0,0,4" />
<Setter Property="Margin" TargetName="PART_ToolBarPanel" Value="1,0,2,2" />
<Setter Property="DockPanel.Dock" TargetName="ToolBarThumb" Value="Top" />
<Setter Property="DockPanel.Dock" TargetName="ToolBarHeader" Value="Top" />
<Setter Property="HorizontalAlignment" TargetName="OverflowGrid" Value="Stretch" />
<Setter Property="VerticalAlignment" TargetName="OverflowGrid" Value="Bottom" />
<Setter Property="Placement" TargetName="OverflowPopup" Value="Right" />
<Setter Property="Margin" TargetName="MainPanelBorder" Value="0,0,0,11" />
<Setter Property="Background" Value="{StaticResource ToolBarVerticalBackground}" />
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding Source={x:Static SystemParameters.HighContrast}}" Value="true">
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />
</DataTrigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
</Application.Resources>
</Application>
+20
View File
@@ -0,0 +1,20 @@
using System.Threading;
using System.Windows;
using Exceptionless;
namespace ClassicAssist.Launcher
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
protected override void OnStartup( StartupEventArgs e )
{
ExceptionlessClient.Default.Configuration.DefaultData.Add( "Locale",
Thread.CurrentThread.CurrentUICulture.Name );
ExceptionlessClient.Default.Startup( "T8v0i7nL90cVRc4sr2pgo5hviThMPRF3OtQ0bK60" );
base.OnStartup( e );
}
}
}
+106
View File
@@ -0,0 +1,106 @@
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Windows.Input;
using System.Windows.Threading;
namespace ClassicAssist.Launcher
{
public class BaseViewModel : INotifyPropertyChanged
{
protected Dispatcher _dispatcher;
public BaseViewModel()
{
_dispatcher = Dispatcher.CurrentDispatcher;
}
public event PropertyChangedEventHandler PropertyChanged;
// ReSharper disable once RedundantAssignment
public virtual void SetProperty<T>( ref T obj, T value, [CallerMemberName] string propertyName = "" )
{
obj = value;
NotifyPropertyChanged( propertyName );
CommandManager.InvalidateRequerySuggested();
}
protected void NotifyPropertyChanged( [CallerMemberName] string propertyName = "" )
{
PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( propertyName ) );
}
}
public class RelayCommand : ICommand
{
private readonly Func<object, bool> _canExecute;
private readonly Action<object> _execute;
public RelayCommand( Action<object> execute, Func<object, bool> canExecute = null )
{
_execute = execute;
_canExecute = canExecute;
}
public event EventHandler CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value;
CanExecuteChangedInternal += value;
}
remove
{
CommandManager.RequerySuggested -= value;
CanExecuteChangedInternal -= value;
}
}
public bool CanExecute( object parameter )
{
return _canExecute == null || _canExecute( parameter );
}
public void Execute( object parameter )
{
_execute( parameter );
}
private event EventHandler CanExecuteChangedInternal;
// ReSharper disable once UnusedMember.Global
public void RaiseCanExecuteChanged()
{
CanExecuteChangedInternal?.Invoke( this, EventArgs.Empty );
}
}
public class RelayCommandAsync : ICommand
{
private readonly Func<object, bool> canExecuteMethod;
private readonly Func<object, Task> executedMethod;
public RelayCommandAsync( Func<object, Task> execute, Func<object, bool> canExecute )
{
executedMethod = execute ?? throw new ArgumentNullException( nameof( execute ) );
canExecuteMethod = canExecute;
}
public event EventHandler CanExecuteChanged
{
add => CommandManager.RequerySuggested += value;
remove => CommandManager.RequerySuggested -= value;
}
public bool CanExecute( object parameter )
{
return canExecuteMethod == null || canExecuteMethod( parameter );
}
public async void Execute( object parameter )
{
await executedMethod( parameter );
}
}
}
@@ -0,0 +1,33 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;
namespace ClassicAssist.Launcher.Behaviours
{
public class CloseOnClickBehaviour : Behavior<Button>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.Click += OnClick;
}
protected override void OnDetaching()
{
AssociatedObject.Click -= OnClick;
}
private void OnClick( object sender, RoutedEventArgs e )
{
if ( !( sender is Button button ) )
{
return;
}
Window window = Window.GetWindow( button );
window?.Close();
}
}
}
@@ -0,0 +1,58 @@
#region License
// Copyright (C) 2020 Reetus
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#endregion
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interactivity;
namespace ClassicAssist.Launcher.Behaviours
{
public class WindowClosingBehaviour : Behavior<Window>
{
public static DependencyProperty CommandProperty = DependencyProperty.Register( "Command", typeof( ICommand ),
typeof( WindowClosingBehaviour ),
new FrameworkPropertyMetadata( default, FrameworkPropertyMetadataOptions.None ) );
public ICommand Command
{
get => (ICommand) GetValue( CommandProperty );
set => SetValue( CommandProperty, value );
}
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.Closing += OnClosing;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.Closing -= OnClosing;
}
private void OnClosing( object sender, CancelEventArgs e )
{
Command?.Execute( sender );
}
}
}
@@ -0,0 +1,85 @@
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net48</TargetFramework>
<UseWPF>true</UseWPF>
<BuildDate>$([System.DateTime]::op_Subtraction($([System.DateTime]::get_Now().get_Date()),$([System.DateTime]::new(2020,7,4))).get_TotalDays())</BuildDate>
<Version>0.3.$(BuildDate).0</Version>
<ApplicationIcon>Properties\cog.ico</ApplicationIcon>
<Product>ClassicAssist Launcher</Product>
<Authors>Reetus</Authors>
<Company>Reetus</Company>
<OutputPath>..\Output\</OutputPath>
<Configurations>Debug;Release;Develop;Linux</Configurations>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugType>full</DebugType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Linux|AnyCPU'">
<DebugType>full</DebugType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Develop|AnyCPU'">
<DebugType>full</DebugType>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Exceptionless" Version="4.3.2027" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="System.Windows.Interactivity.WPF" Version="2.0.20525" />
<PackageReference Include="Trinet.Core.IO.Ntfs" Version="4.1.1" />
</ItemGroup>
<ItemGroup>
<Reference Include="System.Windows.Forms" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xaml" />
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<Compile Update="Controls\EditTextBlock.xaml.cs">
<DependentUpon>%(Filename)</DependentUpon>
</Compile>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Update="Properties\Settings.Designer.cs">
<DesignTimeSharedInput>True</DesignTimeSharedInput>
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.en-AU.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Properties\Resources.en-GB.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Properties\Resources.it-IT.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Properties\Resources.ko-KR.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Update="Properties\Resources.zh.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Update="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
</Project>
@@ -0,0 +1,36 @@
#region License
// Copyright (C) 2020 Reetus
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#endregion
using System;
namespace ClassicAssist.Launcher
{
public class ClassicOptionAttribute : Attribute
{
public ClassicOptionAttribute( string argument )
{
Argument = argument;
}
public string Argument { get; set; }
public string CanIncludeProperty { get; set; }
public object DefaultValue { get; set; }
public bool IncludeIfFalse { get; set; } = true;
}
}
+44
View File
@@ -0,0 +1,44 @@
#region License
// Copyright (C) 2020 Reetus
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#endregion
namespace ClassicAssist.Launcher
{
public class ClassicOptions
{
[ClassicOption( "-autologin", IncludeIfFalse = true )]
public bool Autologin { get; set; }
[ClassicOption( "-reconnect" )]
public bool AutoReconnect { get; set; }
[ClassicOption( "-clientversion", CanIncludeProperty = nameof( OverrideClientVersion ), DefaultValue = "" )]
public string ClientVersion { get; set; }
[ClassicOption( "-debug", IncludeIfFalse = false )]
public bool Debug { get; set; }
public bool OverrideClientVersion { get; set; }
[ClassicOption( "-reconnect_time", CanIncludeProperty = nameof( AutoReconnect ), DefaultValue = 60 )]
public long ReconnectTime { get; set; } = 60000;
[ClassicOption( "-skiploginscreen", IncludeIfFalse = false )]
public bool SkipLoginScreen { get; set; }
}
}
@@ -0,0 +1,16 @@
<UserControl x:Name="root" x:Class="ClassicAssist.Launcher.Controls.EditTextBlock"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<TextBlock x:Name="textBlock" Text="{Binding ElementName=root, Path=Text}" VerticalAlignment="Center"
MouseDown="TextBlock_OnMouseDown" Background="Transparent" />
<TextBox x:Name="textBox"
Text="{Binding ElementName=root, Path=Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Center" Visibility="Collapsed" KeyDown="TextBox_OnKeyDown"
LostFocus="TextBox_LostFocus" />
</Grid>
</UserControl>
@@ -0,0 +1,71 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Threading;
namespace ClassicAssist.Launcher.Controls
{
/// <summary>
/// Interaction logic for EditTextBlock.xaml
/// </summary>
public partial class EditTextBlock
{
public static readonly DependencyProperty TextProperty = DependencyProperty.Register( "Text", typeof( string ),
typeof( EditTextBlock ), new UIPropertyMetadata() );
public static readonly DependencyProperty CanEditProperty = DependencyProperty.Register( "CanEdit",
typeof( bool ), typeof( EditTextBlock ), new UIPropertyMetadata( true ) );
public EditTextBlock()
{
InitializeComponent();
}
public bool CanEdit
{
get => (bool) GetValue( CanEditProperty );
set => SetValue( CanEditProperty, value );
}
public string Text
{
get => (string) GetValue( TextProperty );
set => SetValue( TextProperty, value );
}
private void TextBlock_OnMouseDown( object sender, MouseButtonEventArgs e )
{
if ( e.ClickCount <= 1 )
{
return;
}
if ( !CanEdit )
{
return;
}
( (TextBlock) sender ).Visibility = Visibility.Collapsed;
textBox.Visibility = Visibility.Visible;
textBox.CaretIndex = textBox.Text.Length;
textBox.SelectAll();
Dispatcher?.BeginInvoke( (Action) ( () => Keyboard.Focus( textBox ) ), DispatcherPriority.Render );
}
private void TextBox_OnKeyDown( object sender, KeyEventArgs e )
{
if ( e.Key == Key.Return )
{
TextBox_LostFocus( sender, null );
}
}
private void TextBox_LostFocus( object sender, RoutedEventArgs e )
{
textBlock.Visibility = Visibility.Visible;
( (TextBox) sender ).Visibility = Visibility.Collapsed;
}
}
}
+527
View File
@@ -0,0 +1,527 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Input;
using ClassicAssist.Launcher.Properties;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Trinet.Core.IO.Ntfs;
using Application = System.Windows.Application;
using OpenFileDialog = Microsoft.Win32.OpenFileDialog;
namespace ClassicAssist.Launcher
{
public class MainViewModel : BaseViewModel
{
private const string CONFIG_FILENAME = "Launcher.json";
private readonly ShardManager _manager;
private ICommand _checkforUpdateCommand;
private ObservableCollection<string> _clientPaths = new ObservableCollection<string>();
private ICommand _closingCommand;
private ObservableCollection<string> _dataPaths = new ObservableCollection<string>();
private ICommand _optionsCommand;
private ICommand _selectClientPathCommand;
private ICommand _selectDataPathCommand;
private string _selectedClientPath;
private string _selectedDataPath;
private ShardEntry _selectedShard;
private ObservableCollection<ShardEntry> _shardEntries = new ObservableCollection<ShardEntry>();
private ICommand _showShardsWindowCommand;
private ICommand _startCommand;
public MainViewModel()
{
RemoveAlternateDataStreams( Path.GetDirectoryName( Assembly.GetExecutingAssembly().Location ) );
_manager = ShardManager.GetInstance();
_manager.Shards.CollectionChanged += ( sender, args ) => { ShardEntries = _manager.Shards; };
ShardEntries = _manager.Shards;
string fullPath = Path.Combine( Environment.CurrentDirectory, CONFIG_FILENAME );
if ( !File.Exists( fullPath ) )
{
return;
}
using ( JsonTextReader jtr = new JsonTextReader( new StreamReader( fullPath ) ) )
{
JObject config = (JObject) JToken.ReadFrom( jtr );
if ( config["ClientPaths"] != null )
{
foreach ( JToken token in config["ClientPaths"] )
{
string path = token.ToObject<string>();
if ( File.Exists( path ) )
{
ClientPaths.Add( path );
}
}
}
if ( config["SelectedClientPath"] != null )
{
string path = config["SelectedClientPath"].ToObject<string>();
SelectedClientPath = File.Exists( path ) ? path : ClientPaths.FirstOrDefault();
}
if ( config["DataPaths"] != null )
{
foreach ( JToken token in config["DataPaths"] )
{
string path = token.ToObject<string>();
if ( Directory.Exists( path ) )
{
DataPaths.Add( path );
}
}
}
if ( config["SelectedDataPath"] != null )
{
string path = config["SelectedDataPath"].ToObject<string>();
SelectedDataPath = Directory.Exists( path ) ? path : DataPaths.FirstOrDefault();
}
if ( config["Shards"] != null )
{
foreach ( JToken token in config["Shards"] )
{
ShardEntry shard = new ShardEntry
{
Name = token["Name"]?.ToObject<string>() ?? "Unknown",
Address = token["Address"]?.ToObject<string>() ?? "localhost",
Port = token["Port"]?.ToObject<int>() ?? 2593,
HasStatusProtocol = token["HasStatusProtocol"]?.ToObject<bool>() ?? true,
Encryption = token["Encryption"]?.ToObject<bool>() ?? false
};
ShardEntries.Add( shard );
}
}
if ( config["SelectedShard"] != null )
{
ShardEntry match = _manager.Shards.FirstOrDefault(
s => s.Name == config["SelectedShard"].ToObject<string>() );
if ( match != null )
{
SelectedShard = match;
}
}
if ( config["Plugins"] != null )
{
foreach ( JToken token in config["Plugins"] )
{
string pluginPath = token.ToObject<string>();
Plugins.Add( new PluginEntry { Name = Path.GetFileName( pluginPath ), FullPath = pluginPath } );
}
}
ReadClassicOptions( config );
}
}
public ICommand CheckForUpdateCommand =>
_checkforUpdateCommand ?? ( _checkforUpdateCommand = new RelayCommand( CheckForUpdate, UpdaterExists ) );
public ClassicOptions ClassicOptions { get; set; } = new ClassicOptions();
public ObservableCollection<string> ClientPaths
{
get => _clientPaths;
set => SetProperty( ref _clientPaths, value );
}
public ICommand ClosingCommand =>
_closingCommand ?? ( _closingCommand = new RelayCommand( Closing, o => true ) );
public ObservableCollection<string> DataPaths
{
get => _dataPaths;
set => SetProperty( ref _dataPaths, value );
}
public ICommand OptionsCommand =>
_optionsCommand ?? ( _optionsCommand = new RelayCommand( ShowOptionsWindow, o => true ) );
public List<PluginEntry> Plugins { get; set; } = new List<PluginEntry>();
public ICommand SelectClientPathCommand =>
_selectClientPathCommand ?? ( _selectClientPathCommand = new RelayCommand( SelectClientPath ) );
public ICommand SelectDataPathCommand =>
_selectDataPathCommand ?? ( _selectDataPathCommand = new RelayCommand( SelectDataPath ) );
public string SelectedClientPath
{
get => _selectedClientPath;
set => SetProperty( ref _selectedClientPath, value );
}
public string SelectedDataPath
{
get => _selectedDataPath;
set => SetProperty( ref _selectedDataPath, value );
}
public ShardEntry SelectedShard
{
get => _selectedShard;
set => SetProperty( ref _selectedShard, value );
}
public ObservableCollection<ShardEntry> ShardEntries
{
get => _shardEntries;
set => SetProperty( ref _shardEntries, value );
}
public ICommand ShowShardsWindowCommand =>
_showShardsWindowCommand ?? ( _showShardsWindowCommand = new RelayCommand( ShowShardsWindow, o => true ) );
public ICommand StartCommand =>
_startCommand ?? ( _startCommand = new RelayCommandAsync( Start,
o => !string.IsNullOrEmpty( SelectedClientPath ) && !string.IsNullOrEmpty( SelectedDataPath ) ) );
private static void RemoveAlternateDataStreams( string path )
{
string manifestFile = Path.Combine( path, "MANIFEST.json" );
if ( !File.Exists( manifestFile ) )
{
return;
}
string json = File.ReadAllText( manifestFile );
IEnumerable<ManifestEntry> manifestEntries =
JsonConvert.DeserializeObject<IEnumerable<ManifestEntry>>( json );
foreach ( ManifestEntry manifestEntry in manifestEntries )
{
string filePath = Path.Combine( path, manifestEntry.Name );
if ( !File.Exists( filePath ) )
{
continue;
}
FileInfo file = new FileInfo( filePath );
if ( file.AlternateDataStreamExists( "Zone.Identifier" ) )
{
file.DeleteAlternateDataStream( "Zone.Identifier" );
}
}
}
private void ReadClassicOptions( JObject config )
{
PropertyInfo[] properties =
typeof( ClassicOptions ).GetProperties( BindingFlags.Public | BindingFlags.Instance );
foreach ( PropertyInfo property in properties )
{
string propName = property.Name;
Type propType = property.PropertyType;
object defaultValue = null;
ClassicOptionAttribute attr = property.GetCustomAttribute<ClassicOptionAttribute>();
if ( attr?.DefaultValue != null )
{
defaultValue = attr.DefaultValue;
}
if ( defaultValue == null )
{
defaultValue = Activator.CreateInstance( propType );
}
object val = config[propName]?.ToObject( propType ) ?? defaultValue;
property.SetValue( ClassicOptions, val );
}
}
private void ShowOptionsWindow( object arg )
{
OptionsViewModel vm = new OptionsViewModel( Plugins, ClassicOptions );
OptionsWindow window = new OptionsWindow { DataContext = vm };
window.ShowDialog();
if ( vm.DialogResult != DialogResult.OK )
{
return;
}
Plugins.Clear();
Plugins.AddRange( vm.Plugins );
ClassicOptions = vm.ClassicOptions;
}
private static bool UpdaterExists( object arg )
{
return File.Exists( Path.Combine( Environment.CurrentDirectory, "ClassicAssist.Updater.exe" ) );
}
private static void CheckForUpdate( object obj )
{
string updaterPath = Path.Combine( Environment.CurrentDirectory, "ClassicAssist.Updater.exe" );
if ( File.Exists( updaterPath ) )
{
Process.Start( updaterPath, $"--pid {Process.GetCurrentProcess().Id}" );
}
}
private void SelectClientPath( object obj )
{
OpenFileDialog ofd = new OpenFileDialog
{
CheckFileExists = true,
Multiselect = false,
Filter = "ClassicUO.exe|ClassicUO.exe",
Title = Resources.Select_a_client
};
bool? result = ofd.ShowDialog();
if ( !result.HasValue || !result.Value )
{
return;
}
if ( !ClientPaths.Contains( ofd.FileName ) )
{
ClientPaths.Add( ofd.FileName );
}
SelectedClientPath = ofd.FileName;
}
private void SelectDataPath( object obj )
{
FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog
{
Description = Resources.Select_your_Ultima_Online_directory, ShowNewFolderButton = false
};
DialogResult result = folderBrowserDialog.ShowDialog();
if ( result != DialogResult.OK )
{
return;
}
if ( !DataPaths.Contains( folderBrowserDialog.SelectedPath ) )
{
DataPaths.Add( folderBrowserDialog.SelectedPath );
}
SelectedDataPath = folderBrowserDialog.SelectedPath;
}
/*
* Command line parameter documentation...
* https://github.com/andreakarasho/ClassicUO/wiki/Distribuite-ClassicUO
* https://github.com/andreakarasho/ClassicUO/wiki/Launch-Arguments
*/
private async Task Start( object obj )
{
IPAddress ip = await Utility.ResolveAddress( SelectedShard.Address );
if ( ip == null )
{
MessageBox.Show( Resources.Unable_to_resolve_shard_hostname_ );
return;
}
StringBuilder args = new StringBuilder();
List<string> pluginList =
new List<string> { Path.Combine( Environment.CurrentDirectory, "ClassicAssist.dll" ) };
foreach ( PluginEntry plugin in Plugins )
{
pluginList.Add( plugin.FullPath );
}
string plugins = string.Join( ",", pluginList.ToArray() );
args.Append( $"-plugins \"{plugins}\" " );
args.Append( $"-ip \"{ip}\" -port \"{SelectedShard.Port}\" " );
args.Append( $"-uopath \"{SelectedDataPath}\" " );
args.Append( $"-encryption {( SelectedShard.Encryption ? 1 : 0 )} " );
args.Append( SelectedShard.ShardType > 0 ? $"-shard {SelectedShard.ShardType} " : "-shard 0 " );
BuildClassicOptions( args );
ProcessStartInfo psi = new ProcessStartInfo
{
WorkingDirectory =
Path.GetDirectoryName( SelectedClientPath ) ?? throw new InvalidOperationException(),
FileName = SelectedClientPath,
Arguments = args.ToString(),
UseShellExecute = true
};
Process p = Process.Start( psi );
if ( p != null && !p.HasExited )
{
Application.Current.Shutdown( 0 );
}
}
private void BuildClassicOptions( StringBuilder args )
{
PropertyInfo[] properties =
typeof( ClassicOptions ).GetProperties( BindingFlags.Public | BindingFlags.Instance );
foreach ( PropertyInfo property in properties )
{
ClassicOptionAttribute attr = property.GetCustomAttribute<ClassicOptionAttribute>();
object val = property.GetValue( ClassicOptions );
if ( attr == null )
{
continue;
}
bool skip = val is bool b && b == false && !attr.IncludeIfFalse;
bool canInclude = true;
if ( !string.IsNullOrEmpty( attr.CanIncludeProperty ) )
{
PropertyInfo canIncludeProperty = typeof( ClassicOptions ).GetProperty( attr.CanIncludeProperty );
if ( canIncludeProperty != null )
{
canInclude = (bool) canIncludeProperty.GetValue( ClassicOptions );
}
}
if ( !skip && canInclude )
{
args.Append( $"{attr.Argument} {val} " );
}
}
}
private void ShowShardsWindow( object obj )
{
ShardsWindow window = new ShardsWindow();
window.ShowDialog();
if ( !( window.DataContext is ShardsViewModel vm ) || vm.DialogResult != DialogResult.OK ||
vm.SelectedShard == null )
{
return;
}
SelectedShard = vm.SelectedShard;
}
private void Closing( object obj )
{
JObject config = new JObject();
JArray clientPathArray = new JArray();
foreach ( string clientPath in ClientPaths )
{
clientPathArray.Add( clientPath );
}
config.Add( "ClientPaths", clientPathArray );
config.Add( "SelectedClientPath", SelectedClientPath ?? string.Empty );
JArray dataPathArray = new JArray();
foreach ( string dataPath in DataPaths )
{
dataPathArray.Add( dataPath );
}
config.Add( "DataPaths", dataPathArray );
config.Add( "SelectedDataPath", SelectedDataPath ?? string.Empty );
config.Add( "SelectedShard", SelectedShard.Name );
IEnumerable<ShardEntry> shards = _manager.Shards.Where( s => !s.IsPreset );
JArray shardArray = new JArray();
foreach ( ShardEntry shard in shards )
{
JObject shardObj = new JObject
{
{ "Name", shard.Name },
{ "Address", shard.Address },
{ "Port", shard.Port },
{ "HasStatusProtocol", shard.HasStatusProtocol },
{ "Encryption", shard.Encryption }
};
shardArray.Add( shardObj );
}
config.Add( "Shards", shardArray );
JArray pluginsArray = new JArray();
foreach ( PluginEntry plugin in Plugins )
{
pluginsArray.Add( plugin.FullPath );
}
config.Add( "Plugins", pluginsArray );
WriteClassicOptions( config );
using ( JsonTextWriter jtw =
new JsonTextWriter( new StreamWriter( Path.Combine( Environment.CurrentDirectory, CONFIG_FILENAME ) ) )
)
{
jtw.Formatting = Formatting.Indented;
config.WriteTo( jtw );
}
}
private void WriteClassicOptions( JObject config )
{
PropertyInfo[] properties =
typeof( ClassicOptions ).GetProperties( BindingFlags.Public | BindingFlags.Instance );
foreach ( PropertyInfo property in properties )
{
string propName = property.Name;
object val = property.GetValue( ClassicOptions );
if ( val != null )
{
config.Add( propName, val.ToString() );
}
}
}
}
}
+92
View File
@@ -0,0 +1,92 @@
<Window x:Class="ClassicAssist.Launcher.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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"
xmlns:local="clr-namespace:ClassicAssist.Launcher"
xmlns:properties="clr-namespace:ClassicAssist.Launcher.Properties"
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
xmlns:behaviours="clr-namespace:ClassicAssist.Launcher.Behaviours"
xmlns:valueConverters="clr-namespace:ClassicAssist.Launcher.ValueConverters"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
mc:Ignorable="d"
Title="{x:Static properties:Resources.ClassicAssist_Launcher}" Height="280" Width="400"
ResizeMode="CanMinimize" WindowStartupLocation="CenterScreen">
<i:Interaction.Behaviors>
<behaviours:WindowClosingBehaviour Command="{Binding ClosingCommand}" />
</i:Interaction.Behaviors>
<Window.DataContext>
<local:MainViewModel />
</Window.DataContext>
<Grid Margin="5">
<Grid.Resources>
<Style TargetType="{x:Type GroupBox}" BasedOn="{StaticResource {x:Type GroupBox}}">
<Setter Property="Padding" Value="10" />
</Style>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<GroupBox Header="{x:Static properties:Resources.Client_Options}" Grid.Row="0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ComboBox Grid.Column="0" Margin="0,0,10,0" ItemsSource="{Binding ClientPaths}"
Text="{Binding SelectedClientPath}" />
<Button Content="..." Grid.Column="1" Padding="10,0,10,0"
Command="{Binding SelectClientPathCommand, Mode=OneWay}" />
</Grid>
</GroupBox>
<GroupBox Header="{x:Static properties:Resources.Ultima_Online}" Grid.Row="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ComboBox Grid.Column="0" Margin="0,0,10,0" ItemsSource="{Binding DataPaths}"
Text="{Binding SelectedDataPath}" />
<Button Content="..." Grid.Column="1" Padding="10,0,10,0"
Command="{Binding SelectDataPathCommand, Mode=OneWay}" />
</Grid>
</GroupBox>
<GroupBox Header="{x:Static properties:Resources.Shard}" Grid.Row="2">
<DockPanel>
<ComboBox DockPanel.Dock="Left" Width="225" Margin="0,0,10,0" ItemsSource="{Binding ShardEntries}"
SelectedIndex="0" SelectedItem="{Binding SelectedShard}" DisplayMemberPath="Name" />
<Button Content="{x:Static properties:Resources.Shards}"
Command="{Binding ShowShardsWindowCommand, Mode=OneWay}" />
</DockPanel>
</GroupBox>
<StackPanel Orientation="Horizontal" Grid.Row="3" Margin="0,10,0,10">
<StackPanel.Resources>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Margin" Value="0,0,10,0" />
<Setter Property="Padding" Value="10,0,10,0" />
</Style>
</StackPanel.Resources>
<Button Command="{Binding StartCommand, Mode=OneWay}">
<StackPanel Orientation="Horizontal">
<Image Source="{StaticResource PlayIcon}" Height="16" Margin="0,3,10,3" />
<TextBlock Text="{x:Static properties:Resources.Start}" VerticalAlignment="Center" />
</StackPanel>
</Button>
<Button Command="{Binding CheckForUpdateCommand, Mode=OneWay}">
<StackPanel Orientation="Horizontal">
<Image Source="{StaticResource RefreshButton}" Height="16" Margin="0,3,10,3" />
<TextBlock Text="{x:Static properties:Resources.Check_for_update}" VerticalAlignment="Center" />
</StackPanel>
</Button>
<Button Command="{Binding OptionsCommand, Mode=OneWay}">
<StackPanel Orientation="Horizontal">
<Image Source="{StaticResource OptionsIcon}" Height="16" Margin="0,3,10,3" />
<TextBlock Text="{x:Static properties:Resources.Options}" VerticalAlignment="Center" />
</StackPanel>
</Button>
</StackPanel>
</Grid>
</Window>
+15
View File
@@ -0,0 +1,15 @@
using System.Windows;
namespace ClassicAssist.Launcher
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}
+27
View File
@@ -0,0 +1,27 @@
// Copyright (C) 2020 Reetus
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
using System;
namespace ClassicAssist.Launcher
{
public class ManifestEntry
{
public DateTime ModifiedDate { get; set; }
public string Name { get; set; }
public string SHA1 { get; set; }
public int Size { get; set; }
}
}
+111
View File
@@ -0,0 +1,111 @@
#region License
// Copyright (C) 2020 Reetus
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#endregion
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Windows.Forms;
using System.Windows.Input;
using OpenFileDialog = Microsoft.Win32.OpenFileDialog;
namespace ClassicAssist.Launcher
{
public class OptionsViewModel : BaseViewModel
{
private ICommand _addPluginCommand;
private ClassicOptions _classicOptions = new ClassicOptions();
private ICommand _okCommand;
private ObservableCollection<PluginEntry> _plugins = new ObservableCollection<PluginEntry>();
private ICommand _removePluginCommand;
private PluginEntry _selectedPlugin;
public OptionsViewModel()
{
}
public OptionsViewModel( IEnumerable<PluginEntry> plugins, ClassicOptions classicOptions )
{
Plugins = new ObservableCollection<PluginEntry>( plugins );
ClassicOptions = classicOptions;
}
public ICommand AddPluginCommand =>
_addPluginCommand ?? ( _addPluginCommand = new RelayCommand( AddPlugin, o => true ) );
public ClassicOptions ClassicOptions
{
get => _classicOptions;
set => SetProperty( ref _classicOptions, value );
}
public DialogResult DialogResult { get; set; } = DialogResult.Cancel;
public ICommand OKCommand => _okCommand ?? ( _okCommand = new RelayCommand( OK, o => true ) );
public ObservableCollection<PluginEntry> Plugins
{
get => _plugins;
set => SetProperty( ref _plugins, value );
}
public ICommand RemovePluginCommand =>
_removePluginCommand ??
( _removePluginCommand = new RelayCommand( RemovePlugin, o => SelectedPlugin != null ) );
public PluginEntry SelectedPlugin
{
get => _selectedPlugin;
set => SetProperty( ref _selectedPlugin, value );
}
private void OK( object obj )
{
DialogResult = DialogResult.OK;
}
private void AddPlugin( object obj )
{
OpenFileDialog ofd = new OpenFileDialog
{
Multiselect = false,
InitialDirectory = Environment.CurrentDirectory,
CheckFileExists = true,
Filter = "Executable / DLL Files (*.exe, *.dll)|*.dll;*.exe"
};
bool? result = ofd.ShowDialog();
if ( result.HasValue && result.Value )
{
Plugins.Add( new PluginEntry { Name = Path.GetFileName( ofd.FileName ), FullPath = ofd.FileName } );
}
}
private void RemovePlugin( object obj )
{
if ( !( obj is PluginEntry entry ) )
{
return;
}
Plugins.Remove( entry );
}
}
}
+84
View File
@@ -0,0 +1,84 @@
<Window x:Class="ClassicAssist.Launcher.OptionsWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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"
xmlns:local="clr-namespace:ClassicAssist.Launcher"
xmlns:properties="clr-namespace:ClassicAssist.Launcher.Properties"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:behaviours="clr-namespace:ClassicAssist.Launcher.Behaviours"
mc:Ignorable="d" WindowStartupLocation="CenterScreen"
Title="{x:Static properties:Resources.Options}" Height="400" Width="400">
<Window.DataContext>
<local:OptionsViewModel />
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<GroupBox Margin="10" Grid.Row="0" Header="{x:Static properties:Resources.Additional_Plugins_}">
<Grid Margin="5">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ListBox x:Name="listBox" Grid.Row="1" SelectedItem="{Binding SelectedPlugin}"
ItemsSource="{Binding Plugins}" DisplayMemberPath="Name"
ToolTip="{Binding SelectedItem.FullPath, ElementName=listBox}" />
<StackPanel Orientation="Horizontal" Grid.Row="2" HorizontalAlignment="Right" Margin="0,10,0,0">
<StackPanel.Resources>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Padding" Value="10,0,10,0" />
</Style>
</StackPanel.Resources>
<Button Content="{x:Static properties:Resources.Add}" Command="{Binding AddPluginCommand}"
Margin="0,0,10,0" />
<Button Content="{x:Static properties:Resources.Remove}" Command="{Binding RemovePluginCommand}"
CommandParameter="{Binding SelectedItem, ElementName=listBox}" />
</StackPanel>
</Grid>
</GroupBox>
<GroupBox Header="{x:Static properties:Resources.Options}" Grid.Row="1" Margin="10,0,10,10">
<StackPanel Margin="10">
<CheckBox Content="{x:Static properties:Resources.Debug}" IsChecked="{Binding ClassicOptions.Debug}" />
<CheckBox Content="{x:Static properties:Resources.Autologin}"
IsChecked="{Binding ClassicOptions.Autologin}" />
<CheckBox Content="{x:Static properties:Resources.Skip_Login_Screen}"
IsChecked="{Binding ClassicOptions.SkipLoginScreen}" />
<CheckBox Content="{x:Static properties:Resources.Auto_Reconnect}"
IsChecked="{Binding ClassicOptions.AutoReconnect}" />
<StackPanel Orientation="Horizontal">
<Label Content="{x:Static properties:Resources.Reconnect_Time}" Margin="0,0,10,0" Padding="0" />
<TextBox MinWidth="80" Text="{Binding ClassicOptions.ReconnectTime, Mode=TwoWay}" />
</StackPanel>
<CheckBox Content="{x:Static properties:Resources.Override_Client_Version}"
IsChecked="{Binding ClassicOptions.OverrideClientVersion}" />
<StackPanel Orientation="Horizontal">
<Label Content="{x:Static properties:Resources.Client_Version}" Margin="0,0,10,0" Padding="0" />
<TextBox MinWidth="80" Text="{Binding ClassicOptions.ClientVersion, Mode=TwoWay}" />
</StackPanel>
</StackPanel>
</GroupBox>
<StackPanel Orientation="Horizontal" Grid.Row="2" HorizontalAlignment="Right" Margin="10,0,10,10">
<StackPanel.Resources>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Padding" Value="10,0,10,0" />
</Style>
</StackPanel.Resources>
<Button Content="{x:Static properties:Resources.OK}" Margin="0,0,10,0"
Command="{Binding OKCommand, Mode=OneWay}">
<i:Interaction.Behaviors>
<behaviours:CloseOnClickBehaviour />
</i:Interaction.Behaviors>
</Button>
<Button Content="{x:Static properties:Resources.Cancel}">
<i:Interaction.Behaviors>
<behaviours:CloseOnClickBehaviour />
</i:Interaction.Behaviors>
</Button>
</StackPanel>
</Grid>
</Window>
@@ -0,0 +1,15 @@
using System.Windows;
namespace ClassicAssist.Launcher
{
/// <summary>
/// Interaction logic for OptionsWindow.xaml
/// </summary>
public partial class OptionsWindow : Window
{
public OptionsWindow()
{
InitializeComponent();
}
}
}
+30
View File
@@ -0,0 +1,30 @@
#region License
// Copyright (C) 2020 Reetus
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#endregion
using System.IO;
namespace ClassicAssist.Launcher
{
public class PluginEntry
{
public string FullPath { get; set; }
public bool IsValid => File.Exists( FullPath );
public string Name { get; set; }
}
}
File diff suppressed because it is too large Load Diff
+360
View File
@@ -0,0 +1,360 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ClassicAssist.Launcher.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ClassicAssist.Launcher.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to Add.
/// </summary>
public static string Add {
get {
return ResourceManager.GetString("Add", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Additional Plugins.
/// </summary>
public static string Additional_Plugins_ {
get {
return ResourceManager.GetString("Additional Plugins:", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Address.
/// </summary>
public static string Address {
get {
return ResourceManager.GetString("Address", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Auto Reconnect.
/// </summary>
public static string Auto_Reconnect {
get {
return ResourceManager.GetString("Auto Reconnect", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Autologin.
/// </summary>
public static string Autologin {
get {
return ResourceManager.GetString("Autologin", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Cancel.
/// </summary>
public static string Cancel {
get {
return ResourceManager.GetString("Cancel", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Cannot remove preset shard.
/// </summary>
public static string Cannot_remove_preset_shard {
get {
return ResourceManager.GetString("Cannot remove preset shard", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Check for update.
/// </summary>
public static string Check_for_update {
get {
return ResourceManager.GetString("Check for update", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ClassicAssist Launcher.
/// </summary>
public static string ClassicAssist_Launcher {
get {
return ResourceManager.GetString("ClassicAssist Launcher", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Client Options.
/// </summary>
public static string Client_Options {
get {
return ResourceManager.GetString("Client Options", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Client Version.
/// </summary>
public static string Client_Version {
get {
return ResourceManager.GetString("Client Version", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Debug.
/// </summary>
public static string Debug {
get {
return ResourceManager.GetString("Debug", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Encryption.
/// </summary>
public static string Encryption {
get {
return ResourceManager.GetString("Encryption", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Error.
/// </summary>
public static string Error {
get {
return ResourceManager.GetString("Error", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to OK.
/// </summary>
public static string OK {
get {
return ResourceManager.GetString("OK", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Open a GitHub issue to have your shard added to the list..
/// </summary>
public static string Open_a_GitHub_issue_to_have_your_shard_added_to_the_list_ {
get {
return ResourceManager.GetString("Open a GitHub issue to have your shard added to the list.", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Options.
/// </summary>
public static string Options {
get {
return ResourceManager.GetString("Options", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Override Client Version.
/// </summary>
public static string Override_Client_Version {
get {
return ResourceManager.GetString("Override Client Version", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Ping.
/// </summary>
public static string Ping {
get {
return ResourceManager.GetString("Ping", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Players.
/// </summary>
public static string Players {
get {
return ResourceManager.GetString("Players", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Port.
/// </summary>
public static string Port {
get {
return ResourceManager.GetString("Port", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Reconnect Time:.
/// </summary>
public static string Reconnect_Time {
get {
return ResourceManager.GetString("Reconnect Time", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Reconnect Time (milliseconds).
/// </summary>
public static string Reconnect_Time__milliseconds_ {
get {
return ResourceManager.GetString("Reconnect Time (milliseconds)", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Refresh.
/// </summary>
public static string Refresh {
get {
return ResourceManager.GetString("Refresh", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Remove.
/// </summary>
public static string Remove {
get {
return ResourceManager.GetString("Remove", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Select a client.
/// </summary>
public static string Select_a_client {
get {
return ResourceManager.GetString("Select a client", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Select your Ultima Online directory.
/// </summary>
public static string Select_your_Ultima_Online_directory {
get {
return ResourceManager.GetString("Select your Ultima Online directory", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Shard.
/// </summary>
public static string Shard {
get {
return ResourceManager.GetString("Shard", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Shards.
/// </summary>
public static string Shards {
get {
return ResourceManager.GetString("Shards", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Skip Login Screen.
/// </summary>
public static string Skip_Login_Screen {
get {
return ResourceManager.GetString("Skip Login Screen", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Start.
/// </summary>
public static string Start {
get {
return ResourceManager.GetString("Start", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Ultima Online.
/// </summary>
public static string Ultima_Online {
get {
return ResourceManager.GetString("Ultima Online", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Unable to resolve shard hostname..
/// </summary>
public static string Unable_to_resolve_shard_hostname_ {
get {
return ResourceManager.GetString("Unable to resolve shard hostname.", resourceCulture);
}
}
}
}
@@ -0,0 +1,219 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ClassicAssist Launcher" xml:space="preserve">
<value>ClassicAssist Launcher</value>
</data>
<data name="Client Options" xml:space="preserve">
<value>Client Options</value>
</data>
<data name="Ultima Online" xml:space="preserve">
<value>Ultima Online</value>
</data>
<data name="Check for update" xml:space="preserve">
<value>Check for update</value>
</data>
<data name="Shard" xml:space="preserve">
<value>Shard</value>
</data>
<data name="Port" xml:space="preserve">
<value>Port</value>
</data>
<data name="Start" xml:space="preserve">
<value>Start</value>
</data>
<data name="Select a client" xml:space="preserve">
<value>Select a client</value>
</data>
<data name="Select your Ultima Online directory" xml:space="preserve">
<value>Select your Ultima Online directory</value>
</data>
<data name="Unable to resolve shard hostname." xml:space="preserve">
<value>Unable to resolve shard hostname.</value>
</data>
<data name="Error" xml:space="preserve">
<value>Error</value>
</data>
<data name="Shards" xml:space="preserve">
<value>Shards</value>
</data>
<data name="Address" xml:space="preserve">
<value>Address</value>
</data>
<data name="Players" xml:space="preserve">
<value>Players</value>
</data>
<data name="Cancel" xml:space="preserve">
<value>Cancel</value>
</data>
<data name="OK" xml:space="preserve">
<value>OK</value>
</data>
<data name="Add" xml:space="preserve">
<value>Add</value>
</data>
<data name="Cannot remove preset shard" xml:space="preserve">
<value>Cannot remove preset shard</value>
</data>
<data name="Refresh" xml:space="preserve">
<value>Refresh</value>
</data>
<data name="Remove" xml:space="preserve">
<value>Remove</value>
</data>
<data name="Ping" xml:space="preserve">
<value>Ping</value>
</data>
<data name="Options" xml:space="preserve">
<value>Options</value>
</data>
<data name="Additional Plugins:" xml:space="preserve">
<value>Additional Plugins</value>
</data>
<data name="Debug" xml:space="preserve">
<value>Debug</value>
</data>
<data name="Autologin" xml:space="preserve">
<value>Autologin</value>
</data>
<data name="Auto Reconnect" xml:space="preserve">
<value>Auto Reconnect</value>
</data>
<data name="Reconnect Time (milliseconds)" xml:space="preserve">
<value>Reconnect Time (milliseconds)</value>
</data>
<data name="Skip Login Screen" xml:space="preserve">
<value>Skip Login Screen</value>
</data>
<data name="Reconnect Time" xml:space="preserve">
<value>Reconnect Time:</value>
</data>
<data name="Override Client Version" xml:space="preserve">
<value>Override Client Version</value>
</data>
<data name="Client Version" xml:space="preserve">
<value>Client Version</value>
</data>
<data name="Encryption" xml:space="preserve">
<value>Encryption</value>
</data>
<data name="Open a GitHub issue to have your shard added to the list." xml:space="preserve">
<value>Open a GitHub issue to have your shard added to the list.</value>
</data>
</root>
@@ -0,0 +1,219 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ClassicAssist Launcher" xml:space="preserve">
<value>ClassicAssist Launcher</value>
</data>
<data name="Client Options" xml:space="preserve">
<value>Client Options</value>
</data>
<data name="Ultima Online" xml:space="preserve">
<value>Ultima Online</value>
</data>
<data name="Check for update" xml:space="preserve">
<value>Check for update</value>
</data>
<data name="Shard" xml:space="preserve">
<value>Shard</value>
</data>
<data name="Port" xml:space="preserve">
<value>Port</value>
</data>
<data name="Start" xml:space="preserve">
<value>Start</value>
</data>
<data name="Select a client" xml:space="preserve">
<value>Select a client</value>
</data>
<data name="Select your Ultima Online directory" xml:space="preserve">
<value>Select your Ultima Online directory</value>
</data>
<data name="Unable to resolve shard hostname." xml:space="preserve">
<value>Unable to resolve shard hostname.</value>
</data>
<data name="Error" xml:space="preserve">
<value>Error</value>
</data>
<data name="Shards" xml:space="preserve">
<value>Shards</value>
</data>
<data name="Address" xml:space="preserve">
<value>Address</value>
</data>
<data name="Players" xml:space="preserve">
<value>Players</value>
</data>
<data name="Cancel" xml:space="preserve">
<value>Cancel</value>
</data>
<data name="OK" xml:space="preserve">
<value>OK</value>
</data>
<data name="Add" xml:space="preserve">
<value>Add</value>
</data>
<data name="Cannot remove preset shard" xml:space="preserve">
<value>Cannot remove preset shard</value>
</data>
<data name="Refresh" xml:space="preserve">
<value>Refresh</value>
</data>
<data name="Remove" xml:space="preserve">
<value>Remove</value>
</data>
<data name="Ping" xml:space="preserve">
<value>Ping</value>
</data>
<data name="Options" xml:space="preserve">
<value>Options</value>
</data>
<data name="Additional Plugins:" xml:space="preserve">
<value>Additional Plugins</value>
</data>
<data name="Debug" xml:space="preserve">
<value>Debug</value>
</data>
<data name="Autologin" xml:space="preserve">
<value>Autologin</value>
</data>
<data name="Auto Reconnect" xml:space="preserve">
<value>Auto Reconnect</value>
</data>
<data name="Reconnect Time (milliseconds)" xml:space="preserve">
<value>Reconnect Time (milliseconds)</value>
</data>
<data name="Skip Login Screen" xml:space="preserve">
<value>Skip Login Screen</value>
</data>
<data name="Reconnect Time" xml:space="preserve">
<value>Reconnect Time:</value>
</data>
<data name="Override Client Version" xml:space="preserve">
<value>Override Client Version</value>
</data>
<data name="Client Version" xml:space="preserve">
<value>Client Version</value>
</data>
<data name="Encryption" xml:space="preserve">
<value>Encryption</value>
</data>
<data name="Open a GitHub issue to have your shard added to the list." xml:space="preserve">
<value>Open a GitHub issue to have your shard added to the list.</value>
</data>
</root>
@@ -0,0 +1,219 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ClassicAssist Launcher" xml:space="preserve">
<value>ClassicAssist Launcher</value>
</data>
<data name="Client Options" xml:space="preserve">
<value>Seleziona Client</value>
</data>
<data name="Ultima Online" xml:space="preserve">
<value>Seleziona cartella di Ultima Online</value>
</data>
<data name="Check for update" xml:space="preserve">
<value>Verifica Aggiornamenti</value>
</data>
<data name="Shard" xml:space="preserve">
<value>Seleziona Shard</value>
</data>
<data name="Port" xml:space="preserve">
<value>Porta</value>
</data>
<data name="Start" xml:space="preserve">
<value>Avvia</value>
</data>
<data name="Select a client" xml:space="preserve">
<value>Seleziona il Client</value>
</data>
<data name="Select your Ultima Online directory" xml:space="preserve">
<value>Seleziona la cartella di Ultima Online</value>
</data>
<data name="Unable to resolve shard hostname." xml:space="preserve">
<value>Hostname/IP dello Shard non raggiunto.</value>
</data>
<data name="Error" xml:space="preserve">
<value>Errore</value>
</data>
<data name="Shards" xml:space="preserve">
<value>Shards</value>
</data>
<data name="Address" xml:space="preserve">
<value>Indirizzo</value>
</data>
<data name="Players" xml:space="preserve">
<value>Giocatori</value>
</data>
<data name="Cancel" xml:space="preserve">
<value>Annulla</value>
</data>
<data name="OK" xml:space="preserve">
<value>Ok</value>
</data>
<data name="Add" xml:space="preserve">
<value>Aggiungi</value>
</data>
<data name="Cannot remove preset shard" xml:space="preserve">
<value>Impossibile rimuovere lo Shard predefinito</value>
</data>
<data name="Refresh" xml:space="preserve">
<value>Aggiorna</value>
</data>
<data name="Remove" xml:space="preserve">
<value>Rimuovi</value>
</data>
<data name="Ping" xml:space="preserve">
<value>Ping</value>
</data>
<data name="Options" xml:space="preserve">
<value>Opzioni</value>
</data>
<data name="Additional Plugins:" xml:space="preserve">
<value>Plug-in aggiuntivi</value>
</data>
<data name="Debug" xml:space="preserve">
<value>Debug</value>
</data>
<data name="Autologin" xml:space="preserve">
<value>Autologin</value>
</data>
<data name="Auto Reconnect" xml:space="preserve">
<value>Autoriconnetti</value>
</data>
<data name="Reconnect Time (milliseconds)" xml:space="preserve">
<value>Autoriconnetti dopo (millisecondi)</value>
</data>
<data name="Skip Login Screen" xml:space="preserve">
<value>Salta la schermata di accesso</value>
</data>
<data name="Reconnect Time" xml:space="preserve">
<value>Autoriconnetti dopo:</value>
</data>
<data name="Override Client Version" xml:space="preserve">
<value>Sovrascrivi versione Client</value>
</data>
<data name="Client Version" xml:space="preserve">
<value>Versione Client</value>
</data>
<data name="Encryption" xml:space="preserve">
<value>Crittografia</value>
</data>
<data name="Open a GitHub issue to have your shard added to the list." xml:space="preserve">
<value>Aprire un problema di GitHub per aggiungere la partizione all'elenco.</value>
</data>
</root>
@@ -0,0 +1,219 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ClassicAssist Launcher" xml:space="preserve">
<value>클래식어시스트 런처</value>
</data>
<data name="Client Options" xml:space="preserve">
<value>클라이언트 옵션</value>
</data>
<data name="Ultima Online" xml:space="preserve">
<value>Ultima Online</value>
</data>
<data name="Check for update" xml:space="preserve">
<value>업데이트 확인</value>
</data>
<data name="Shard" xml:space="preserve">
<value>파편</value>
</data>
<data name="Port" xml:space="preserve">
<value>포트</value>
</data>
<data name="Start" xml:space="preserve">
<value>시작</value>
</data>
<data name="Select a client" xml:space="preserve">
<value>클라이언트 선택</value>
</data>
<data name="Select your Ultima Online directory" xml:space="preserve">
<value>울티마 온라인 디렉토리 선택</value>
</data>
<data name="Unable to resolve shard hostname." xml:space="preserve">
<value>샤드 호스트 이름을 확인할 수 없습니다.</value>
</data>
<data name="Error" xml:space="preserve">
<value>오류</value>
</data>
<data name="Shards" xml:space="preserve">
<value>파편</value>
</data>
<data name="Address" xml:space="preserve">
<value>주소</value>
</data>
<data name="Players" xml:space="preserve">
<value>플레이어</value>
</data>
<data name="Cancel" xml:space="preserve">
<value>취소</value>
</data>
<data name="OK" xml:space="preserve">
<value>그래</value>
</data>
<data name="Add" xml:space="preserve">
<value>추가</value>
</data>
<data name="Cannot remove preset shard" xml:space="preserve">
<value>사전 설정 샤드를 제거할 수 없음</value>
</data>
<data name="Refresh" xml:space="preserve">
<value>새로 고침</value>
</data>
<data name="Remove" xml:space="preserve">
<value>제거</value>
</data>
<data name="Ping" xml:space="preserve">
<value>Ping</value>
</data>
<data name="Options" xml:space="preserve">
<value>옵션</value>
</data>
<data name="Additional Plugins:" xml:space="preserve">
<value>추가 플러그인</value>
</data>
<data name="Debug" xml:space="preserve">
<value>디버그</value>
</data>
<data name="Autologin" xml:space="preserve">
<value>자동 로그인</value>
</data>
<data name="Auto Reconnect" xml:space="preserve">
<value>자동 다시 연결</value>
</data>
<data name="Reconnect Time (milliseconds)" xml:space="preserve">
<value>다시 연결 시간(밀리초)</value>
</data>
<data name="Skip Login Screen" xml:space="preserve">
<value>로그인 화면 건너뛰기</value>
</data>
<data name="Reconnect Time" xml:space="preserve">
<value>다시 연결 시간:</value>
</data>
<data name="Override Client Version" xml:space="preserve">
<value>클라이언트 버전 재정의</value>
</data>
<data name="Client Version" xml:space="preserve">
<value>클라이언트 버전</value>
</data>
<data name="Encryption" xml:space="preserve">
<value>암호화</value>
</data>
<data name="Open a GitHub issue to have your shard added to the list." xml:space="preserve">
<value>GitHub 문제를 열어 샤드를 목록에 추가합니다.</value>
</data>
</root>
@@ -0,0 +1,219 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ClassicAssist Launcher" xml:space="preserve">
<value>ClassicAssist Launcher</value>
</data>
<data name="Client Options" xml:space="preserve">
<value>Opcje klienta</value>
</data>
<data name="Ultima Online" xml:space="preserve">
<value>Ultima Online</value>
</data>
<data name="Check for update" xml:space="preserve">
<value>Sprawdź aktualizacje</value>
</data>
<data name="Shard" xml:space="preserve">
<value>Shard</value>
</data>
<data name="Port" xml:space="preserve">
<value>Port</value>
</data>
<data name="Start" xml:space="preserve">
<value>Start</value>
</data>
<data name="Select a client" xml:space="preserve">
<value>Wybierz klienta</value>
</data>
<data name="Select your Ultima Online directory" xml:space="preserve">
<value>Wybierz katalog z instalacją Ultima Online</value>
</data>
<data name="Unable to resolve shard hostname." xml:space="preserve">
<value>Nie można rozwiązać nazwy shardu</value>
</data>
<data name="Error" xml:space="preserve">
<value>Błąd</value>
</data>
<data name="Shards" xml:space="preserve">
<value>Shardy</value>
</data>
<data name="Address" xml:space="preserve">
<value>Adres</value>
</data>
<data name="Players" xml:space="preserve">
<value>Gracze</value>
</data>
<data name="Cancel" xml:space="preserve">
<value>Anuluj</value>
</data>
<data name="OK" xml:space="preserve">
<value>OK</value>
</data>
<data name="Add" xml:space="preserve">
<value>Dodaj</value>
</data>
<data name="Cannot remove preset shard" xml:space="preserve">
<value>Nie można usunąć obecnego shardu</value>
</data>
<data name="Refresh" xml:space="preserve">
<value>Odśwież</value>
</data>
<data name="Remove" xml:space="preserve">
<value>Usuń</value>
</data>
<data name="Ping" xml:space="preserve">
<value>Ping</value>
</data>
<data name="Options" xml:space="preserve">
<value>Opcje</value>
</data>
<data name="Additional Plugins:" xml:space="preserve">
<value>Dodatkowe wtyczki</value>
</data>
<data name="Debug" xml:space="preserve">
<value>Debug</value>
</data>
<data name="Autologin" xml:space="preserve">
<value>Autologowanie</value>
</data>
<data name="Auto Reconnect" xml:space="preserve">
<value>Automatyczne odnawianie połączenia</value>
</data>
<data name="Reconnect Time (milliseconds)" xml:space="preserve">
<value>Czas automatycznego odnawiania połączenia (milisekundy)</value>
</data>
<data name="Skip Login Screen" xml:space="preserve">
<value>Pomiń ekran logowania</value>
</data>
<data name="Reconnect Time" xml:space="preserve">
<value>Czas ponownego połączenia:</value>
</data>
<data name="Override Client Version" xml:space="preserve">
<value>Nadpisz wersję klienta</value>
</data>
<data name="Client Version" xml:space="preserve">
<value>Wersja klienta</value>
</data>
<data name="Encryption" xml:space="preserve">
<value>Enkrypcja</value>
</data>
<data name="Open a GitHub issue to have your shard added to the list." xml:space="preserve">
<value>Otwórz zgłoszenie na GitHub aby dodać swój shard do listy na stałe.</value>
</data>
</root>
@@ -0,0 +1,219 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ClassicAssist Launcher" xml:space="preserve">
<value>ClassicAssist Launcher</value>
</data>
<data name="Client Options" xml:space="preserve">
<value>Client Options</value>
</data>
<data name="Ultima Online" xml:space="preserve">
<value>Ultima Online</value>
</data>
<data name="Check for update" xml:space="preserve">
<value>Check for update</value>
</data>
<data name="Shard" xml:space="preserve">
<value>Shard</value>
</data>
<data name="Port" xml:space="preserve">
<value>Port</value>
</data>
<data name="Start" xml:space="preserve">
<value>Start</value>
</data>
<data name="Select a client" xml:space="preserve">
<value>Select a client</value>
</data>
<data name="Select your Ultima Online directory" xml:space="preserve">
<value>Select your Ultima Online directory</value>
</data>
<data name="Unable to resolve shard hostname." xml:space="preserve">
<value>Unable to resolve shard hostname.</value>
</data>
<data name="Error" xml:space="preserve">
<value>Error</value>
</data>
<data name="Shards" xml:space="preserve">
<value>Shards</value>
</data>
<data name="Address" xml:space="preserve">
<value>Address</value>
</data>
<data name="Players" xml:space="preserve">
<value>Players</value>
</data>
<data name="Cancel" xml:space="preserve">
<value>Cancel</value>
</data>
<data name="OK" xml:space="preserve">
<value>OK</value>
</data>
<data name="Add" xml:space="preserve">
<value>Add</value>
</data>
<data name="Cannot remove preset shard" xml:space="preserve">
<value>Cannot remove preset shard</value>
</data>
<data name="Refresh" xml:space="preserve">
<value>Refresh</value>
</data>
<data name="Remove" xml:space="preserve">
<value>Remove</value>
</data>
<data name="Ping" xml:space="preserve">
<value>Ping</value>
</data>
<data name="Options" xml:space="preserve">
<value>Options</value>
</data>
<data name="Additional Plugins:" xml:space="preserve">
<value>Additional Plugins</value>
</data>
<data name="Debug" xml:space="preserve">
<value>Debug</value>
</data>
<data name="Autologin" xml:space="preserve">
<value>Autologin</value>
</data>
<data name="Auto Reconnect" xml:space="preserve">
<value>Auto Reconnect</value>
</data>
<data name="Reconnect Time (milliseconds)" xml:space="preserve">
<value>Reconnect Time (milliseconds)</value>
</data>
<data name="Skip Login Screen" xml:space="preserve">
<value>Skip Login Screen</value>
</data>
<data name="Reconnect Time" xml:space="preserve">
<value>Reconnect Time:</value>
</data>
<data name="Override Client Version" xml:space="preserve">
<value>Override Client Version</value>
</data>
<data name="Client Version" xml:space="preserve">
<value>Client Version</value>
</data>
<data name="Encryption" xml:space="preserve">
<value>Encryption</value>
</data>
<data name="Open a GitHub issue to have your shard added to the list." xml:space="preserve">
<value>Open a GitHub issue to have your shard added to the list.</value>
</data>
</root>
@@ -0,0 +1,219 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ClassicAssist Launcher" xml:space="preserve">
<value>经典辅助启动器</value>
</data>
<data name="Client Options" xml:space="preserve">
<value>客户端选项</value>
</data>
<data name="Ultima Online" xml:space="preserve">
<value>Ultima Online</value>
</data>
<data name="Check for update" xml:space="preserve">
<value>检查更新</value>
</data>
<data name="Shard" xml:space="preserve">
<value>碎片</value>
</data>
<data name="Port" xml:space="preserve">
<value>港口</value>
</data>
<data name="Start" xml:space="preserve">
<value>开始</value>
</data>
<data name="Select a client" xml:space="preserve">
<value>选择客户端</value>
</data>
<data name="Select your Ultima Online directory" xml:space="preserve">
<value>选择您的 Ultima 在线目录</value>
</data>
<data name="Unable to resolve shard hostname." xml:space="preserve">
<value>无法解析分片主机名。</value>
</data>
<data name="Error" xml:space="preserve">
<value>错误</value>
</data>
<data name="Shards" xml:space="preserve">
<value>碎片</value>
</data>
<data name="Address" xml:space="preserve">
<value>地址</value>
</data>
<data name="Players" xml:space="preserve">
<value>球员</value>
</data>
<data name="Cancel" xml:space="preserve">
<value>取消</value>
</data>
<data name="OK" xml:space="preserve">
<value>还行</value>
</data>
<data name="Add" xml:space="preserve">
<value>添加</value>
</data>
<data name="Cannot remove preset shard" xml:space="preserve">
<value>无法删除预设分片</value>
</data>
<data name="Refresh" xml:space="preserve">
<value>刷新</value>
</data>
<data name="Remove" xml:space="preserve">
<value>删除</value>
</data>
<data name="Ping" xml:space="preserve">
<value>坪</value>
</data>
<data name="Options" xml:space="preserve">
<value>选件</value>
</data>
<data name="Additional Plugins:" xml:space="preserve">
<value>其他插件</value>
</data>
<data name="Debug" xml:space="preserve">
<value>调试</value>
</data>
<data name="Autologin" xml:space="preserve">
<value>自动登录</value>
</data>
<data name="Auto Reconnect" xml:space="preserve">
<value>自动重新连接</value>
</data>
<data name="Reconnect Time (milliseconds)" xml:space="preserve">
<value>重新连接时间(毫秒)</value>
</data>
<data name="Skip Login Screen" xml:space="preserve">
<value>跳过登录屏幕</value>
</data>
<data name="Reconnect Time" xml:space="preserve">
<value>重新连接时间:</value>
</data>
<data name="Override Client Version" xml:space="preserve">
<value>覆盖客户端版本</value>
</data>
<data name="Client Version" xml:space="preserve">
<value>客户端版本</value>
</data>
<data name="Encryption" xml:space="preserve">
<value>加密</value>
</data>
<data name="Open a GitHub issue to have your shard added to the list." xml:space="preserve">
<value>打开 GitHub 问题,将分片添加到列表中。</value>
</data>
</root>
+26
View File
@@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ClassicAssist.Launcher.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.4.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}
@@ -0,0 +1,8 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>
Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

+83
View File
@@ -0,0 +1,83 @@
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;
using ClassicAssist.Launcher.Annotations;
namespace ClassicAssist.Launcher
{
public class ShardEntry : INotifyPropertyChanged
{
private const string RUNUO_REGEX = @".*Clients=(\d+),.*";
private string _address;
private bool _encryption;
private string _name;
private string _ping;
private int _port;
private int _shardType;
private string _status;
public string Address
{
get => _address;
set => SetProperty( ref _address, value );
}
public bool Encryption
{
get => _encryption;
set => SetProperty( ref _encryption, value );
}
public bool HasStatusProtocol { get; set; } = true;
public bool IsPreset { get; set; } = false;
public string Name
{
get => _name;
set => SetProperty( ref _name, value );
}
public string Ping
{
get => _ping;
set => SetProperty( ref _ping, value );
}
public int Port
{
get => _port;
set => SetProperty( ref _port, value );
}
public int ShardType
{
get => _shardType;
set => SetProperty( ref _shardType, value );
}
public string Status
{
get => _status;
set => SetProperty( ref _status, value );
}
public string StatusRegex { get; set; } = RUNUO_REGEX;
public event PropertyChangedEventHandler PropertyChanged;
// ReSharper disable once RedundantAssignment
public virtual void SetProperty<T>( ref T obj, T value, [CallerMemberName] string propertyName = "" )
{
obj = value;
OnPropertyChanged( propertyName );
CommandManager.InvalidateRequerySuggested();
}
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged( [CallerMemberName] string propertyName = null )
{
PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( propertyName ) );
}
}
}
+93
View File
@@ -0,0 +1,93 @@
using System.Collections.ObjectModel;
namespace ClassicAssist.Launcher
{
public class ShardManager
{
private static ShardManager _instance;
private static readonly object _lock = new object();
private ShardManager()
{
Shards.Add( new ShardEntry
{
Name = "Official EA Servers",
Address = "login.ultimaonline.com",
Port = 7775,
IsPreset = true,
HasStatusProtocol = false,
Encryption = true
} );
Shards.Add( new ShardEntry
{
Name = "UOGamers: Demise", Address = "login.uodemise.com", Port = 2593, IsPreset = true
} );
Shards.Add( new ShardEntry
{
Name = "UOGamers: Hybrid", Address = "login.uohybrid.com", Port = 2593, IsPreset = true
} );
Shards.Add( new ShardEntry
{
Name = "Heritage UO", Address = "play.trueuo.com", Port = 2593, IsPreset = true
} );
Shards.Add( new ShardEntry
{
Name = "UO Forever", Address = "login.uoforever.com", Port = 2599, IsPreset = true
} );
Shards.Add( new ShardEntry
{
Name = "UO Outlands",
Address = "play.uooutlands.com",
Port = 2593,
IsPreset = true,
HasStatusProtocol = false,
ShardType = 2
} );
Shards.Add( new ShardEntry
{
Name = "UO Players",
Address = "login.uoplayers.com",
Port = 2593,
IsPreset = true,
HasStatusProtocol = true
} );
Shards.Add( new ShardEntry
{
Name = "UO:Renaissance",
Address = "login.uorenaissance.com",
Port = 2593,
IsPreset = true,
HasStatusProtocol = true
} );
}
public ObservableCollection<ShardEntry> Shards { get; set; } = new ObservableCollection<ShardEntry>();
public static ShardManager GetInstance()
{
// ReSharper disable once InvertIf
if ( _instance == null )
{
lock ( _lock )
{
if ( _instance != null )
{
return _instance;
}
_instance = new ShardManager();
return _instance;
}
}
return _instance;
}
}
}
+198
View File
@@ -0,0 +1,198 @@
using System;
using System.Collections.ObjectModel;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Input;
using ClassicAssist.Launcher.Properties;
namespace ClassicAssist.Launcher
{
public class ShardsViewModel : BaseViewModel
{
private readonly ShardManager _manager;
private ICommand _addCommand;
private ICommand _cancelCommand;
private bool _isRefreshing;
private ICommand _okCommand;
private ICommand _refreshCommand;
private ICommand _removeCommand;
private ShardEntry _selectedShard;
private ObservableCollection<ShardEntry> _shards;
public ShardsViewModel()
{
_manager = ShardManager.GetInstance();
Shards = _manager.Shards;
Refresh( this );
}
public ICommand AddCommand => _addCommand ?? ( _addCommand = new RelayCommand( Add, o => true ) );
public ICommand CancelCommand => _cancelCommand ?? ( _cancelCommand = new RelayCommand( Cancel, o => true ) );
public DialogResult DialogResult { get; set; }
public bool IsRefreshing
{
get => _isRefreshing;
set => SetProperty( ref _isRefreshing, value );
}
public ICommand OKCommand => _okCommand ?? ( _okCommand = new RelayCommand( OK, o => true ) );
public ICommand RefreshCommand =>
_refreshCommand ?? ( _refreshCommand = new RelayCommand( Refresh, o => !IsRefreshing ) );
public ICommand RemoveCommand =>
_removeCommand ?? ( _removeCommand =
new RelayCommand( Remove, o => SelectedShard != null && !SelectedShard.IsPreset ) );
public ShardEntry SelectedShard
{
get => _selectedShard;
set => SetProperty( ref _selectedShard, value );
}
public ObservableCollection<ShardEntry> Shards
{
get => _shards;
set
{
SetProperty( ref _shards, value );
_manager.Shards = value;
}
}
private void Remove( object obj )
{
if ( !( obj is ShardEntry entry ) )
{
return;
}
if ( entry.IsPreset )
{
MessageBox.Show( Resources.Cannot_remove_preset_shard, Resources.Error );
return;
}
Shards.Remove( entry );
}
private void Add( object obj )
{
Shards.Add( new ShardEntry { Name = "Shard Name", Address = "localhost", Port = 2593 } );
}
private void Refresh( object obj )
{
try
{
foreach ( ShardEntry shard in Shards )
{
Task.Run( async () =>
{
if ( !shard.HasStatusProtocol )
{
return "-";
}
string status = await GetStatus( shard );
return status;
} ).ContinueWith( t =>
{
if ( !string.IsNullOrEmpty( shard.StatusRegex ) )
{
Match matches = Regex.Match( t.Result, shard.StatusRegex );
shard.Status = matches.Success ? matches.Groups[1].Value : "-";
}
else
{
shard.Status = t.Result;
}
NotifyPropertyChanged( nameof( Shards ) );
} );
Task.Run( async () => await GetPing( shard ) ).ContinueWith( result =>
{
shard.Ping = result.Result;
NotifyPropertyChanged( nameof( Shards ) );
} );
}
}
finally
{
IsRefreshing = false;
}
}
private void OK( object obj )
{
DialogResult = DialogResult.OK;
}
public async Task<string> GetStatus( ShardEntry shard )
{
if ( !shard.HasStatusProtocol )
{
return "Unknown";
}
TcpClient client = new TcpClient();
Task connectTask = client.ConnectAsync( shard.Address, shard.Port );
await Task.WhenAny( connectTask, Task.Delay( TimeSpan.FromSeconds( 5 ) ) );
if ( !client.Connected )
{
return "Unknown";
}
byte[] packet = { 0x7F, 0x00, 0x00, 0x7F, 0xF1, 0x00, 0x04, 0xFF };
client.Client.Send( packet );
NetworkStream stream = client.GetStream();
byte[] buffer = new byte[256];
stream.ReadTimeout = 60000;
await stream.ReadAsync( buffer, 0, buffer.Length );
client.Close();
string status = Encoding.ASCII.GetString( buffer ).TrimEnd( '\0' );
return status;
}
public async Task<string> GetPing( ShardEntry entry )
{
IPAddress ip = await Utility.ResolveAddress( entry.Address );
if ( ip == null )
{
return "-";
}
Ping ping = new Ping();
PingReply result = ping.Send( ip.ToString() );
return result?.Status == IPStatus.Success ? result.RoundtripTime.ToString() : "-";
}
private void Cancel( object obj )
{
DialogResult = DialogResult.Cancel;
}
}
}
+119
View File
@@ -0,0 +1,119 @@
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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"
xmlns:properties="clr-namespace:ClassicAssist.Launcher.Properties"
xmlns:launcher="clr-namespace:ClassicAssist.Launcher"
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
xmlns:behaviours="clr-namespace:ClassicAssist.Launcher.Behaviours"
xmlns:ValueConverters="clr-namespace:ClassicAssist.Launcher.ValueConverters"
xmlns:controls="clr-namespace:ClassicAssist.Launcher.Controls"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
x:Class="ClassicAssist.Launcher.ShardsWindow"
mc:Ignorable="d"
Title="{x:Static properties:Resources.Shards}" Height="400" Width="620" WindowStartupLocation="CenterScreen">
<Window.Resources>
<ValueConverters:InverseBooleanConverter x:Key="InverseBooleanConverter" />
<ValueConverters:BooleanToOpacityValueConverter x:Key="BooleanToOpacityValueConverter" />
<ValueConverters:CellWidthValueConverter x:Key="CellWidthValueConverter" />
</Window.Resources>
<Window.DataContext>
<launcher:ShardsViewModel />
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ToolBar Grid.Row="0" Style="{DynamicResource ToolBarStyle1}">
<Button Height="24" Margin="0,0,5,0" Command="{Binding AddCommand, Mode=OneWay}">
<Image Source="{StaticResource AddIcon}" ToolTip="{x:Static properties:Resources.Add}"
Opacity="{Binding IsEnabled, Converter={StaticResource BooleanToOpacityValueConverter}, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" />
</Button>
<Button Height="24" Margin="0,0,5,0" Command="{Binding RemoveCommand, Mode=OneWay}"
CommandParameter="{Binding SelectedShard}">
<Image Source="{StaticResource RemoveIcon}" ToolTip="{x:Static properties:Resources.Remove}"
Opacity="{Binding IsEnabled, Converter={StaticResource BooleanToOpacityValueConverter}, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" />
</Button>
<Button Height="24" Command="{Binding RefreshCommand}" CommandParameter="{Binding SelectedShard}">
<Image Source="{StaticResource RefreshIcon}" ToolTip="{x:Static properties:Resources.Refresh}"
Opacity="{Binding IsEnabled, Converter={StaticResource BooleanToOpacityValueConverter}, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" />
</Button>
</ToolBar>
<ListView ItemsSource="{Binding Shards}" Grid.Row="1" SelectedItem="{Binding SelectedShard}" Margin="10">
<ListView.View>
<GridView>
<GridViewColumn Header="{x:Static properties:Resources.Shard}" Width="150" x:Name="NameColumn">
<GridViewColumn.CellTemplate>
<DataTemplate>
<controls:EditTextBlock
Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"
CanEdit="{Binding IsPreset, Converter={StaticResource InverseBooleanConverter}}"
Width="{Binding ActualWidth, ElementName=NameColumn, Converter={StaticResource CellWidthValueConverter}}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="{x:Static properties:Resources.Address}" Width="150" x:Name="AddressColumn">
<GridViewColumn.CellTemplate>
<DataTemplate>
<controls:EditTextBlock
Text="{Binding Address, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"
CanEdit="{Binding IsPreset, Converter={StaticResource InverseBooleanConverter}}"
Width="{Binding ActualWidth, ElementName=AddressColumn, Converter={StaticResource CellWidthValueConverter}}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="{x:Static properties:Resources.Port}" Width="50" x:Name="PortColumn">
<GridViewColumn.CellTemplate>
<DataTemplate>
<controls:EditTextBlock
Text="{Binding Port, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"
CanEdit="{Binding IsPreset, Converter={StaticResource InverseBooleanConverter}}"
Width="{Binding ActualWidth, ElementName=PortColumn, Converter={StaticResource CellWidthValueConverter}}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="{x:Static properties:Resources.Encryption}" Width="75">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Encryption}"
IsEnabled="{Binding IsPreset, Converter={StaticResource InverseBooleanConverter}}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="{x:Static properties:Resources.Players}" Width="75"
DisplayMemberBinding="{Binding Status}" />
<GridViewColumn Header="{x:Static properties:Resources.Ping}" Width="50"
DisplayMemberBinding="{Binding Ping}" />
</GridView>
</ListView.View>
</ListView>
<TextBlock Grid.Row="2" Margin="10,0">
<Hyperlink NavigateUri="https://github.com/Reetus/ClassicAssist/issues"
RequestNavigate="Hyperlink_RequestNavigate">
<Run Text="{x:Static properties:Resources.Open_a_GitHub_issue_to_have_your_shard_added_to_the_list_}" />
</Hyperlink>
</TextBlock>
<StackPanel Orientation="Horizontal" Grid.Row="3" HorizontalAlignment="Right" Margin="0,0,10,10">
<StackPanel.Resources>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Padding" Value="15,0,15,0" />
</Style>
</StackPanel.Resources>
<Button Content="{x:Static properties:Resources.OK}" Margin="0,0,10,0"
Command="{Binding OKCommand, Mode=OneWay}">
<i:Interaction.Behaviors>
<behaviours:CloseOnClickBehaviour />
</i:Interaction.Behaviors>
</Button>
<Button Content="{x:Static properties:Resources.Cancel}" Command="{Binding CancelCommand, Mode=OneWay}">
<i:Interaction.Behaviors>
<behaviours:CloseOnClickBehaviour />
</i:Interaction.Behaviors>
</Button>
</StackPanel>
</Grid>
</Window>
@@ -0,0 +1,22 @@
using System.Diagnostics;
using System.Windows;
using System.Windows.Navigation;
namespace ClassicAssist.Launcher
{
/// <summary>
/// Interaction logic for ShardsWindow.xaml
/// </summary>
public partial class ShardsWindow : Window
{
public ShardsWindow()
{
InitializeComponent();
}
private void Hyperlink_RequestNavigate( object sender, RequestNavigateEventArgs e )
{
Process.Start( e.Uri.ToString() );
}
}
}
+41
View File
@@ -0,0 +1,41 @@
#region License
// Copyright (C) 2020 Reetus
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#endregion
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
namespace ClassicAssist.Launcher
{
public static class Utility
{
public static async Task<IPAddress> ResolveAddress( string hostname )
{
if ( IPAddress.TryParse( hostname, out IPAddress address ) )
{
return address;
}
IPHostEntry hostentry = await Dns.GetHostEntryAsync( hostname );
return hostentry?.AddressList.FirstOrDefault( i => i.AddressFamily == AddressFamily.InterNetwork );
}
}
}
@@ -0,0 +1,43 @@
#region License
// Copyright (C) 2020 Reetus
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#endregion
using System;
using System.Globalization;
using System.Windows.Data;
namespace ClassicAssist.Launcher.ValueConverters
{
public class BooleanToOpacityValueConverter : IValueConverter
{
public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
{
if ( value is bool val && !val )
{
return 0.5;
}
return 1.0;
}
public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
{
throw new NotImplementedException();
}
}
}
@@ -0,0 +1,46 @@
#region License
// Copyright (C) 2020 Reetus
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#endregion
using System;
using System.Globalization;
using System.Windows.Data;
namespace ClassicAssist.Launcher.ValueConverters
{
public class CellWidthValueConverter : IValueConverter
{
private double substractValue = 15;
public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
{
if ( parameter != null )
{
substractValue = double.Parse( parameter.ToString() );
}
double? val = (double?) value - substractValue;
return val;
}
public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
{
return (double?) value + substractValue;
}
}
}
@@ -0,0 +1,27 @@
using System;
using System.Globalization;
using System.Windows.Data;
namespace ClassicAssist.Launcher.ValueConverters
{
public class InverseBooleanConverter : IValueConverter
{
public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
{
try
{
bool testValue = (bool) value;
return !testValue; // or do whatever you need with this boolean
}
catch
{
return true;
} // or false
}
public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
{
return Convert( value, targetType, parameter, culture );
}
}
}