diff --git a/ConfigEditor/ConfigEditor.csproj b/ConfigEditor/ConfigEditor.csproj index 528f0d25..5ee8c762 100644 --- a/ConfigEditor/ConfigEditor.csproj +++ b/ConfigEditor/ConfigEditor.csproj @@ -1,4 +1,4 @@ - + WinExe @@ -148,10 +148,7 @@ - - - - + diff --git a/ConfigEditor/lang/a20b/ja_ConfigData.xml b/ConfigEditor/lang/a20b/ja_ConfigData.xml index 294770fd..75ea9720 100644 --- a/ConfigEditor/lang/a20b/ja_ConfigData.xml +++ b/ConfigEditor/lang/a20b/ja_ConfigData.xml @@ -1,42 +1,48 @@  - サーバー名を設定します。サーバーリストにはこの名前で表示されます。 + サーバー名を設定します。 + サーバーリストにはこの名前で表示されます。 サーバーの説明を設定します。 + サーバリストではこの説明文が表示されます。 サーバーのウェブサイトを設定します。 + サーバリストのリンクをクリックするとこのリンクがブラウザで開かれます。 - サーバーパスワードを設定します。サーバーに入る際に問われます。 + サーバーパスワードを設定します。 + サーバーに入る際に問われます。 - サーバに入室した際に初めに表示させるメッセージ文です。 - 空にした場合は表示されません。 + サーバに入室した際に初めに表示させるコンフォームのメッセージ文です。空にした場合は表示されません。 + このコンフォームを更に複雑に変更する場合は、XUiの"serverjoinrulesdialog"を変更してください。 サーバーが待機するポート番号を設定します。 + 同じLAN内のPCにLANサーバーとして認識させたい場合は、26900〜26905、27015〜27020の範囲で指定してください。 サーバーの公開状況を設定します。 1に設定した場合は最初のプレイヤーだけ直接IPアドレスを入力する必要があります。 + 2 = 公開, 1 = フレンドリストのみ, 0 = 表示させない. - ネットワークプロトコルで使用させないものを設定します。複数指定する場合はカンマ区切りでできます。現段階ではLiteNetLib, SteamNetworkingの2つ。 + ネットワークプロトコルで使用させないものを設定します。複数指定する場合はカンマ区切りでできます。 + 現段階ではLiteNetLib, SteamNetworkingの2つがネットワークプロトコルとして使用されているようです。 Dedicatedサーバの場合で、NATルータを使用していないく、正しくポートフォワーディングが設定されている場合はSteamNetworkingを無効化します。 - Maximum (!) speed in kiB/s the world is transferred at to a client on first connect if it does not have the world yet. - Maximum is about 1300 kiB/s, even if you set a higher value. + クライアントがまだワールドを持っていない場合、最初の接続時にワールドを転送する最大速度をkiB/sで指定します。最大値は約1300kiB/sです。 参加できる最大人数を設定します。 - MaxPlayerCountを超えて参加する場合に使用される特殊なプレイヤースロットです。 + MaxPlayerCountのうち、一部の数だけ使用される特殊なプレイヤースロットです。 ここで参加するプレイヤーはServerReservedSlotsPermissionで指定される権限が適用されます。 @@ -68,15 +74,16 @@ Telnetにアクセスする際のパスワードです。 + もしパスワードが空の場合、ローカルループバックアドレスからのみ接続可能となります。 - After this many wrong passwords from a single remote client the client will be blocked from connecting to the Telnet interface + 1箇所から指定した数だけパスワードを間違えると、クライアントはTelnetへの接続をブロックされます。 - How long will the block persist (in seconds) + Telnetへの接続をブロックされた際の時間を指定します。(秒単位) - ターミナルウィンドウを表示し、ログの出力やコマンドの入力ができます。a17ではこちらでもサーバの管理ができるようになり ました。 + ターミナルウィンドウを表示し、ログの出力やコマンドの入力ができます。a17ではこちらでもサーバの管理ができるようになりました。 ただし、Windows専用なのでLinuxやmacOSでは今までどおりTelnetを使いましょう。 @@ -86,20 +93,18 @@ EasyAntiCheatを有効にするかしないか。 - EACは主に海賊版対策で用いら、VACのようにチートを防御するものではないらしいため注意。 - Hide logging of command execution. + コマンド実行の履歴をログで隠すかどうか。 - 0 = show everything - 1 = hide only from Telnet/ControlPanel - 2 = also hide from remote game clients - 3 = hide everything + 0 = 全て表示 + 1 = Telnet/ControlPanelからのみ隠す + 2 = ゲームからのみ隠す + 3 = 全て隠す 各プレイヤーがどれだけの範囲でチャンクを描写するかどうかを設定します。 プレイヤーあたりの最大マップファイルサイズは512バイトにこの値を掛けたものです。 - 標準値は131072で、ゲーム内で32km2を表します。 最小単位は4096/km2でしょうか。 - 原文 => Override how many chunks can be uncovered on the ingame map by each player. Resulting max map file size limit per player is (x * 512 Bytes), uncovered area is (x * 256 m2). Default 131072 means max 32 km2 can be uncovered at any time + 標準値は131072で、ゲーム内で32km2を表します。 参加時にプロフィールを更新するかしないか。 @@ -107,15 +112,16 @@ もしユーザーがプロフィールを変更した場合、この値をfalseにしていないと更新されません。 - ワールド生成の種類を設定します。現時点ではランダム生成のRWGもしくは既定のワールド(Nevezgene)が設定できます。 + ワールド生成の種類を設定します。現時点ではランダム生成のRWGもしくは既定のワールド(Worldsフォルダ内にある) "Navezgane"、"PREGEN01"などが指定できます。 + RWGの場合はWorldGenSeedとWorldGenSizeによっては生成に時間がかかる可能性があります。 GameWorldでRWGが選択された際に用いられるシード値です。もし既に生成したことのあるワールドなら読み込みがすぐに終わります。 GameWorldでRWGが選択された際に生成されるマップのサイズを2048から16384の間で指定します。 - 小さいとマップは小さくなりますが、生成時間と生成に消費されるメモリが少なく、大きいと数値に比例して増大します。 - 恐らく半径のサイズのことで、1ブロック単位じゃないかと思います。 + 小さいとマップは小さくなりますが、生成時間と生成に消費されるメモリが少なくなります。逆に大きいと数値に比例して増大します。 + 恐らく単位はxzのブロック数のことで、1ブロック単位じゃないかと思います。 ゲーム名を設定します。この値は保存する際のディレクトリ名となり、木などの配置のためのシード値でもあります。 @@ -141,8 +147,7 @@ 取得するXPの量の割合(%)です。 - プレイヤーのスポーン時に指定されたレベル分だけ敵性生物の出現を停止させます。 - ただし、このレベルがどの程度の広さを指すかは不明。 + プレイヤーのスポーン時に指定されたレベル以下の時だけ敵性生物の出現を停止させます。 PlayerSafeZoneLevelの安全が保証される時間です。なおゲーム内時間らしいです。 @@ -154,7 +159,7 @@ 1日の時間をリアルタイムで何分とするかを設定します。 - ゲーム無い時間で昼の時間を設定します。こちらはリアルタイムではないので要注意。 + ゲーム内時間で昼の時間を設定します。こちらはリアルタイムではないので要注意。 死亡した際にアイテムをドロップするかどうか。 @@ -172,63 +177,95 @@ 3 = バックパックのみ - ベッドロールの安全圏を設定します。このエリア内はゾンビは湧きません。既に無効化されたベッドロールは効果は無いようです。 - 原文 => Size of bedroll deadzone, no zombies will spawn inside this area, and any cleared sleeper volumes that touch a bedroll deadzone will not spawn after they've been cleared. + ベッドロールの安全圏を設定します。このエリア内はゾンビ(スリーパー含めて)は湧きません。既に無効化されたベッドロールは効果は無いようです。 ベッドロールが最終オンラインから何日で無効化されるかどうか。 - ゲーム無い時間なのかリアル時間なのかは不明 - 原文 => Number of days a bedroll stays active after owner was last online + ゲーム内時間なのかリアル時間なのかは不明 ゾンビの最大湧き数。 増やしすぎるとメモリ消費やCPU消費が増加するため注意。 - 動物の最大湧き数。 + サーバーに多くのプレイヤーがいる場合、この制限を増やして野生動物を増やすことができます。 + 動物はゾンビほどCPUを消費しません。 + 注意: + これにより任意に多くの動物が生まれるわけではありません。 + もし多くのプレイヤーが分散している場合、制限に達している可能性があるので制限を増やすことでスポーン数が増えます。 - Max viewdistance a client may request (6 - 12). High impact on memory usage and performance. + クライアントが要求できる最大表示距離(6 - 12)。 + メモリ使用量とパフォーマンスに大きな影響を与えます。 敵を出現させるかどうか。 - 通常の敵をノーマルモードにするかフェラルにするかどうかの設定?未検証なので不明。 + 通常の敵をノーマルモードにするかフェラルにするかどうかの設定です。 0 = Normal 1 = Feral - 0-3 (Off, Day, Night, All) + フェラルゾンビ(だけ?)の感覚を強化する設定です。視覚や聴覚、嗅覚などの距離を増やすらしいです。 + 設定値はおそらく日中だけ、夜間だけ強化するみたいな感じでしょうか?試してないので不明。 + + 0 = Off + 1 = Day + 2 = Night + 3 = All - おそらく昼のゾンビの速度の設定? - 0-4 (walk, jog, run, sprint, nightmare) + 昼のゾンビの速度の設定です。 + + 0 = walk + 1 = jog + 2 = run + 3 = sprint + 4 = nightmare - おそらく夜のゾンビの速度の設定? - 0-4 (walk, jog, run, sprint, nightmare) + 夜のゾンビの速度の設定です。 + + 0 = walk + 1 = jog + 2 = run + 3 = sprint + 4 = nightmare - おそらくフェラルゾンビの速度の設定? - 0-4 (walk, jog, run, sprint, nightmare) + フェラルゾンビの速度の設定です。 + + 0 = walk + 1 = jog + 2 = run + 3 = sprint + 4 = nightmare - 不明。 - 0-4 (walk, jog, run, sprint, nightmare) + ブラッドムーンホードの際のゾンビ歩行速度の設定です。 + + 0 = walk + 1 = jog + 2 = run + 3 = sprint + 4 = nightmare - What frequency (in days) should a blood moon take place + ブラッドムーンホードの間隔を設定します。単位は日。 - How many days can the actual blood moon day randomly deviate from the above setting. Setting this to 0 makes blood moons happen exactly each Nth day as specified in BloodMoonFrequency + ブラッドムーンホードをBloodMoonFrequencyで指定した日数から指定した日数からランダムで選定された日数をズラします。 + 0の場合はBloodMoonFrequencyの値通りでブラッドムーンホードが来ます。 + 要するに0以外にするといつホードが来るかわからなくなります。 - The Hour number that the red day number begins on a blood moon day. Setting this to -1 makes the red never show. + ブラッドムーンホードの際の経過日数を赤字にする開始時間を設定します。(ゲーム内の8時?) + -1を設定すると赤字になりません。 - The number of zombies spawned during blood moons per player. + ブラッドムーンホードの敵対生物の出現数をプレイヤーごとに設定します。 一つの探索物から得られる資源の割合。 @@ -238,6 +275,7 @@ 航空支援の投下する間隔。ゲーム内時間(h)で指定します。 + 0にすると救援物資は投下されません。 支援物資が投下された時、マップに支援物資の位置を表示します。 @@ -247,51 +285,63 @@ プレイヤー同士のキルのモードを設定します。 + 0 = プレイヤーキルなし - 1 = 同盟(フレンド?)のみキルあり - 2 = フレンド以外キルあり + 1 = 同盟のみキルあり + 2 = 同盟以外キルあり 3 = 全員対象 - Maximum allowed land claims per player. + プレイヤーごとに設置できるランドクレイムブロックの最大数です。 - Size in blocks that is protected by a keystone + ランドクレイムブロックで保護されるブロックサイズです。 - Keystones must be this many blocks apart (unless you are friends with the other player) + 他のランドクレイムブロックを設置できなくする距離を設定します。 + フレンド(同盟のこと?)の場合は除く。 - The number of days a player can be offline before their claims expire and are no longer protected + プレーヤーがオフラインの状態で、ランドクレイムブロックが保護されなくなるまでの日数(現実時間?) - - Controls how offline players land claims decay. All claims have full protection for the first 24hrs. 0=Linear, 1=Exponential, 2=Full protection until claim is expired. + + オフラインプレーヤーのランドクレームがどのように減衰するかを設定します。 + + 0 = 線形関数 + 1 = 指数関数 + 2 = クレームが期限切れになるまで完全に保護されます。 - How much protected claim area block hardness is increased when a player is online. 0 means infinite (no damage will ever be taken). Default is 4x + プレイヤーがオンラインのときに、保護されたランドクレームエリア内のブロックの強度を倍率でどれだけ増加するか。 + 0を設定するとダメージを受けなくなります。 + デフォルトは4倍です。 - How much protected claim area block hardness is increased when a player is offline. 0 means infinite (no damage will ever be taken). Default is 4x + プレイヤーがオフラインのときに、保護されたランドクレームエリア内のブロックの強度を倍率でどれだけ増加するか。 + 0を設定するとダメージを受けなくなります。 + デフォルトは4倍です。 - The number of minutes after a player logs out that the land claim area hardness transitions from online to offline. Default is 0 + プレイヤーがログアウトしてから、ランドクレイムエリア内のブロックの強度がオンラインからオフラインモードに遷移するまでの時間(分)です。 + デフォルトは0分です。 - - Is Dynamic Mesh system enabled + + DynamicMeshシステムを有効にします。 - - Is Dynamic Mesh system only active in player LCB areas + + DynamicMeshシステムをランドクレイムブロックエリア内でのみ有効にします。 Dynamic Mesh LCB chunk radius - How many items can be processed concurrently, higher values use more RAM + 同時に処理できるアイテムの数です。数値が高ければ高いほど多くのRAMを消費します。 - Required permission level to use twitch integration on the server + サーバーでTwitch Integrationを使用するために必要なパーミッションレベル - - If the server allows twitch actions during a blood moon. This could cause server lag with extra zombies being spawned during blood moon. + + ブラッドムーンホード中にTwitch Integrationを許可するかどうか(?) + ブラッドムーン中にサーバーがtwitchアクションを許可した場合、余計なゾンビが発生してサーバーラグが発生する可能性があります。 \ No newline at end of file diff --git a/SSH.NET.LICENSE.txt b/SSH.NET.LICENSE.txt new file mode 100644 index 00000000..d13cc4b2 --- /dev/null +++ b/SSH.NET.LICENSE.txt @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/SavannahManager.sln b/SavannahManager.sln index 77260496..98c52853 100644 --- a/SavannahManager.sln +++ b/SavannahManager.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29009.5 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.32014.148 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libraries", "Libraries", "{2FA6990C-0A0D-4D9C-8C0E-67EBE81C0053}" EndProject @@ -36,6 +36,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SavannahManager", "Savannah EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Updater", "Updater\Updater.csproj", "{53D5F6A6-6218-4B2F-B409-2F8585516C73}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SshConsole", "SshConsole\SshConsole.csproj", "{3237FA14-ABBF-424A-923F-E511C8E84D83}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -130,6 +132,18 @@ Global {53D5F6A6-6218-4B2F-B409-2F8585516C73}.Release|x64.Build.0 = Release|Any CPU {53D5F6A6-6218-4B2F-B409-2F8585516C73}.Release|x86.ActiveCfg = Release|Any CPU {53D5F6A6-6218-4B2F-B409-2F8585516C73}.Release|x86.Build.0 = Release|Any CPU + {3237FA14-ABBF-424A-923F-E511C8E84D83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3237FA14-ABBF-424A-923F-E511C8E84D83}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3237FA14-ABBF-424A-923F-E511C8E84D83}.Debug|x64.ActiveCfg = Debug|Any CPU + {3237FA14-ABBF-424A-923F-E511C8E84D83}.Debug|x64.Build.0 = Debug|Any CPU + {3237FA14-ABBF-424A-923F-E511C8E84D83}.Debug|x86.ActiveCfg = Debug|Any CPU + {3237FA14-ABBF-424A-923F-E511C8E84D83}.Debug|x86.Build.0 = Debug|Any CPU + {3237FA14-ABBF-424A-923F-E511C8E84D83}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3237FA14-ABBF-424A-923F-E511C8E84D83}.Release|Any CPU.Build.0 = Release|Any CPU + {3237FA14-ABBF-424A-923F-E511C8E84D83}.Release|x64.ActiveCfg = Release|Any CPU + {3237FA14-ABBF-424A-923F-E511C8E84D83}.Release|x64.Build.0 = Release|Any CPU + {3237FA14-ABBF-424A-923F-E511C8E84D83}.Release|x86.ActiveCfg = Release|Any CPU + {3237FA14-ABBF-424A-923F-E511C8E84D83}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -142,6 +156,7 @@ Global {FA07FC46-E341-4DBF-9B3C-1741C9ACF50A} = {0333E27F-0504-40A4-A258-7D138F45DFE3} {E59C12D3-59AC-4993-AB2A-4F1BD121E596} = {0333E27F-0504-40A4-A258-7D138F45DFE3} {53D5F6A6-6218-4B2F-B409-2F8585516C73} = {0333E27F-0504-40A4-A258-7D138F45DFE3} + {3237FA14-ABBF-424A-923F-E511C8E84D83} = {5A07C2C2-CEB4-4416-88D0-C861C5FC70CD} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {31C190B0-ABF9-42A1-9D21-B9089B220FA9} diff --git a/SavannahManager/App.xaml b/SavannahManager/App.xaml index 42584433..76a68433 100644 --- a/SavannahManager/App.xaml +++ b/SavannahManager/App.xaml @@ -2,7 +2,7 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:_7dtd_svmanager_fix_mvvm" - Startup="MyApp_Startup" + Startup="MyApp_Startup" Exit="App_OnExit" DispatcherUnhandledException="Application_DispatcherUnhandledException"> diff --git a/SavannahManager/App.xaml.cs b/SavannahManager/App.xaml.cs index 2f11afdc..2916c94c 100644 --- a/SavannahManager/App.xaml.cs +++ b/SavannahManager/App.xaml.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using System.Windows; using System.Windows.Threading; +using _7dtd_svmanager_fix_mvvm.Models.Interfaces; namespace _7dtd_svmanager_fix_mvvm { @@ -13,7 +14,7 @@ namespace _7dtd_svmanager_fix_mvvm /// public partial class App : Application { - private IDisposable _mainWindow; + private IRelease _mainWindow; private void MyApp_Startup(object sender, StartupEventArgs e) { TaskScheduler.UnobservedTaskException += TaskSchedulerOnUnobservedTaskException; @@ -24,19 +25,25 @@ private void MyApp_Startup(object sender, StartupEventArgs e) mainWindow.Show(); } + private void App_OnExit(object sender, ExitEventArgs e) + { + _mainWindow.Dispose(); + } + private void CurrentDomainOnUnhandledException(object sender, UnhandledExceptionEventArgs e) { if (e.ExceptionObject is Exception exception) { ShowAndWriteException(exception); - _mainWindow.Dispose(); + _mainWindow.Release(); } } private void TaskSchedulerOnUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e) { - ShowAndWriteException(e.Exception); - _mainWindow.Dispose(); + var exception = e.Exception.InnerException; + ShowAndWriteException(exception); + _mainWindow.Release(); } private void Application_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) @@ -58,12 +65,17 @@ public static void ShowAndWriteException(Exception exception) MessageBox.Show(mes, "予期せぬエラー", MessageBoxButton.OK, MessageBoxImage.Error); var dt = DateTime.Now; - OutToFile(AppInfo.GetAppPath() + @"\error-" + dt.ToString("yyyy-MM-dd- HH-mm-ss") + ".log", mes); + OutToFile("error-" + dt.ToString("yyyy-MM-dd- HH-mm-ss") + ".log", mes); } private static void OutToFile(string filename, string text) { - using var fs = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read); + var dirName = "errors"; + var dirInfo = new DirectoryInfo(dirName); + if (!dirInfo.Exists) + dirInfo.Create(); + + using var fs = new FileStream($"{dirInfo.FullName}\\{filename}", FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read); using var sw = new StreamWriter(fs, System.Text.Encoding.UTF8); sw.Write(text); } diff --git a/SavannahManager/Backup/Views/BackupSelector.xaml.cs b/SavannahManager/Backup/Views/BackupSelector.xaml.cs deleted file mode 100644 index 92ac56ca..00000000 --- a/SavannahManager/Backup/Views/BackupSelector.xaml.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Shapes; -using _7dtd_svmanager_fix_mvvm.Backup.Models; -using _7dtd_svmanager_fix_mvvm.Backup.ViewModels; -using _7dtd_svmanager_fix_mvvm.Models; -using CommonStyleLib.Views; - -namespace _7dtd_svmanager_fix_mvvm.Backup.Views -{ - /// - /// BackupSelector.xaml の相互作用ロジック - /// - public partial class BackupSelector : Window - { - public BackupSelector() - { - InitializeComponent(); - } - } -} diff --git a/SavannahManager/Backup/Images/DirectoryIcon.png b/SavannahManager/Images/Backup/DirectoryIcon.png similarity index 100% rename from SavannahManager/Backup/Images/DirectoryIcon.png rename to SavannahManager/Images/Backup/DirectoryIcon.png diff --git a/SavannahManager/Backup/Images/FileIcon.png b/SavannahManager/Images/Backup/FileIcon.png similarity index 100% rename from SavannahManager/Backup/Images/FileIcon.png rename to SavannahManager/Images/Backup/FileIcon.png diff --git a/SavannahManager/Backup/Images/no-image.png b/SavannahManager/Images/Backup/no-image.png similarity index 100% rename from SavannahManager/Backup/Images/no-image.png rename to SavannahManager/Images/Backup/no-image.png diff --git a/SavannahManager/LangResources/SettingsResources.Designer.cs b/SavannahManager/LangResources/SettingsResources.Designer.cs index ca7cb697..8082be30 100644 --- a/SavannahManager/LangResources/SettingsResources.Designer.cs +++ b/SavannahManager/LangResources/SettingsResources.Designer.cs @@ -19,7 +19,7 @@ namespace _7dtd_svmanager_fix_mvvm.LangResources { // または Visual Studio のようなツールを使用して自動生成されました。 // メンバーを追加または削除するには、.ResX ファイルを編集して、/str オプションと共に // ResGen を実行し直すか、または VS プロジェクトをビルドし直します。 - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] public class SettingsResources { @@ -96,6 +96,16 @@ public static string Filter_XmlFile { } } + /// + /// 復元する際のディレクトリパスです。 + ///空の場合は「%AppData%\7DaysToDie」が復元先として使用されます。 に類似しているローカライズされた文字列を検索します。 + /// + public static string Help_BackupRestorePath { + get { + return ResourceManager.GetString("Help_BackupRestorePath", resourceCulture); + } + } + /// /// ベータモードでは開発中の機能を使用することができます。 ///正式に実装する保証はなければ、動作保証もできないので使用には注意してください。 に類似しているローカライズされた文字列を検索します。 @@ -154,6 +164,15 @@ public static string UI_AutoCheckUpdLabel { } } + /// + /// バックアップ保存先のパス に類似しているローカライズされた文字列を検索します。 + /// + public static string UI_BackupDestinationPath { + get { + return ResourceManager.GetString("UI_BackupDestinationPath", resourceCulture); + } + } + /// /// ベータモードの有効化 に類似しているローカライズされた文字列を検索します。 /// @@ -253,6 +272,15 @@ public static string UI_OthersLabel { } } + /// + /// 復元先のパス に類似しているローカライズされた文字列を検索します。 + /// + public static string UI_RestoreDestinationPath { + get { + return ResourceManager.GetString("UI_RestoreDestinationPath", resourceCulture); + } + } + /// /// 保存 に類似しているローカライズされた文字列を検索します。 /// diff --git a/SavannahManager/LangResources/SettingsResources.en-US.resx b/SavannahManager/LangResources/SettingsResources.en-US.resx index 15fe8fc7..c579dab8 100644 --- a/SavannahManager/LangResources/SettingsResources.en-US.resx +++ b/SavannahManager/LangResources/SettingsResources.en-US.resx @@ -112,10 +112,10 @@ 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 Config File Path @@ -129,6 +129,10 @@ XML Files (*.xml)|*.xml|All Files(*.*)|*.* Filter + + The directory path for restoring. +It will be expanded to "%AppData%\7DaysToDie" if the path is empty. + In beta mode, you can use features that are still under development. There is no guarantee that they will be formally implemented, nor can they be guaranteed to work, so please be careful when using them. @@ -154,6 +158,10 @@ In a local environment, 2000 milliseconds (2 seconds) should usually be enough.< Check automatically updates UI, Setting + + Backup Destination Path + UI, Setting + Enable Betamode UI, Setting @@ -176,11 +184,11 @@ In a local environment, 2000 milliseconds (2 seconds) should usually be enough.< Key - UI, 設定 + UI, Setting Edit Key - UI, 設定 + UI, Setting Enable Outputing logs @@ -192,12 +200,16 @@ In a local environment, 2000 milliseconds (2 seconds) should usually be enough.< Length of Console Text - UI, 設定 + UI, Setting Others UI, Setting + + Restore Destination Path + UI, Setting + Save UI, Setting @@ -212,11 +224,11 @@ In a local environment, 2000 milliseconds (2 seconds) should usually be enough.< Shortcut Key - UI, 設定 + UI, Setting Characters - UI, 設定 + UI, Setting Update diff --git a/SavannahManager/LangResources/SettingsResources.resx b/SavannahManager/LangResources/SettingsResources.resx index 029d9184..f16ce60d 100644 --- a/SavannahManager/LangResources/SettingsResources.resx +++ b/SavannahManager/LangResources/SettingsResources.resx @@ -112,10 +112,10 @@ 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 コンフィグファイルパス @@ -129,6 +129,10 @@ XMLファイル (*.xml)|*.xml|すべてのファイル(*.*)|*.* フィルター + + 復元する際のディレクトリパスです。 +空の場合は「%AppData%\7DaysToDie」が復元先として使用されます。 + ベータモードでは開発中の機能を使用することができます。 正式に実装する保証はなければ、動作保証もできないので使用には注意してください。 @@ -154,6 +158,10 @@ Get Timeなどのコンソールログに出力しないで解析する機能で 自動でアップデートをチェックする UI, 設定 + + バックアップ保存先のパス + UI, 設定 + ベータモードの有効化 UI, 設定 @@ -198,6 +206,10 @@ Get Timeなどのコンソールログに出力しないで解析する機能で その他 UI, 設定 + + 復元先のパス + UI, 設定 + 保存 UI, 設定 diff --git a/SavannahManager/Models/AutoRestart.cs b/SavannahManager/Models/AutoRestart.cs new file mode 100644 index 00000000..c4b5b2d6 --- /dev/null +++ b/SavannahManager/Models/AutoRestart.cs @@ -0,0 +1,156 @@ +using _7dtd_svmanager_fix_mvvm.Models.Interfaces; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reactive.Subjects; +using System.Text; +using System.Threading.Tasks; + +namespace _7dtd_svmanager_fix_mvvm.Models +{ + public class AutoRestart : IDisposable + { + #region Fields + + private readonly TimeSpan _baseTime; + private DateTime _thresholdTime; + private DateTime _messageDateTime; + + private bool _isRequestStop; + private readonly MainWindowServerStart _model; + private readonly SettingLoader _setting; + + #endregion + + #region Properties + + public bool IsRestarting { get; private set; } + + #endregion + + #region Events + + private readonly Subject _timeProgress = new(); + public IObservable TimeProgress => _timeProgress; + + private readonly Subject _fewRemaining = new(); + public IObservable FewRemaining => _fewRemaining; + + #endregion + + public AutoRestart(MainWindowServerStart model) + { + _model = model; + _setting = model.Model.Setting; + _baseTime = _setting.IntervalTimeMode switch + { + 0 => new TimeSpan(0, 0, _setting.IntervalTime), + 1 => new TimeSpan(0, _setting.IntervalTime, 0), + _ => new TimeSpan(_setting.IntervalTime, 0, 0) + }; + _thresholdTime = CalculateThresholdTime(_baseTime); + } + + private static DateTime CalculateThresholdTime(TimeSpan baseTime) + { + return DateTime.Now + baseTime; + } + + public void Start() + { + Task.Factory.StartNew(async () => + { + _messageDateTime = DateTime.MinValue; + var isStop = false; + while (!_isRequestStop) + { + if (!isStop && DateTime.Now >= _thresholdTime) + { + IsRestarting = true; + _model.Model.ServerStop(); + isStop = true; + } + + if (isStop) + { + if (!_model.Model.IsConnected) + { + if (!_model.IsSsh) + { + if (!await _model.Model.ServerStart()) + return; + } + else + { + if (!await _model.Model.ServerStartWithSsh()) + return; + } + IsRestarting = false; + isStop = false; + _thresholdTime = CalculateThresholdTime(_baseTime); + } + + await Task.Delay(1000); + } + + _timeProgress.OnNext(_thresholdTime - DateTime.Now); + + if (CanSendMessage()) + { + _fewRemaining.OnNext(_thresholdTime - DateTime.Now); + } + + await Task.Delay(500); + } + + IsRestarting = false; + _timeProgress.OnCompleted(); + }); + } + + public bool CanSendMessage() + { + if (!_setting.IsAutoRestartSendMessage) + return false; + + var startTime = _setting.AutoRestartSendingMessageStartTime; + var startTimeMode = _setting.AutoRestartSendingMessageStartTimeMode; + var interval = _setting.AutoRestartSendingMessageIntervalTime; + var intervalTimeMode = _setting.AutoRestartSendingMessageIntervalTimeMode; + + var startTimeSpan = startTimeMode switch + { + 0 => new TimeSpan(0, 0, startTime), + _ => new TimeSpan(0, startTime, 0) + }; + var intervalTimeSpan = intervalTimeMode switch + { + 0 => new TimeSpan(0, 0, interval), + _ => new TimeSpan(0, interval, 0) + }; + + if (_thresholdTime - DateTime.Now <= startTimeSpan) + { + if (_messageDateTime == DateTime.MinValue) + { + _messageDateTime = DateTime.Now; + } + + if (DateTime.Now - _messageDateTime >= intervalTimeSpan) + { + _messageDateTime = DateTime.Now; + return true; + } + } + + return false; + } + + public void Dispose() + { + _isRequestStop = true; + GC.SuppressFinalize(this); + } + } +} diff --git a/SavannahManager/Backup/Models/BackupSelectorModel.cs b/SavannahManager/Models/Backup/BackupSelectorModel.cs similarity index 94% rename from SavannahManager/Backup/Models/BackupSelectorModel.cs rename to SavannahManager/Models/Backup/BackupSelectorModel.cs index 61ec5664..6684a52d 100644 --- a/SavannahManager/Backup/Models/BackupSelectorModel.cs +++ b/SavannahManager/Models/Backup/BackupSelectorModel.cs @@ -2,24 +2,16 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; -using System.Linq; -using System.Security.Authentication.ExtendedProtection; -using System.Text; -using System.Threading; using System.Threading.Tasks; -using System.Windows.Documents; using System.Windows.Media; -using System.Windows.Media.Imaging; -using _7dtd_svmanager_fix_mvvm.Backup.Models.Image; -using _7dtd_svmanager_fix_mvvm.Models; +using _7dtd_svmanager_fix_mvvm.Models.Backup.Image; using BackupLib.Backup; using BackupLib.CommonPath; -using CommonCoreLib.CommonPath; using CommonExtensionLib.Extensions; using CommonStyleLib.ExMessageBox; using CommonStyleLib.Models; -namespace _7dtd_svmanager_fix_mvvm.Backup.Models +namespace _7dtd_svmanager_fix_mvvm.Models.Backup { public class BackupItem : PathMapItem { @@ -40,11 +32,11 @@ public static IEnumerable ToBackupItem(IEnumerable path var list = new List(); foreach (var pathMapItem in pathMapItems) { - ImageSource imageSource = ImageLoader.LoadFromResource("_7dtd_svmanager_fix_mvvm.Backup.Images.no-image.png"); + ImageSource imageSource = ImageLoader.LoadFromResource("_7dtd_svmanager_fix_mvvm.Images.Backup.no-image.png"); if (pathMapItem.ItemType == PathMapItemType.File) - imageSource = ImageLoader.LoadFromResource("_7dtd_svmanager_fix_mvvm.Backup.Images.FileIcon.png"); + imageSource = ImageLoader.LoadFromResource("_7dtd_svmanager_fix_mvvm.Images.Backup.FileIcon.png"); if (pathMapItem.ItemType == PathMapItemType.Directory) - imageSource = ImageLoader.LoadFromResource("_7dtd_svmanager_fix_mvvm.Backup.Images.DirectoryIcon.png"); + imageSource = ImageLoader.LoadFromResource("_7dtd_svmanager_fix_mvvm.Images.Backup.DirectoryIcon.png"); list.Add(new BackupItem { diff --git a/SavannahManager/Backup/Models/Image/ImageLoader.cs b/SavannahManager/Models/Backup/Image/ImageLoader.cs similarity index 87% rename from SavannahManager/Backup/Models/Image/ImageLoader.cs rename to SavannahManager/Models/Backup/Image/ImageLoader.cs index 270a3b73..a6bf75a6 100644 --- a/SavannahManager/Backup/Models/Image/ImageLoader.cs +++ b/SavannahManager/Models/Backup/Image/ImageLoader.cs @@ -1,12 +1,8 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Windows.Media.Imaging; -namespace _7dtd_svmanager_fix_mvvm.Backup.Models.Image +namespace _7dtd_svmanager_fix_mvvm.Models.Backup.Image { public static class ImageLoader { diff --git a/SavannahManager/Models/CommandCollector.cs b/SavannahManager/Models/CommandCollector.cs new file mode 100644 index 00000000..ccfc8330 --- /dev/null +++ b/SavannahManager/Models/CommandCollector.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace _7dtd_svmanager_fix_mvvm.Models +{ + public class CommandCollector + { + private readonly LinkedList _commands = new(); + private LinkedListNode _current; + + public int MaxSaved { get; set; } = 32; + + public CommandCollector() + { + _commands.AddLast(""); + _current = _commands.Last; + } + + public void AddCommand(string cmd) + { + if (_commands.Count > MaxSaved) + { + _commands.RemoveFirst(); + } + + var last = _commands.Last; + if (last == null) + return; + + var newNode = new LinkedListNode(cmd); + _commands.AddBefore(last, newNode); + } + + public string GetPreviousCommand() + { + if (_current.Previous == null) + return _current.Value; + + var value = _current.Previous.Value; + _current = _current.Previous; + return value; + } + + + public string GetNextCommand() + { + if (_current.Next == null) + return _current.Value; + + var value = _current.Next.Value; + _current = _current.Next; + return value; + } + } +} diff --git a/SavannahManager/Models/Interfaces/IMainWindowServerStart.cs b/SavannahManager/Models/Interfaces/IMainWindowServerStart.cs new file mode 100644 index 00000000..ea97f4b1 --- /dev/null +++ b/SavannahManager/Models/Interfaces/IMainWindowServerStart.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace _7dtd_svmanager_fix_mvvm.Models.Interfaces +{ + public class MainWindowServerStart + { + public IMainWindowServerStart Model { get; set; } + + public bool IsSsh { get; } + + public MainWindowServerStart(IMainWindowServerStart model, bool isSsh) + { + Model = model; + IsSsh = isSsh; + } + } + + public interface IMainWindowServerStart + { + public bool IsConnected { get; } + public SettingLoader Setting { get; } + + Task ServerStart(); + Task ServerStartWithSsh(); + bool ServerStop(); + } +} diff --git a/SavannahManager/Models/IMainWindowTelnet.cs b/SavannahManager/Models/Interfaces/IMainWindowTelnet.cs similarity index 80% rename from SavannahManager/Models/IMainWindowTelnet.cs rename to SavannahManager/Models/Interfaces/IMainWindowTelnet.cs index 51949c5c..05ca03e3 100644 --- a/SavannahManager/Models/IMainWindowTelnet.cs +++ b/SavannahManager/Models/Interfaces/IMainWindowTelnet.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace _7dtd_svmanager_fix_mvvm.Models +namespace _7dtd_svmanager_fix_mvvm.Models.Interfaces { public interface IMainWindowTelnet { diff --git a/SavannahManager/Models/Interfaces/IRelease.cs b/SavannahManager/Models/Interfaces/IRelease.cs new file mode 100644 index 00000000..b396a853 --- /dev/null +++ b/SavannahManager/Models/Interfaces/IRelease.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace _7dtd_svmanager_fix_mvvm.Models.Interfaces +{ + /// + /// Interface of releasing the object. + /// + interface IRelease : IDisposable + { + /// + /// Release the object. Unlike Dispose, the object can be reused. + /// + void Release(); + } +} diff --git a/SavannahManager/Models/LogStream.cs b/SavannahManager/Models/LogStream.cs deleted file mode 100644 index 4a3a0339..00000000 --- a/SavannahManager/Models/LogStream.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System; -using System.IO; -using CommonCoreLib; - -namespace _7dtd_svmanager_fix_mvvm.Models -{ - public class LogStream : IDisposable - { - private FileStream _fs; - private StreamWriter _sw; - - - /// - /// Create Instance of LogFile Stream. - /// - public LogStream(string dirPath) - { - var di = new DirectoryInfo(AppInfo.GetAppPath() + @"\logs"); - if (!di.Exists) - di.Create(); - var dt = DateTime.Now; - - _fs = new FileStream(dirPath + - dt.ToString("yyyy-MM-dd- HH-mm-ss") + ".log", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read); - - _sw = new StreamWriter(_fs, System.Text.Encoding.UTF8) - { - AutoFlush = true - }; - } - - - /// - /// Dispose LogFile Stream. - /// - public void Dispose() - { - if (_sw != null) - { - lock (_sw) - { - _sw?.Dispose(); - _sw = null; - } - } - - if (_fs != null) - { - lock (_fs) - { - _fs?.Dispose(); - _fs = null; - } - } - } - - public void WriteSteam(string text) { - _sw?.Write(text); - } - } -} diff --git a/SavannahManager/Permissions/Models/AbstractGetSteamIdModel.cs b/SavannahManager/Models/Permissions/AbstractGetSteamIdModel.cs similarity index 91% rename from SavannahManager/Permissions/Models/AbstractGetSteamIdModel.cs rename to SavannahManager/Models/Permissions/AbstractGetSteamIdModel.cs index df7949bc..b780d0ce 100644 --- a/SavannahManager/Permissions/Models/AbstractGetSteamIdModel.cs +++ b/SavannahManager/Models/Permissions/AbstractGetSteamIdModel.cs @@ -1,7 +1,7 @@ using System.Threading.Tasks; using CommonStyleLib.Models; -namespace _7dtd_svmanager_fix_mvvm.Permissions.Models +namespace _7dtd_svmanager_fix_mvvm.Models.Permissions { public abstract class AbstractGetSteamIdModel : ModelBase { diff --git a/SavannahManager/Permissions/Models/GetGroupSteamIdModel.cs b/SavannahManager/Models/Permissions/GetGroupSteamIdModel.cs similarity index 85% rename from SavannahManager/Permissions/Models/GetGroupSteamIdModel.cs rename to SavannahManager/Models/Permissions/GetGroupSteamIdModel.cs index 7a3723f7..d37612ef 100644 --- a/SavannahManager/Permissions/Models/GetGroupSteamIdModel.cs +++ b/SavannahManager/Models/Permissions/GetGroupSteamIdModel.cs @@ -1,15 +1,10 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; +using System.IO; using System.Net; -using System.Text; using System.Threading.Tasks; -using CommonStyleLib.Models; using SavannahXmlLib.XmlWrapper; using SvManagerLibrary.Web; -namespace _7dtd_svmanager_fix_mvvm.Permissions.Models +namespace _7dtd_svmanager_fix_mvvm.Models.Permissions { public class GetGroupSteamIdModel : AbstractGetSteamIdModel { diff --git a/SavannahManager/Permissions/Models/GetProfileSteamIdModel.cs b/SavannahManager/Models/Permissions/GetProfileSteamIdModel.cs similarity index 79% rename from SavannahManager/Permissions/Models/GetProfileSteamIdModel.cs rename to SavannahManager/Models/Permissions/GetProfileSteamIdModel.cs index e19b0d0d..be1fde49 100644 --- a/SavannahManager/Permissions/Models/GetProfileSteamIdModel.cs +++ b/SavannahManager/Models/Permissions/GetProfileSteamIdModel.cs @@ -1,17 +1,10 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; +using System.IO; using System.Net; -using System.Runtime.InteropServices; -using System.Text; using System.Threading.Tasks; -using _7dtd_svmanager_fix_mvvm.Models; -using Newtonsoft.Json; using SavannahXmlLib.XmlWrapper; using SvManagerLibrary.Web; -namespace _7dtd_svmanager_fix_mvvm.Permissions.Models +namespace _7dtd_svmanager_fix_mvvm.Models.Permissions { public class GetProfileSteamIdModel : AbstractGetSteamIdModel { diff --git a/SavannahManager/Permissions/Models/PermissionEditorModel.cs b/SavannahManager/Models/Permissions/PermissionEditorModel.cs similarity index 98% rename from SavannahManager/Permissions/Models/PermissionEditorModel.cs rename to SavannahManager/Models/Permissions/PermissionEditorModel.cs index 516a780b..2cc3e623 100644 --- a/SavannahManager/Permissions/Models/PermissionEditorModel.cs +++ b/SavannahManager/Models/Permissions/PermissionEditorModel.cs @@ -3,18 +3,12 @@ using System.Collections.ObjectModel; using System.IO; using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Controls; -using System.Windows.Input; -using CommonExtensionLib.Extensions; using CommonStyleLib.Models; -using Prism.Commands; using Prism.Mvvm; using SavannahXmlLib.XmlWrapper; using SavannahXmlLib.XmlWrapper.Nodes; -namespace _7dtd_svmanager_fix_mvvm.Permissions.Models +namespace _7dtd_svmanager_fix_mvvm.Models.Permissions { public abstract class PermissionBase : BindableBase { diff --git a/SavannahManager/Permissions/Models/UnBanDateSettingModel.cs b/SavannahManager/Models/Permissions/UnBanDateSettingModel.cs similarity index 92% rename from SavannahManager/Permissions/Models/UnBanDateSettingModel.cs rename to SavannahManager/Models/Permissions/UnBanDateSettingModel.cs index bc1cf5df..6a96172b 100644 --- a/SavannahManager/Permissions/Models/UnBanDateSettingModel.cs +++ b/SavannahManager/Models/Permissions/UnBanDateSettingModel.cs @@ -1,13 +1,9 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Text.RegularExpressions; -using System.Threading.Tasks; using CommonExtensionLib.Extensions; using CommonStyleLib.Models; -namespace _7dtd_svmanager_fix_mvvm.Permissions.Models +namespace _7dtd_svmanager_fix_mvvm.Models.Permissions { public class UnBanDateSettingModel : ModelBase { @@ -47,6 +43,9 @@ public string ConvertToString() public static DateTime? ConvertStringToDateTime(string text) { + if (text == null) + return DateTime.Now; + //2035-12-31 23:59:59 var regex = new Regex("(?[0-9]{4})-(?[0-9]{2})-(?[0-9]{2}) (?[0-9]{2}):(?[0-9]{2}):(?[0-9]{2})"); var match = regex.Match(text); diff --git a/SavannahManager/PlayerController/Models/Pages/AdminAddModel.cs b/SavannahManager/Models/PlayerController/Pages/AdminAddModel.cs similarity index 82% rename from SavannahManager/PlayerController/Models/Pages/AdminAddModel.cs rename to SavannahManager/Models/PlayerController/Pages/AdminAddModel.cs index 94d0f8f2..39113135 100644 --- a/SavannahManager/PlayerController/Models/Pages/AdminAddModel.cs +++ b/SavannahManager/Models/PlayerController/Pages/AdminAddModel.cs @@ -1,16 +1,10 @@ -using _7dtd_svmanager_fix_mvvm.Models; -using _7dtd_svmanager_fix_mvvm.PlayerController.Views.Pages; +using System; +using _7dtd_svmanager_fix_mvvm.Models.Interfaces; +using _7dtd_svmanager_fix_mvvm.Views.PlayerController.Pages; using CommonStyleLib.ExMessageBox; -using CommonStyleLib.Models; using Prism.Mvvm; -using SvManagerLibrary.Telnet; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -namespace _7dtd_svmanager_fix_mvvm.PlayerController.Models.Pages +namespace _7dtd_svmanager_fix_mvvm.Models.PlayerController.Pages { public class AdminAddModel : BindableBase, IPlayerPage { diff --git a/SavannahManager/PlayerController/Models/Pages/BanModel.cs b/SavannahManager/Models/PlayerController/Pages/BanModel.cs similarity index 90% rename from SavannahManager/PlayerController/Models/Pages/BanModel.cs rename to SavannahManager/Models/PlayerController/Pages/BanModel.cs index 8b610196..c2187156 100644 --- a/SavannahManager/PlayerController/Models/Pages/BanModel.cs +++ b/SavannahManager/Models/PlayerController/Pages/BanModel.cs @@ -1,15 +1,11 @@ -using _7dtd_svmanager_fix_mvvm.Models; -using _7dtd_svmanager_fix_mvvm.PlayerController.Views.Pages; +using System; +using System.Collections.ObjectModel; +using _7dtd_svmanager_fix_mvvm.Models.Interfaces; +using _7dtd_svmanager_fix_mvvm.Views.PlayerController.Pages; using CommonStyleLib.ExMessageBox; using Prism.Mvvm; -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -namespace _7dtd_svmanager_fix_mvvm.PlayerController.Models.Pages +namespace _7dtd_svmanager_fix_mvvm.Models.PlayerController.Pages { public class DurationInfo { diff --git a/SavannahManager/PlayerController/Models/Pages/KickModel.cs b/SavannahManager/Models/PlayerController/Pages/KickModel.cs similarity index 82% rename from SavannahManager/PlayerController/Models/Pages/KickModel.cs rename to SavannahManager/Models/PlayerController/Pages/KickModel.cs index 89efd830..eb3e466a 100644 --- a/SavannahManager/PlayerController/Models/Pages/KickModel.cs +++ b/SavannahManager/Models/PlayerController/Pages/KickModel.cs @@ -1,14 +1,10 @@ -using _7dtd_svmanager_fix_mvvm.Models; -using _7dtd_svmanager_fix_mvvm.PlayerController.Views.Pages; +using System; +using _7dtd_svmanager_fix_mvvm.Models.Interfaces; +using _7dtd_svmanager_fix_mvvm.Views.PlayerController.Pages; using CommonStyleLib.ExMessageBox; using Prism.Mvvm; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -namespace _7dtd_svmanager_fix_mvvm.PlayerController.Models.Pages +namespace _7dtd_svmanager_fix_mvvm.Models.PlayerController.Pages { public class KickModel : BindableBase, IPlayerPage { diff --git a/SavannahManager/Models/PlayerController/PlayerBaseModel.cs b/SavannahManager/Models/PlayerController/PlayerBaseModel.cs new file mode 100644 index 00000000..bb0ecbb9 --- /dev/null +++ b/SavannahManager/Models/PlayerController/PlayerBaseModel.cs @@ -0,0 +1,9 @@ +using CommonStyleLib.Models; + +namespace _7dtd_svmanager_fix_mvvm.Models.PlayerController +{ + public class PlayerBaseModel : ModelBase + { + + } +} diff --git a/SavannahManager/PlayerController/Models/PlayerInfoModel.cs b/SavannahManager/Models/PlayerController/PlayerInfoModel.cs similarity index 63% rename from SavannahManager/PlayerController/Models/PlayerInfoModel.cs rename to SavannahManager/Models/PlayerController/PlayerInfoModel.cs index eb7e17d6..7d191bd2 100644 --- a/SavannahManager/PlayerController/Models/PlayerInfoModel.cs +++ b/SavannahManager/Models/PlayerController/PlayerInfoModel.cs @@ -1,12 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using CommonExtensionLib.Extensions; +using CommonExtensionLib.Extensions; using CommonStyleLib.Models; -namespace _7dtd_svmanager_fix_mvvm.PlayerController.Models +namespace _7dtd_svmanager_fix_mvvm.Models.PlayerController { public class PlayerInfoModel : ModelBase { diff --git a/SavannahManager/Models/SettingLoader.cs b/SavannahManager/Models/SettingLoader.cs index 5f98f04c..ecbfdcca 100644 --- a/SavannahManager/Models/SettingLoader.cs +++ b/SavannahManager/Models/SettingLoader.cs @@ -2,24 +2,18 @@ using System.Diagnostics; using System.IO; using _7dtd_svmanager_fix_mvvm.LangResources; +using _7dtd_svmanager_fix_mvvm.Views.UserControls; using CommonCoreLib.CommonPath; using CommonCoreLib.Ini; +using SvManagerLibrary.Crypto; namespace _7dtd_svmanager_fix_mvvm.Models { - public sealed class SettingLoader + public sealed class SettingLoader : IDisposable { - /// - /// Singleton SettingLoader instance for all. - /// - public static SettingLoader SettingInstance { private set; get; } - - static SettingLoader() - { - SettingInstance = new SettingLoader(ConstantValues.SettingFilePath); - } private const string MainClassName = "Main"; + private const string AutoRestartClassName = "AutoRestart"; private const string ServerClassName = "Server"; private const string BackupClassName = "Backup"; @@ -57,16 +51,61 @@ static SettingLoader() public bool IsAutoUpdate { get; set; } + public bool IsEncryptPassword { get; set; } + + + #region Auto Restart + + public int IntervalTime { get; set; } + + public int IntervalTimeMode { get; set; } + + public bool IsAutoRestartSendMessage { get; set; } + + public int AutoRestartSendingMessageStartTime { get; set; } + + public int AutoRestartSendingMessageStartTimeMode { get; set; } + + public int AutoRestartSendingMessageIntervalTime { get; set; } + + public int AutoRestartSendingMessageIntervalTimeMode { get; set; } + + public string AutoRestartSendingMessageFormat { get; set; } + + #endregion + + public string BackupDirPath { get; set; } public string RestoreDirPath { get; set; } public bool IsConsoleLogTextWrapping { get; set; } + + public string SshAddress { get; set; } + + public int SshPort { get; set; } + + public string SshUserName { get; set; } + + public string SshPassword { get; set; } + + public string SshExeFileDirectory { get; set; } + + public string SshConfigFileName { get; set; } + + public int SshAuthMode { get; set; } + + public string SshKeyPath { get; set; } + + public bool CanEncrypt => _encryptWrapper != null; + #endregion private readonly IniLoader _iniLoader; + private RijndaelWrapper _encryptWrapper; + public SettingLoader(string filename) { _iniLoader = new IniLoader(filename); @@ -125,6 +164,12 @@ private void LoadOldFormat() private void Load() { + IsEncryptPassword = _iniLoader.GetValue(MainClassName, "IsEncryptPassword", false); + if (!IsEncryptPassword) + { + Password = _iniLoader.GetValue(ServerClassName, "Password", ""); + } + Width = _iniLoader.GetValue(MainClassName, "Width", 900); Height = _iniLoader.GetValue(MainClassName, "Height", 550); @@ -136,8 +181,6 @@ private void Load() Port = _iniLoader.GetValue(ServerClassName, "Port", 8081); - Password = _iniLoader.GetValue(ServerClassName, "Password", ""); - LocalMode = _iniLoader.GetValue(MainClassName, "LocalServerMode", true); CultureName = _iniLoader.GetValue(MainClassName, "Culture", ResourceService.English); @@ -154,11 +197,57 @@ private void Load() IsAutoUpdate = _iniLoader.GetValue(MainClassName, "IsUpdateCheck", true); - BackupDirPath = _iniLoader.GetValue(BackupClassName, "DirPath", "backup").UnifiedSystemPathSeparator(); + IntervalTime = _iniLoader.GetValue(AutoRestartClassName, "IntervalTime", 5); + IntervalTimeMode = _iniLoader.GetValue(AutoRestartClassName, "IntervalTimeMode", 2); + IsAutoRestartSendMessage = _iniLoader.GetValue(AutoRestartClassName, "IsSendMessage", false); + AutoRestartSendingMessageStartTime = + _iniLoader.GetValue(AutoRestartClassName, "SendingMessageStartTime", 1); + AutoRestartSendingMessageStartTimeMode = + _iniLoader.GetValue(AutoRestartClassName, "SendingMessageStartTimeMode", 1); + AutoRestartSendingMessageIntervalTime = + _iniLoader.GetValue(AutoRestartClassName, "SendingMessageIntervalTime", 10); + AutoRestartSendingMessageIntervalTimeMode = + _iniLoader.GetValue(AutoRestartClassName, "SendingMessageIntervalTimeMode", 0); + AutoRestartSendingMessageFormat = _iniLoader.GetValue(MainClassName, "SendingMessageFormat", + "Restart the server after {0} seconds."); + BackupDirPath = _iniLoader.GetValue(BackupClassName, "DirPath", "backup").UnifiedSystemPathSeparator(); RestoreDirPath = _iniLoader.GetValue(BackupClassName, "RestoreDirPath", "").UnifiedSystemPathSeparator(); IsConsoleLogTextWrapping = _iniLoader.GetValue(MainClassName, "IsConsoleTextWrapping", false); + + SshAddress = _iniLoader.GetValue(ServerClassName, "SshAddress", ""); + SshPort = _iniLoader.GetValue(ServerClassName, "SshPort", 22); + SshUserName = _iniLoader.GetValue(ServerClassName, "SshUserName", ""); + SshExeFileDirectory = _iniLoader.GetValue(ServerClassName, "SshExeFileDirectory", ""); + SshConfigFileName = _iniLoader.GetValue(ServerClassName, "SshConfigFileName", ""); + SshAuthMode = _iniLoader.GetValue(ServerClassName, "SshAuthMode", AuthMode.Password.ToInt()); + SshKeyPath = _iniLoader.GetValue(ServerClassName, "SshKeyPath", ""); + } + + public void SetEncryptionPassword(string password, string salt) + { + salt ??= Environment.MachineName; + _encryptWrapper = new RijndaelWrapper(password, CommonCoreLib.Crypto.Sha256.GetSha256(salt)); + } + + public void LoadEncryptionData() + { + var encryptedPassword = _iniLoader.GetValue(ServerClassName, "Password", ""); + var encryptedSshPassword = _iniLoader.GetValue(ServerClassName, "SshPassword", ""); + + try + { + Password = _encryptWrapper.Decrypt(encryptedPassword); + SshPassword = _encryptWrapper.Decrypt(encryptedSshPassword); + } + catch + { + Password = ""; + SshPassword = ""; + _encryptWrapper = null; + throw; + } } public void ApplyCulture() @@ -169,6 +258,21 @@ public void ApplyCulture() public void Save() { _iniLoader.SetValue(MainClassName, "Version", "1.1"); + + _iniLoader.SetValue(MainClassName, "IsEncryptPassword", IsEncryptPassword); + if (!IsEncryptPassword) + { + _iniLoader.SetValue(ServerClassName, "Password", Password); + } + else + { + if (_encryptWrapper != null && !string.IsNullOrEmpty(Password)) + { + _iniLoader.SetValue(ServerClassName, "Password", _encryptWrapper.Encrypt(Password ?? string.Empty)); + _iniLoader.SetValue(ServerClassName, "SshPassword", _encryptWrapper.Encrypt(SshPassword ?? string.Empty)); + } + } + _iniLoader.SetValue(MainClassName, "Width", Width); _iniLoader.SetValue(MainClassName, "Height", Height); _iniLoader.SetValue(ServerClassName, "ExePath", ExeFilePath); @@ -176,7 +280,6 @@ public void Save() _iniLoader.SetValue(ServerClassName, "AdminPath", AdminFilePath); _iniLoader.SetValue(ServerClassName, "Address", Address); _iniLoader.SetValue(ServerClassName, "Port", Port); - _iniLoader.SetValue(ServerClassName, "Password", Password); _iniLoader.SetValue(MainClassName, "LocalServerMode", LocalMode); _iniLoader.SetValue(MainClassName, "Culture", CultureName); _iniLoader.SetValue(MainClassName, "ConsoleLogLength", ConsoleTextLength); @@ -185,9 +288,29 @@ public void Save() _iniLoader.SetValue(MainClassName, "IsLogOutput", IsLogGetter); _iniLoader.SetValue(MainClassName, "IsFirstBoot", IsFirstBoot); _iniLoader.SetValue(MainClassName, "IsUpdateCheck", IsAutoUpdate); + _iniLoader.SetValue(AutoRestartClassName, "IntervalTime", IntervalTime); + _iniLoader.SetValue(AutoRestartClassName, "IntervalTimeMode", IntervalTimeMode); + _iniLoader.SetValue(AutoRestartClassName, "IsSendMessage", IsAutoRestartSendMessage); + _iniLoader.SetValue(AutoRestartClassName, "SendingMessageStartTime", AutoRestartSendingMessageStartTime); + _iniLoader.SetValue(AutoRestartClassName, "SendingMessageStartTimeMode", AutoRestartSendingMessageStartTimeMode); + _iniLoader.SetValue(AutoRestartClassName, "SendingMessageIntervalTime", AutoRestartSendingMessageIntervalTime); + _iniLoader.SetValue(AutoRestartClassName, "SendingMessageIntervalTimeMode", AutoRestartSendingMessageIntervalTimeMode); + _iniLoader.SetValue(AutoRestartClassName, "SendingMessageFormat", AutoRestartSendingMessageFormat); _iniLoader.SetValue(BackupClassName, "DirPath", BackupDirPath); _iniLoader.SetValue(BackupClassName, "RestoreDirPath", RestoreDirPath); _iniLoader.SetValue(MainClassName, "IsConsoleTextWrapping", IsConsoleLogTextWrapping); + _iniLoader.SetValue(ServerClassName, "SshAddress", SshAddress); + _iniLoader.SetValue(ServerClassName, "SshPort", SshPort); + _iniLoader.SetValue(ServerClassName, "SshUserName", SshUserName); + _iniLoader.SetValue(ServerClassName, "SshExeFileDirectory", SshExeFileDirectory); + _iniLoader.SetValue(ServerClassName, "SshConfigFileName", SshConfigFileName); + _iniLoader.SetValue(ServerClassName, "SshAuthMode", SshAuthMode); + _iniLoader.SetValue(ServerClassName, "SshKeyPath", SshKeyPath); + } + + public void Dispose() + { + _encryptWrapper?.Dispose(); } } } diff --git a/SavannahManager/Setup/ViewModels/INavigationRefresh.cs b/SavannahManager/Models/Settings/InputWindowModel.cs similarity index 51% rename from SavannahManager/Setup/ViewModels/INavigationRefresh.cs rename to SavannahManager/Models/Settings/InputWindowModel.cs index e2b7483b..2ae9a003 100644 --- a/SavannahManager/Setup/ViewModels/INavigationRefresh.cs +++ b/SavannahManager/Models/Settings/InputWindowModel.cs @@ -3,11 +3,11 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using CommonStyleLib.Models; -namespace _7dtd_svmanager_fix_mvvm.Setup.ViewModels +namespace _7dtd_svmanager_fix_mvvm.Models.Settings { - public interface INavigationRefresh + public class InputWindowModel : ModelBase { - void RefreshValues(); } } diff --git a/SavannahManager/Settings/Models/KeyConfigModel.cs b/SavannahManager/Models/Settings/KeyConfigModel.cs similarity index 97% rename from SavannahManager/Settings/Models/KeyConfigModel.cs rename to SavannahManager/Models/Settings/KeyConfigModel.cs index 33fec1c3..3e5a9454 100644 --- a/SavannahManager/Settings/Models/KeyConfigModel.cs +++ b/SavannahManager/Models/Settings/KeyConfigModel.cs @@ -1,10 +1,10 @@ -using CommonStyleLib.Models; -using System; +using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Windows.Input; +using CommonStyleLib.Models; -namespace _7dtd_svmanager_fix_mvvm.Settings.Models +namespace _7dtd_svmanager_fix_mvvm.Models.Settings { public class ShortcutKeyForList { diff --git a/SavannahManager/Settings/Models/SettingModel.cs b/SavannahManager/Models/Settings/SettingModel.cs similarity index 58% rename from SavannahManager/Settings/Models/SettingModel.cs rename to SavannahManager/Models/Settings/SettingModel.cs index f28c6ec4..d54c3140 100644 --- a/SavannahManager/Settings/Models/SettingModel.cs +++ b/SavannahManager/Models/Settings/SettingModel.cs @@ -1,9 +1,8 @@ -using _7dtd_svmanager_fix_mvvm.Models; -using CommonStyleLib.Models; +using System.IO; using CommonStyleLib.File; -using System.IO; +using CommonStyleLib.Models; -namespace _7dtd_svmanager_fix_mvvm.Settings.Models +namespace _7dtd_svmanager_fix_mvvm.Models.Settings { public class SettingModel : ModelBase { @@ -15,6 +14,15 @@ public class SettingModel : ModelBase private int _telnetWaitTime = 2; private bool _isBetaMode; private bool _isAutoUpdate = true; + private bool _isEncryptPassword; + private int _intervalTime; + private int _intervalTimeSelectedIndex; + private bool _isAutoRestartSendMessage; + private int _autoRestartSendingMessageStartTime; + private int _autoRestartSendingMessageStartTimeMode; + private int _autoRestartSendingMessageIntervalTime; + private int _autoRestartSendingMessageIntervalTimeMode; + private string _autoRestartSendingMessageFormat; private string _backupDirPath; private string _restoreDirPath; private readonly SettingLoader _setting; @@ -76,6 +84,60 @@ public bool IsAutoUpdate set => base.SetProperty(ref _isAutoUpdate, value); } + public bool IsEncryptPassword + { + get => _isEncryptPassword; + set => SetProperty(ref _isEncryptPassword, value); + } + + public int IntervalTime + { + get => _intervalTime; + set => SetProperty(ref _intervalTime, value); + } + + public int IntervalTimeSelectedIndex + { + get => _intervalTimeSelectedIndex; + set => SetProperty(ref _intervalTimeSelectedIndex, value); + } + + public bool IsAutoRestartSendMessage + { + get => _isAutoRestartSendMessage; + set => SetProperty(ref _isAutoRestartSendMessage, value); + } + + public int AutoRestartSendingMessageStartTime + { + get => _autoRestartSendingMessageStartTime; + set => SetProperty(ref _autoRestartSendingMessageStartTime, value); + } + + public int AutoRestartSendingMessageStartTimeMode + { + get => _autoRestartSendingMessageStartTimeMode; + set => SetProperty(ref _autoRestartSendingMessageStartTimeMode, value); + } + + public int AutoRestartSendingMessageIntervalTime + { + get => _autoRestartSendingMessageIntervalTime; + set => SetProperty(ref _autoRestartSendingMessageIntervalTime, value); + } + + public int AutoRestartSendingMessageIntervalTimeMode + { + get => _autoRestartSendingMessageIntervalTimeMode; + set => SetProperty(ref _autoRestartSendingMessageIntervalTimeMode, value); + } + + public string AutoRestartSendingMessageFormat + { + get => _autoRestartSendingMessageFormat; + set => SetProperty(ref _autoRestartSendingMessageFormat, value); + } + public string BackupDirPath { get => _backupDirPath; @@ -88,6 +150,7 @@ public string RestoreDirPath set => SetProperty(ref _restoreDirPath, value); } + public bool IsRequirePassword => !_setting.CanEncrypt; public ShortcutKeyManager ShortcutKeyManager { get; } @@ -107,11 +170,26 @@ public SettingModel(SettingLoader setting, ShortcutKeyManager shortcutKeyManager TelnetWaitTime = setting.TelnetWaitTime; IsBetaMode = setting.IsBetaMode; IsAutoUpdate = setting.IsAutoUpdate; + IsEncryptPassword = setting.IsEncryptPassword; + IntervalTime = setting.IntervalTime; + IntervalTimeSelectedIndex = setting.IntervalTimeMode; + IsAutoRestartSendMessage = setting.IsAutoRestartSendMessage; + AutoRestartSendingMessageStartTime = setting.AutoRestartSendingMessageStartTime; + AutoRestartSendingMessageStartTimeMode = setting.AutoRestartSendingMessageStartTimeMode; + AutoRestartSendingMessageIntervalTime = setting.AutoRestartSendingMessageIntervalTime; + AutoRestartSendingMessageIntervalTimeMode = setting.AutoRestartSendingMessageIntervalTimeMode; + AutoRestartSendingMessageFormat = setting.AutoRestartSendingMessageFormat; BackupDirPath = setting.BackupDirPath; RestoreDirPath = setting.RestoreDirPath; } } + public void EnabledEncryptionData(string password, string salt) + { + salt = string.IsNullOrEmpty(salt) ? null : salt; + _setting.SetEncryptionPassword(password, salt); + } + public void Save() { if (_setting != null) @@ -124,6 +202,15 @@ public void Save() _setting.TelnetWaitTime = TelnetWaitTime; _setting.IsBetaMode = IsBetaMode; _setting.IsAutoUpdate = IsAutoUpdate; + _setting.IsEncryptPassword = IsEncryptPassword; + _setting.IntervalTime = IntervalTime; + _setting.IntervalTimeMode = IntervalTimeSelectedIndex; + _setting.IsAutoRestartSendMessage = IsAutoRestartSendMessage; + _setting.AutoRestartSendingMessageStartTime = AutoRestartSendingMessageStartTime; + _setting.AutoRestartSendingMessageStartTimeMode = AutoRestartSendingMessageStartTimeMode; + _setting.AutoRestartSendingMessageIntervalTime = AutoRestartSendingMessageIntervalTime; + _setting.AutoRestartSendingMessageIntervalTimeMode = AutoRestartSendingMessageIntervalTimeMode; + _setting.AutoRestartSendingMessageFormat = AutoRestartSendingMessageFormat; _setting.BackupDirPath = BackupDirPath; _setting.RestoreDirPath = RestoreDirPath; _setting.Save(); diff --git a/SavannahManager/Setup/Models/AdminPageModel.cs b/SavannahManager/Models/Setup/AdminPageModel.cs similarity index 84% rename from SavannahManager/Setup/Models/AdminPageModel.cs rename to SavannahManager/Models/Setup/AdminPageModel.cs index df45f8d1..5f9a6945 100644 --- a/SavannahManager/Setup/Models/AdminPageModel.cs +++ b/SavannahManager/Models/Setup/AdminPageModel.cs @@ -1,15 +1,8 @@ -using CommonStyleLib.File; -using Microsoft.Win32; -using SvManagerLibrary.SteamLibrary; -using System; -using System.Collections.Generic; +using System; using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using CommonStyleLib.ExMessageBox; +using CommonStyleLib.File; -namespace _7dtd_svmanager_fix_mvvm.Setup.Models +namespace _7dtd_svmanager_fix_mvvm.Models.Setup { public class AdminPageModel : PageModelBase { diff --git a/SavannahManager/Setup/CanChangedEventHandler.cs b/SavannahManager/Models/Setup/CanChangedEventHandler.cs similarity index 69% rename from SavannahManager/Setup/CanChangedEventHandler.cs rename to SavannahManager/Models/Setup/CanChangedEventHandler.cs index d5abd2c8..fd4d176b 100644 --- a/SavannahManager/Setup/CanChangedEventHandler.cs +++ b/SavannahManager/Models/Setup/CanChangedEventHandler.cs @@ -1,10 +1,6 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -namespace _7dtd_svmanager_fix_mvvm.Setup +namespace _7dtd_svmanager_fix_mvvm.Models.Setup { public class CanChangedEventArgs : EventArgs { diff --git a/SavannahManager/Setup/Models/ConfigPageModel.cs b/SavannahManager/Models/Setup/ConfigPageModel.cs similarity index 88% rename from SavannahManager/Setup/Models/ConfigPageModel.cs rename to SavannahManager/Models/Setup/ConfigPageModel.cs index c47e4c3b..ad573b9f 100644 --- a/SavannahManager/Setup/Models/ConfigPageModel.cs +++ b/SavannahManager/Models/Setup/ConfigPageModel.cs @@ -1,16 +1,8 @@ -using CommonStyleLib.File; +using CommonStyleLib.ExMessageBox; +using CommonStyleLib.File; using Microsoft.Win32; -using Prism.Mvvm; -using SvManagerLibrary.SteamLibrary; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using CommonStyleLib.ExMessageBox; -namespace _7dtd_svmanager_fix_mvvm.Setup.Models +namespace _7dtd_svmanager_fix_mvvm.Models.Setup { public class ConfigPageModel : PageModelBase { diff --git a/SavannahManager/Setup/Models/ExecutablePageModel.cs b/SavannahManager/Models/Setup/ExecutablePageModel.cs similarity index 94% rename from SavannahManager/Setup/Models/ExecutablePageModel.cs rename to SavannahManager/Models/Setup/ExecutablePageModel.cs index 5d4b8db6..1adbb603 100644 --- a/SavannahManager/Setup/Models/ExecutablePageModel.cs +++ b/SavannahManager/Models/Setup/ExecutablePageModel.cs @@ -1,12 +1,8 @@ using CommonStyleLib.ExMessageBox; using CommonStyleLib.File; using Microsoft.Win32; -using Prism.Mvvm; -using SvManagerLibrary.SteamLibrary; -using System; -using System.IO; -namespace _7dtd_svmanager_fix_mvvm.Setup.Models +namespace _7dtd_svmanager_fix_mvvm.Models.Setup { public class ExecutablePageModel : PageModelBase { diff --git a/SavannahManager/Setup/Models/FinishPageModel.cs b/SavannahManager/Models/Setup/FinishPageModel.cs similarity index 75% rename from SavannahManager/Setup/Models/FinishPageModel.cs rename to SavannahManager/Models/Setup/FinishPageModel.cs index 757df3a5..74a68d1d 100644 --- a/SavannahManager/Setup/Models/FinishPageModel.cs +++ b/SavannahManager/Models/Setup/FinishPageModel.cs @@ -1,11 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Prism.Mvvm; - -namespace _7dtd_svmanager_fix_mvvm.Setup.Models +namespace _7dtd_svmanager_fix_mvvm.Models.Setup { public class FinishPageModel : PageModelBase { diff --git a/SavannahManager/Setup/Models/FirstPageModel.cs b/SavannahManager/Models/Setup/FirstPageModel.cs similarity index 66% rename from SavannahManager/Setup/Models/FirstPageModel.cs rename to SavannahManager/Models/Setup/FirstPageModel.cs index c2340a92..1fed9714 100644 --- a/SavannahManager/Setup/Models/FirstPageModel.cs +++ b/SavannahManager/Models/Setup/FirstPageModel.cs @@ -1,18 +1,13 @@ using System; -using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Linq; -using System.Reactive.Linq; -using System.Text; -using System.Threading.Tasks; using _7dtd_svmanager_fix_mvvm.LangResources; -using _7dtd_svmanager_fix_mvvm.Models; -namespace _7dtd_svmanager_fix_mvvm.Setup.Models +namespace _7dtd_svmanager_fix_mvvm.Models.Setup { public class FirstPageModel : PageModelBase { + private readonly SettingLoader _settingLoader; private int _languagesSelectedIndex; public int LanguagesSelectedIndex @@ -28,20 +23,19 @@ public int LanguagesSelectedIndex public FirstPageModel(InitializeData initializeData) : base(initializeData) { - var settingLoader = SettingLoader.SettingInstance; - var cultureName = settingLoader.CultureName; + _settingLoader = initializeData.Setting; + var cultureName = _settingLoader.CultureName; LanguagesSelectedIndex = cultureName == ResourceService.Japanese ? 1 : 0; } public void ChangeCulture() { - var settingLoader = SettingLoader.SettingInstance; if (LanguagesSelectedIndex < 0 || LanguagesSelectedIndex >= Languages.Count) return; - settingLoader.CultureName = Languages[LanguagesSelectedIndex].Item2; - settingLoader.ApplyCulture(); + _settingLoader.CultureName = Languages[LanguagesSelectedIndex].Item2; + _settingLoader.ApplyCulture(); } } diff --git a/SavannahManager/Setup/Models/InitializeData.cs b/SavannahManager/Models/Setup/InitializeData.cs similarity index 77% rename from SavannahManager/Setup/Models/InitializeData.cs rename to SavannahManager/Models/Setup/InitializeData.cs index bd0dd556..30d8d218 100644 --- a/SavannahManager/Setup/Models/InitializeData.cs +++ b/SavannahManager/Models/Setup/InitializeData.cs @@ -1,6 +1,4 @@ -using _7dtd_svmanager_fix_mvvm.Models; - -namespace _7dtd_svmanager_fix_mvvm.Setup.Models +namespace _7dtd_svmanager_fix_mvvm.Models.Setup { public class InitializeData { diff --git a/SavannahManager/Setup/Models/PageModelBase.cs b/SavannahManager/Models/Setup/PageModelBase.cs similarity index 97% rename from SavannahManager/Setup/Models/PageModelBase.cs rename to SavannahManager/Models/Setup/PageModelBase.cs index a7678d01..8b7454d3 100644 --- a/SavannahManager/Setup/Models/PageModelBase.cs +++ b/SavannahManager/Models/Setup/PageModelBase.cs @@ -3,7 +3,7 @@ using Prism.Mvvm; using SvManagerLibrary.SteamLibrary; -namespace _7dtd_svmanager_fix_mvvm.Setup.Models +namespace _7dtd_svmanager_fix_mvvm.Models.Setup { public abstract class PageModelBase : BindableBase { diff --git a/SavannahManager/Settings/ShortcutKey.cs b/SavannahManager/Models/ShortcutKey.cs similarity index 96% rename from SavannahManager/Settings/ShortcutKey.cs rename to SavannahManager/Models/ShortcutKey.cs index 9bcdd1ab..8faf6f20 100644 --- a/SavannahManager/Settings/ShortcutKey.cs +++ b/SavannahManager/Models/ShortcutKey.cs @@ -1,15 +1,12 @@ -using _7dtd_svmanager_fix_mvvm.Models; -using CommonExtensionLib.Extensions; -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Windows.Input; -using CommonCoreLib.XMLWrapper; using SavannahXmlLib.XmlWrapper; using SavannahXmlLib.XmlWrapper.Nodes; using AttributeInfo = SavannahXmlLib.XmlWrapper.Nodes.AttributeInfo; -namespace _7dtd_svmanager_fix_mvvm.Settings +namespace _7dtd_svmanager_fix_mvvm.Models { public class ShortcutKey { diff --git a/SavannahManager/Models/Ssh/SshServerManager.cs b/SavannahManager/Models/Ssh/SshServerManager.cs new file mode 100644 index 00000000..d1945df5 --- /dev/null +++ b/SavannahManager/Models/Ssh/SshServerManager.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SvManagerLibrary.Ssh; + +namespace _7dtd_svmanager_fix_mvvm.Models.Ssh +{ + public class SshServerManager : IDisposable + { + + #region Fields + + private readonly SshServerConnector _sshServerConnector; + + #endregion + + #region Properties + + + + #endregion + + public SshServerManager(string hostAddress, int hostPort = 22) + { + _sshServerConnector = new SshServerConnector(hostAddress, hostPort); + _sshServerConnector.SshDataReceived.Subscribe(reader => Debug.WriteLine(reader.ReadToEnd())); + } + + public bool Connect(string user, string password) + { + _sshServerConnector.SetLoginInformation(user, password); + return _sshServerConnector.Connect(); + } + + public bool Connect(string user, string passPhrase, string keyPath) + { + _sshServerConnector.SetLoginInformation(user, passPhrase, keyPath); + return _sshServerConnector.Connect(); + } + + public void StartServer(string command) + { + _sshServerConnector.WriteLine($"nohup sh -c '( ( {command} &>/dev/null ) & )' > /dev/null"); + } + + #region IDisposable Members + public void Dispose() + { + _sshServerConnector?.Dispose(); + } + #endregion + } +} diff --git a/SavannahManager/Update/Models/Archive.cs b/SavannahManager/Models/Update/Archive.cs similarity index 93% rename from SavannahManager/Update/Models/Archive.cs rename to SavannahManager/Models/Update/Archive.cs index a95b6a7b..8a4f89b1 100644 --- a/SavannahManager/Update/Models/Archive.cs +++ b/SavannahManager/Models/Update/Archive.cs @@ -1,7 +1,7 @@ using System.IO; using System.IO.Compression; -namespace _7dtd_svmanager_fix_mvvm.Update.Models +namespace _7dtd_svmanager_fix_mvvm.Models.Update { public static class Zip { diff --git a/SavannahManager/Update/Models/CheckCleanFileModel.cs b/SavannahManager/Models/Update/CheckCleanFileModel.cs similarity index 94% rename from SavannahManager/Update/Models/CheckCleanFileModel.cs rename to SavannahManager/Models/Update/CheckCleanFileModel.cs index 65110301..c69607cd 100644 --- a/SavannahManager/Update/Models/CheckCleanFileModel.cs +++ b/SavannahManager/Models/Update/CheckCleanFileModel.cs @@ -1,16 +1,12 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.IO; using System.Linq; -using System.Text; -using System.Threading.Tasks; -using _7dtd_svmanager_fix_mvvm.Update.Models.Node; +using _7dtd_svmanager_fix_mvvm.Models.Update.Node; using CommonExtensionLib.Extensions; using CommonStyleLib.Models; -namespace _7dtd_svmanager_fix_mvvm.Update.Models +namespace _7dtd_svmanager_fix_mvvm.Models.Update { public class DirectoryTree { diff --git a/SavannahManager/Models/Update/LoadingModel.cs b/SavannahManager/Models/Update/LoadingModel.cs new file mode 100644 index 00000000..62d9911d --- /dev/null +++ b/SavannahManager/Models/Update/LoadingModel.cs @@ -0,0 +1,8 @@ +using CommonStyleLib.Models; + +namespace _7dtd_svmanager_fix_mvvm.Models.Update +{ + public class LoadingModel : ModelBase + { + } +} diff --git a/SavannahManager/Update/Models/Node/DirectoryNode.cs b/SavannahManager/Models/Update/Node/DirectoryNode.cs similarity index 97% rename from SavannahManager/Update/Models/Node/DirectoryNode.cs rename to SavannahManager/Models/Update/Node/DirectoryNode.cs index a513d7bc..23aab57c 100644 --- a/SavannahManager/Update/Models/Node/DirectoryNode.cs +++ b/SavannahManager/Models/Update/Node/DirectoryNode.cs @@ -3,7 +3,7 @@ using System.Linq; using Prism.Mvvm; -namespace _7dtd_svmanager_fix_mvvm.Update.Models.Node +namespace _7dtd_svmanager_fix_mvvm.Models.Update.Node { public class DirectoryNode : BindableBase { diff --git a/SavannahManager/Update/Models/UpdFormModel.cs b/SavannahManager/Models/Update/UpdFormModel.cs similarity index 97% rename from SavannahManager/Update/Models/UpdFormModel.cs rename to SavannahManager/Models/Update/UpdFormModel.cs index da7d739a..dd15be88 100644 --- a/SavannahManager/Update/Models/UpdFormModel.cs +++ b/SavannahManager/Models/Update/UpdFormModel.cs @@ -1,23 +1,20 @@ -using CommonStyleLib.ExMessageBox; -using CommonExtensionLib.Extensions; -using CommonStyleLib.Models; -using System; +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; -using _7dtd_svmanager_fix_mvvm.Update.Views; -using UpdateLib.Http; -using UpdateLib.Update; +using _7dtd_svmanager_fix_mvvm.Views.Update; +using CommonExtensionLib.Extensions; +using CommonStyleLib.ExMessageBox; +using CommonStyleLib.Models; using Path = System.IO.Path; -namespace _7dtd_svmanager_fix_mvvm.Update.Models +namespace _7dtd_svmanager_fix_mvvm.Models.Update { public class UpdFormModel : ModelBase { diff --git a/SavannahManager/Update/Models/UpdateManager.cs b/SavannahManager/Models/Update/UpdateManager.cs similarity index 97% rename from SavannahManager/Update/Models/UpdateManager.cs rename to SavannahManager/Models/Update/UpdateManager.cs index c54f97d4..5592f542 100644 --- a/SavannahManager/Update/Models/UpdateManager.cs +++ b/SavannahManager/Models/Update/UpdateManager.cs @@ -5,19 +5,15 @@ using System.IO; using System.Linq; using System.Net; -using System.Text; using System.Threading.Tasks; -using System.Windows.Media; -using _7dtd_svmanager_fix_mvvm.Update.Views; +using _7dtd_svmanager_fix_mvvm.Views.Update; using CommonExtensionLib.Extensions; using SavannahXmlLib.XmlWrapper; -using CommonStyleLib.File; using SavannahXmlLib.XmlWrapper.Nodes; using UpdateLib.Http; using UpdateLib.Update; -using Color = System.Drawing.Color; -namespace _7dtd_svmanager_fix_mvvm.Update.Models +namespace _7dtd_svmanager_fix_mvvm.Models.Update { public class UpdateManager { diff --git a/SavannahManager/Models/ForceShutdownerModel.cs b/SavannahManager/Models/WindowModel/ForceShutdownerModel.cs similarity index 94% rename from SavannahManager/Models/ForceShutdownerModel.cs rename to SavannahManager/Models/WindowModel/ForceShutdownerModel.cs index 91666b40..a562936d 100644 --- a/SavannahManager/Models/ForceShutdownerModel.cs +++ b/SavannahManager/Models/WindowModel/ForceShutdownerModel.cs @@ -8,7 +8,7 @@ using System.Text; using System.Threading.Tasks; -namespace _7dtd_svmanager_fix_mvvm.Models +namespace _7dtd_svmanager_fix_mvvm.Models.WindowModel { public class ProcessTab { @@ -28,7 +28,7 @@ public bool ProcessSelected private readonly List _processIds = new List(); private bool _processSelected; - + public void Refresh() { var ps = Process.GetProcessesByName("7DaysToDieServer"); @@ -55,7 +55,7 @@ public void KillProcess(int index) System.Threading.Thread.Sleep(500); } - catch (System.ArgumentException sae) + catch (ArgumentException sae) { ExMessageBoxBase.Show(sae.Message, LangResources.CommonResources.Error, ExMessageBoxBase.MessageType.Exclamation); return; diff --git a/SavannahManager/Models/IpAddressGetterModel.cs b/SavannahManager/Models/WindowModel/IpAddressGetterModel.cs similarity index 96% rename from SavannahManager/Models/IpAddressGetterModel.cs rename to SavannahManager/Models/WindowModel/IpAddressGetterModel.cs index 602b8d68..8b2fc2a3 100644 --- a/SavannahManager/Models/IpAddressGetterModel.cs +++ b/SavannahManager/Models/WindowModel/IpAddressGetterModel.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using System.Windows; -namespace _7dtd_svmanager_fix_mvvm.Models +namespace _7dtd_svmanager_fix_mvvm.Models.WindowModel { public class IpAddressGetterModel : ModelBase { diff --git a/SavannahManager/Models/MainWindowModel.cs b/SavannahManager/Models/WindowModel/MainWindowModel.cs similarity index 74% rename from SavannahManager/Models/MainWindowModel.cs rename to SavannahManager/Models/WindowModel/MainWindowModel.cs index c0ef8aaa..afdebe6d 100644 --- a/SavannahManager/Models/MainWindowModel.cs +++ b/SavannahManager/Models/WindowModel/MainWindowModel.cs @@ -11,8 +11,6 @@ using System.Text.RegularExpressions; using System.Windows.Input; using _7dtd_svmanager_fix_mvvm.LangResources; -using _7dtd_svmanager_fix_mvvm.Settings; -using _7dtd_svmanager_fix_mvvm.Update.Models; using _7dtd_svmanager_fix_mvvm.ViewModels; using _7dtd_svmanager_fix_mvvm.Models.Config; using CommonStyleLib.Models; @@ -23,10 +21,16 @@ using SvManagerLibrary.Player; using CommonExtensionLib.Extensions; using System.Linq; - -namespace _7dtd_svmanager_fix_mvvm.Models +using System.Windows.Forms; +using _7dtd_svmanager_fix_mvvm.Models.Interfaces; +using _7dtd_svmanager_fix_mvvm.Models.Ssh; +using _7dtd_svmanager_fix_mvvm.Models.Update; +using _7dtd_svmanager_fix_mvvm.Views.UserControls; +using Renci.SshNet.Common; + +namespace _7dtd_svmanager_fix_mvvm.Models.WindowModel { - public class MainWindowModel : ModelBase, IMainWindowTelnet, IDisposable + public class MainWindowModel : ModelBase, IMainWindowTelnet, IMainWindowServerStart, IRelease { #region AppendedLogTextEvent public class AppendedLogTextEventArgs @@ -84,13 +88,6 @@ public ObservableCollection UsersList set => SetProperty(ref _usersList, value); } - - private string _chatLogText; - public string ChatLogText - { - get => _chatLogText; - set => SetProperty(ref _chatLogText, value); - } private string _chatInputText; public string ChatInputText { @@ -105,6 +102,13 @@ public bool ConnectionPanelIsEnabled set => SetProperty(ref _connectionPanelIsEnabled, value); } + private string _autoRestartText = "AutoRestart Disabled"; + public string AutoRestartText + { + get => _autoRestartText; + set => SetProperty(ref _autoRestartText, value); + } + private bool _isBeta; public bool IsBeta @@ -121,7 +125,6 @@ public bool LocalMode { SetProperty(ref _localMode, value); ConnectionPanelIsEnabled = !value; - StartBtEnabled = value; } } private bool _localModeEnabled = true; @@ -186,6 +189,64 @@ public bool IsConsoleLogTextWrapping get => _isConsoleLogTextWrapping; set => SetProperty(ref _isConsoleLogTextWrapping, value); } + + + private string _sshAddressText = string.Empty; + private string _sshPortText = string.Empty; + private string _sshUserNameText = string.Empty; + private string _sshPasswordText = string.Empty; + private string _sshExeFileDirectoryText; + private string _sshConfigFileNameText; + private AuthMode _sshAuthMode; + private string _sshKeyPathText; + private string _sshPassPhraseText; + + public string SshAddressText + { + get => _sshAddressText; + set => SetProperty(ref _sshAddressText, value); + } + public string SshPortText + { + get => _sshPortText; + set => SetProperty(ref _sshPortText, value); + } + public string SshUserNameText + { + get => _sshUserNameText; + set => SetProperty(ref _sshUserNameText, value); + } + public string SshPasswordText + { + get => _sshPasswordText; + set => SetProperty(ref _sshPasswordText, value); + } + public string SshExeFileDirectoryText + { + get => _sshExeFileDirectoryText; + set => SetProperty(ref _sshExeFileDirectoryText, value); + } + public string SshConfigFileNameText + { + get => _sshConfigFileNameText; + set => SetProperty(ref _sshConfigFileNameText, value); + } + + public AuthMode SshAuthMode + { + get => _sshAuthMode; + set => SetProperty(ref _sshAuthMode, value); + } + public string SshKeyPathText + { + get => _sshKeyPathText; + set => SetProperty(ref _sshKeyPathText, value); + } + public string SshPassPhraseText + { + get => _sshPassPhraseText; + set => SetProperty(ref _sshPassPhraseText, value); + } #endregion #region Properties @@ -193,12 +254,15 @@ public bool IsConsoleLogTextWrapping //public IMessageBoxWindowService MessageBoxWindowService { get; set; } private bool _isConnected; - private bool IsConnected + public bool IsConnected { get => _isConnected && RowConnected; set => _isConnected = value; } private bool RowConnected => Telnet != null && Telnet.Connected; + + public bool AutoRestartEnabled { get; set; } + public bool IsFailed { get; private set; } public bool IsTelnetLoading { get; protected set; } public SettingLoader Setting { get; } @@ -217,16 +281,16 @@ private bool IsConnected private int _port; private string _password = string.Empty; - private readonly List _chatArray = new List(); - - private readonly Dictionary _playersDictionary = new Dictionary(); - private readonly List _connectedIds = new List(); + private readonly List _chatArray = new(); + private readonly CommandCollector _commandCollector = new(); + private readonly Dictionary _playersDictionary = new(); + private readonly List _connectedIds = new(); private bool _isServerForceStop; private bool _isLogGetter; - private LogStream _loggingStream; + private AutoRestart _autoRestart; #endregion #region Event @@ -245,7 +309,7 @@ private bool IsConnected public MainWindowModel() { - Setting = SettingLoader.SettingInstance; + Setting = new SettingLoader(ConstantValues.SettingFilePath); ShortcutKeyManager = new ShortcutKeyManager(ConstantValues.AppDirectoryPath + @"\KeyConfig.xml", ConstantValues.AppDirectoryPath + @"\Settings\KeyConfig\" + Resources.KeyConfigPath); } @@ -268,24 +332,61 @@ public void InitializeWindow() Left = (screenWidth - Width) / 2; } + public static (double left, double top) CalculateCenterTop(ModelBase model, double targetWidth, double targetHeight) + { + var returnLeft = model.Left + model.Width / 2 - targetWidth / 2; + var returnTop = model.Top + model.Height / 2 - targetHeight / 2; + + return (returnLeft, returnTop); + } + public void Initialize() { Address = Setting.Address; PortText = Setting.Port.ToString(); - Password = Setting.Password; IsConsoleLogTextWrapping = Setting.IsConsoleLogTextWrapping; ConsoleTextLength = Setting.ConsoleTextLength; _isLogGetter = Setting.IsLogGetter; LocalMode = Setting.LocalMode; - StartBtEnabled = LocalMode; IsBeta = Setting.IsBetaMode; + SshAddressText = Setting.SshAddress; + SshPortText = Setting.SshPort.ToString(); + SshUserNameText = Setting.SshUserName; + SshExeFileDirectoryText = Setting.SshExeFileDirectory; + SshConfigFileNameText = Setting.SshConfigFileName; + SshAuthMode = Setting.SshAuthMode.FromInt(); + SshKeyPathText = Setting.SshKeyPath; + Setting.ApplyCulture(); } + public bool InitializeEncryptionData(string password = null, string salt = null) + { + if (password != null) + { + salt = string.IsNullOrEmpty(salt) ? null : salt; + Setting.SetEncryptionPassword(password, salt); + try + { + Setting.LoadEncryptionData(); + } + catch + { + _errorOccurred.OnNext("Invalid password."); + return false; + } + } + + Password = Setting.Password; + SshPasswordText = Setting.SshPassword; + + return true; + } + public async Task CheckUpdate() { if (Setting.IsAutoUpdate) @@ -304,6 +405,16 @@ public void SettingsSave() Setting.Port = _port; Setting.Password = _password; Setting.IsConsoleLogTextWrapping = IsConsoleLogTextWrapping; + + Setting.SshAddress = _sshAddressText; + int.TryParse(_sshPortText, out var sshPort); + Setting.SshPort = sshPort; + Setting.SshUserName = _sshUserNameText; + Setting.SshPassword = _sshPasswordText; + Setting.SshExeFileDirectory = _sshExeFileDirectoryText; + Setting.SshConfigFileName = _sshConfigFileNameText; + Setting.SshAuthMode = _sshAuthMode.ToInt(); + Setting.SshKeyPath = _sshKeyPathText; } public void ChangeCulture(string cultureName) { @@ -345,15 +456,20 @@ private void FeedColorChange(SolidColorBrush color) - public void ServerStart() + public async Task ServerStart() { - if (!FileExistCheck()) return; + if (!LocalMode) + { + return await ServerStartWithSsh(); + } + + if (!FileExistCheck()) return false; var checkedValues = ConfigChecker.GetConfigInfo(ConfigFilePath); if (checkedValues.IsFailed) { _errorOccurred.OnNext(checkedValues.Message); - return; + return false; } const string localAddress = "127.0.0.1"; @@ -363,13 +479,13 @@ public void ServerStart() if (IsConnected) { _errorOccurred.OnNext(Resources.AlreadyConnected); - return; + return false; } var serverProcessManager = new ServerProcessManager(ExeFilePath, ConfigFilePath); void ProcessFailedAction(string message) => _errorOccurred.OnNext(message); if (!serverProcessManager.ProcessStart(ProcessFailedAction)) - return; + return false; StartBtEnabled = false; TelnetBtIsEnabled = false; @@ -378,8 +494,62 @@ public void ServerStart() BottomNewsLabel = Resources.UI_WaitingServer; SetBorderColor(CommonStyleLib.ConstantValues.ActivatedBorderColor2); + await ConnectTelnetForServerStart(localAddress, localPort, localPassword); + return true; + } + public async Task ServerStartWithSsh() + { + if (IsConnected) + { + _errorOccurred.OnNext(Resources.AlreadyConnected); + return false; + } + + StartBtEnabled = false; + TelnetBtIsEnabled = false; + LocalModeEnabled = false; + + BottomNewsLabel = Resources.UI_WaitingServer; + SetBorderColor(CommonStyleLib.ConstantValues.ActivatedBorderColor2); + + try + { + using var sshManager = new SshServerManager(SshAddressText); + if (SshAuthMode == AuthMode.Password) + sshManager.Connect(SshUserNameText, SshPasswordText); + else + sshManager.Connect(SshUserNameText, SshPassPhraseText, SshKeyPathText); + sshManager.StartServer($"cd {SshExeFileDirectoryText} " + + $"&& ./startserver.sh -configfile={SshConfigFileNameText}"); + await Task.Delay(500); + } + catch (SshAuthenticationException) + { + _errorOccurred.OnNext("failed to authenticate on ssh."); + + StartBtEnabled = true; + TelnetBtIsEnabled = true; + LocalModeEnabled = true; + BottomNewsLabel = Resources.UI_ReadyComplete; + } + catch (SshOperationTimeoutException) + { + _errorOccurred.OnNext("failed to connect ssh."); + + StartBtEnabled = true; + TelnetBtIsEnabled = true; + LocalModeEnabled = true; + BottomNewsLabel = Resources.UI_ReadyComplete; + } + + await ConnectTelnetForServerStart(Address, _port, Password); + return true; + } + + private async Task ConnectTelnetForServerStart(string address, int port, string password) + { Telnet = GenerateTelnetClient(this); - _ = Task.Factory.StartNew(() => + await Task.Factory.StartNew(() => { IsTelnetLoading = true; while (true) @@ -397,7 +567,7 @@ public void ServerStart() break; } - if (Telnet.Connect(localAddress, localPort)) + if (Telnet.Connect(address, port)) { IsConnected = true; IsTelnetLoading = false; @@ -410,9 +580,7 @@ public void ServerStart() SetBorderColor(CommonStyleLib.ConstantValues.ActivatedBorderColor); Telnet.Write(TelnetClient.Cr); - AppendConsoleLog(SocTelnetSend(localPassword)); - - MakeLogStream(); + AppendConsoleLog(SocTelnetSend(password)); break; } @@ -421,6 +589,7 @@ public void ServerStart() } }); } + public bool ServerStop() { if (IsTelnetLoading) @@ -444,15 +613,55 @@ public bool ServerStop() return false; } - private void MakeLogStream() + public bool StartAutoRestart() { - if (_isLogGetter) - _loggingStream = new LogStream(ConstantValues.LogDirectoryPath); + if (!IsBeta || !IsConnected) + { + var reason = ""; + if (!IsBeta) + reason = "because beta mod not enabled"; + else if (!IsConnected) + reason = "because telnet are not connected"; + + _errorOccurred.OnNext($"Cannot enable auto restart mode {reason}."); + return false; + } + + if (_autoRestart != null) + { + StopAutoRestart(); + } + + var isSsh = !LocalMode; + + _autoRestart = new AutoRestart(new MainWindowServerStart(this, isSsh)); + var newsLabel = BottomNewsLabel; + _autoRestart.TimeProgress.Subscribe((ts) => + { + BottomNewsLabel = $"{newsLabel}, AutoRestart: {ts:d\\.hh\\:mm\\:ss} remaining."; + Debug.WriteLine($"AutoRestart: {ts} remaining."); + }, () => BottomNewsLabel = newsLabel); + _autoRestart.FewRemaining.Subscribe(ts => + { + SocTelnetSend($"say \"{string.Format(Setting.AutoRestartSendingMessageFormat, ts.Seconds)}\""); + }); + _autoRestart.Start(); + + AutoRestartText = "AutoRestart Enabled"; + AutoRestartEnabled = true; + + return true; } - public void WriteLogStream(string log) + public void StopAutoRestart() { - _loggingStream?.WriteSteam(log); + if (_autoRestart == null || _autoRestart.IsRestarting) + return; + + _autoRestart?.Dispose(); + _autoRestart = null; + AutoRestartText = "AutoRestart Disabled"; + AutoRestartEnabled = false; } private bool FileExistCheck() @@ -489,11 +698,11 @@ private bool FileExistCheck() return true; } - public void TelnetConnectOrDisconnect() + public void SwitchTelnetConnection() { if (!IsConnected) { - _ = TelnetConnect().ContinueWith((task) => + _ = ConnectTelnet().ContinueWith((task) => { var innerExceptions = task.Exception?.InnerExceptions; if (innerExceptions != null) @@ -507,10 +716,10 @@ public void TelnetConnectOrDisconnect() } else { - TelnetDisconnect(); + DisconnectTelnet(); } } - private async Task TelnetConnect() + private async Task ConnectTelnet() { var localAddress = Address; var localPort = _port; @@ -542,13 +751,11 @@ private async Task TelnetConnect() Telnet = GenerateTelnetClient(this); var connected = await Task.Factory.StartNew(() => Telnet.Connect(localAddress, localPort)); TelnetBtIsEnabled = true; - if (LocalMode) - StartBtEnabled = true; + StartBtEnabled = true; IsFailed = false; if (connected) { - MakeLogStream(); TelnetBtLabel = Resources.UI_DisconnectFromTelnet; LocalModeEnabled = false; ConnectionPanelIsEnabled = false; @@ -572,7 +779,7 @@ private async Task TelnetConnect() TelnetFinish(); } } - private void TelnetDisconnect() + private void DisconnectTelnet() { try { @@ -594,6 +801,12 @@ private static TelnetClient GenerateTelnetClient(MainWindowModel model) { TelnetEventWaitTime = model.Setting.TelnetWaitTime }; + + if (model._isLogGetter) + { + telnet.EnableLogging(ConstantValues.LogDirectoryPath); + } + telnet.Started += (sender, args) => model._telnetStartedSubject?.OnNext(args); telnet.Finished += (sender, args) => model._telnetFinishedSubject?.OnNext(args); telnet.ReadEvent += (sender, args) => model._telnetReadSubject?.OnNext(args); @@ -607,20 +820,19 @@ public void TelnetFinish() ConnectionPanelIsEnabled = !LocalMode; LocalModeEnabled = true; - StartBtEnabled = LocalMode; - - _loggingStream?.Dispose(); - _loggingStream = null; + StartBtEnabled = true; + Telnet?.Dispose(); Telnet = null; } - public void AddChatText(string text) + public string GetChatText(string text) { _chatArray.AddMultiLine(text); var cData = _chatArray.LastOrDefault(); if (cData != null) - ChatLogText += $"{cData.Name}: {cData.Message}\r\n"; + return $"{cData.Name}: {cData.Message}\r\n"; + return string.Empty; } public void SendChat(string text, Action act) { @@ -772,8 +984,20 @@ public void SendCommand(string cmd) } #endif + _commandCollector.AddCommand(cmd); SocTelnetSendNrt(cmd); } + + public string GetPreviousCommand() + { + return _commandCollector.GetPreviousCommand(); + } + + public string GetNextCommand() + { + return _commandCollector.GetNextCommand(); + } + public bool CheckConnected() { if (IsConnected) @@ -899,7 +1123,7 @@ public void PushShortcutKey(Key key) if (ShortcutKeyManager.IsPushed("StartServerKey", Keyboard.Modifiers, key)) { if (!IsConnected) - ServerStart(); + _ = ServerStart(); } else if (ShortcutKeyManager.IsPushed("StopServerKey", Keyboard.Modifiers, key)) { @@ -908,13 +1132,13 @@ public void PushShortcutKey(Key key) else if (ShortcutKeyManager.IsPushed("ConTelnetKey", Keyboard.Modifiers, key)) { if (!IsConnected) - _ = TelnetConnect(); + _ = ConnectTelnet(); } else if (ShortcutKeyManager.IsPushed("DisConTelnetKey", Keyboard.Modifiers, key)) { if (IsConnected) { - TelnetDisconnect(); + DisconnectTelnet(); } } } @@ -931,6 +1155,27 @@ public void Dispose() GC.SuppressFinalize(this); } + public void Release() + { + if (Telnet != null) + { + lock (Telnet) + { + Telnet?.Dispose(); + Telnet = null; + } + } + + if (_autoRestart != null) + { + lock (_autoRestart) + { + _autoRestart.Dispose(); + _autoRestart = null; + } + } + } + // Protected implementation of Dispose pattern. protected virtual void Dispose(bool disposing) { @@ -939,15 +1184,7 @@ protected virtual void Dispose(bool disposing) if (disposing) { - if (Telnet != null) - { - lock (Telnet) - { - Telnet?.Dispose(); - Telnet = null; - } - } - + Release(); if (_telnetFinishedSubject != null) { @@ -979,6 +1216,7 @@ protected virtual void Dispose(bool disposing) } Setting.Save(); + Setting.Dispose(); } _disposed = true; diff --git a/SavannahManager/Models/PortCheckModel.cs b/SavannahManager/Models/WindowModel/PortCheckModel.cs similarity index 96% rename from SavannahManager/Models/PortCheckModel.cs rename to SavannahManager/Models/WindowModel/PortCheckModel.cs index 162c3b80..faed9236 100644 --- a/SavannahManager/Models/PortCheckModel.cs +++ b/SavannahManager/Models/WindowModel/PortCheckModel.cs @@ -5,7 +5,7 @@ using System.Text; using System.Threading.Tasks; -namespace _7dtd_svmanager_fix_mvvm.Models +namespace _7dtd_svmanager_fix_mvvm.Models.WindowModel { public class PortCheckModel : ModelBase { diff --git a/SavannahManager/Models/TelnetWaitTimeCalculatorModel.cs b/SavannahManager/Models/WindowModel/TelnetWaitTimeCalculatorModel.cs similarity index 97% rename from SavannahManager/Models/TelnetWaitTimeCalculatorModel.cs rename to SavannahManager/Models/WindowModel/TelnetWaitTimeCalculatorModel.cs index 3cef377a..5fbba24f 100644 --- a/SavannahManager/Models/TelnetWaitTimeCalculatorModel.cs +++ b/SavannahManager/Models/WindowModel/TelnetWaitTimeCalculatorModel.cs @@ -9,7 +9,7 @@ using CommonStyleLib.Models; using SvManagerLibrary.Telnet; -namespace _7dtd_svmanager_fix_mvvm.Models +namespace _7dtd_svmanager_fix_mvvm.Models.WindowModel { public class TelnetWaitTimeCalculatorModel : ModelBase { diff --git a/SavannahManager/Models/VersionInfoModel.cs b/SavannahManager/Models/WindowModel/VersionInfoModel.cs similarity index 71% rename from SavannahManager/Models/VersionInfoModel.cs rename to SavannahManager/Models/WindowModel/VersionInfoModel.cs index f5c11376..a5069a67 100644 --- a/SavannahManager/Models/VersionInfoModel.cs +++ b/SavannahManager/Models/WindowModel/VersionInfoModel.cs @@ -9,7 +9,7 @@ using System.Threading.Tasks; using System.Windows; -namespace _7dtd_svmanager_fix_mvvm.Models +namespace _7dtd_svmanager_fix_mvvm.Models.WindowModel { public class VersionInfoModel : ModelBase { @@ -21,11 +21,20 @@ public string Version set => SetProperty(ref _version, value); } + private string _copyrgiht; + + public string Copyright + { + get => _copyrgiht; + set => SetProperty(ref _copyrgiht, value); + } + public void SetVersion() { - //var asm = Assembly.GetExecutingAssembly(); + var asm = Assembly.GetExecutingAssembly(); //var ver = asm.GetName().Version; - + Copyright = Attribute.GetCustomAttribute(asm, typeof(AssemblyCopyrightAttribute)) + is AssemblyCopyrightAttribute copyrightAttribute ? copyrightAttribute.Copyright : string.Empty; Version = ConstantValues.Version; //ver.ToString() + "b"; } diff --git a/SavannahManager/Permissions/Views/GetSteamId.xaml.cs b/SavannahManager/Permissions/Views/GetSteamId.xaml.cs deleted file mode 100644 index b34adf29..00000000 --- a/SavannahManager/Permissions/Views/GetSteamId.xaml.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Shapes; - -namespace _7dtd_svmanager_fix_mvvm.Permissions.Views -{ - /// - /// GetSteamId.xaml の相互作用ロジック - /// - public partial class GetSteamId : Window - { - public GetSteamId() - { - InitializeComponent(); - } - } -} diff --git a/SavannahManager/Permissions/Views/PermissionEditor.xaml.cs b/SavannahManager/Permissions/Views/PermissionEditor.xaml.cs deleted file mode 100644 index 5d90f5b7..00000000 --- a/SavannahManager/Permissions/Views/PermissionEditor.xaml.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Shapes; -using _7dtd_svmanager_fix_mvvm.Permissions.Models; -using _7dtd_svmanager_fix_mvvm.Permissions.ViewModels; -using CommonStyleLib.Views; - -namespace _7dtd_svmanager_fix_mvvm.Permissions.Views -{ - /// - /// PermissionEditor.xaml の相互作用ロジック - /// - public partial class PermissionEditor : Window - { - public PermissionEditor() - { - InitializeComponent(); - } - } -} diff --git a/SavannahManager/Permissions/Views/UnBanDateSetting.xaml.cs b/SavannahManager/Permissions/Views/UnBanDateSetting.xaml.cs deleted file mode 100644 index 515d5372..00000000 --- a/SavannahManager/Permissions/Views/UnBanDateSetting.xaml.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Shapes; -using _7dtd_svmanager_fix_mvvm.Permissions.ViewModels; - -namespace _7dtd_svmanager_fix_mvvm.Permissions.Views -{ - /// - /// UnBanDateSetting.xaml の相互作用ロジック - /// - public partial class UnBanDateSetting : Window - { - public UnBanDateSetting() - { - InitializeComponent(); - } - - public void SetDisplayDate(DateTime dateTime) - { - DateCalendar.DisplayDate = dateTime; - } - } -} diff --git a/SavannahManager/PlayerController/Models/PlayerBaseModel.cs b/SavannahManager/PlayerController/Models/PlayerBaseModel.cs deleted file mode 100644 index ae4c630e..00000000 --- a/SavannahManager/PlayerController/Models/PlayerBaseModel.cs +++ /dev/null @@ -1,14 +0,0 @@ -using CommonStyleLib.Models; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace _7dtd_svmanager_fix_mvvm.PlayerController.Models -{ - public class PlayerBaseModel : ModelBase - { - - } -} diff --git a/SavannahManager/PlayerController/ViewModels/PlayerBaseViewModel.cs b/SavannahManager/PlayerController/ViewModels/PlayerBaseViewModel.cs deleted file mode 100644 index 54fee8a4..00000000 --- a/SavannahManager/PlayerController/ViewModels/PlayerBaseViewModel.cs +++ /dev/null @@ -1,36 +0,0 @@ -using _7dtd_svmanager_fix_mvvm.PlayerController.Models; -using CommonStyleLib.ViewModels; -using Reactive.Bindings; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Input; -using CommonStyleLib.Views; - -namespace _7dtd_svmanager_fix_mvvm.PlayerController.ViewModels -{ - public class PlayerBaseViewModel : ViewModelBase - { - public PlayerBaseViewModel(WindowService windowService, PlayerBaseModel model) : base(windowService, model) - { - _model = model; - } - - private readonly PlayerBaseModel _model; - private string _windowTitle; - - #region EventProperties - #endregion - - #region Properties - public string WindowTitle - { - get => _windowTitle; - set => SetProperty(ref _windowTitle, value); - } - #endregion - } -} diff --git a/SavannahManager/PlayerController/Views/Pages/AdminAdd.xaml.cs b/SavannahManager/PlayerController/Views/Pages/AdminAdd.xaml.cs deleted file mode 100644 index 2b84562f..00000000 --- a/SavannahManager/PlayerController/Views/Pages/AdminAdd.xaml.cs +++ /dev/null @@ -1,47 +0,0 @@ -using _7dtd_svmanager_fix_mvvm.Models; -using _7dtd_svmanager_fix_mvvm.PlayerController.Models.Pages; -using _7dtd_svmanager_fix_mvvm.PlayerController.ViewModels.Pages; -using CommonStyleLib.ExMessageBox; -using SvManagerLibrary.Telnet; -using System; -using System.Windows; -using System.Windows.Controls; - -namespace _7dtd_svmanager_fix_mvvm.PlayerController.Views.Pages -{ - /// - /// Add.xaml の相互作用ロジック - /// - public partial class AdminAdd : Page, IPlayerPage - { - #region EndedEvent - public event EventHandler Ended; - protected virtual void OnEnded(EventArgs e) - { - Ended?.Invoke(this, e); - } - #endregion - - #region Fiels - #endregion - - public AdminAdd(IMainWindowTelnet telnet, AddType.Type addType, string playerId = "") - { - InitializeComponent(); - - var model = new AdminAddModel(telnet, new AddType(addType)) - { - Name = playerId - }; - model.Ended += Model_Ended; - - var vm = new AdminAddViewModel(model); - DataContext = vm; - } - - private void Model_Ended(object sender, EventArgs e) - { - OnEnded(e); - } - } -} diff --git a/SavannahManager/PlayerController/Views/Pages/Ban.xaml.cs b/SavannahManager/PlayerController/Views/Pages/Ban.xaml.cs deleted file mode 100644 index 3a990fc0..00000000 --- a/SavannahManager/PlayerController/Views/Pages/Ban.xaml.cs +++ /dev/null @@ -1,43 +0,0 @@ -using _7dtd_svmanager_fix_mvvm.Models; -using _7dtd_svmanager_fix_mvvm.PlayerController.Models.Pages; -using _7dtd_svmanager_fix_mvvm.PlayerController.ViewModels.Pages; -using System; -using System.Collections.Generic; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; - -namespace _7dtd_svmanager_fix_mvvm.PlayerController.Views.Pages -{ - /// - /// Ban.xaml の相互作用ロジック - /// - public partial class Ban : Page, IPlayerPage - { - #region EndedEvent - public event EventHandler Ended; - protected virtual void OnEnded(EventArgs e) - { - Ended?.Invoke(this, e); - } - #endregion - - public Ban(IMainWindowTelnet telnet, string playerId = "") - { - InitializeComponent(); - - var model = new BanModel(telnet); - var vm = new BanViewModel(model); - DataContext = vm; - - model.Ended += Model_Ended; - - model.Name = playerId; - } - - private void Model_Ended(object sender, EventArgs e) - { - OnEnded(e); - } - } -} diff --git a/SavannahManager/PlayerController/Views/Pages/IPlayerPage.cs b/SavannahManager/PlayerController/Views/Pages/IPlayerPage.cs deleted file mode 100644 index aa1461c6..00000000 --- a/SavannahManager/PlayerController/Views/Pages/IPlayerPage.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; - -namespace _7dtd_svmanager_fix_mvvm.PlayerController.Views.Pages -{ - public interface IPlayerPage - { - event EventHandler Ended; - } -} diff --git a/SavannahManager/PlayerController/Views/Pages/Kick.xaml.cs b/SavannahManager/PlayerController/Views/Pages/Kick.xaml.cs deleted file mode 100644 index 6606caa0..00000000 --- a/SavannahManager/PlayerController/Views/Pages/Kick.xaml.cs +++ /dev/null @@ -1,42 +0,0 @@ -using _7dtd_svmanager_fix_mvvm.Models; -using _7dtd_svmanager_fix_mvvm.PlayerController.Models.Pages; -using _7dtd_svmanager_fix_mvvm.PlayerController.ViewModels.Pages; -using System; -using System.Windows; -using System.Windows.Controls; - -namespace _7dtd_svmanager_fix_mvvm.PlayerController.Views.Pages -{ - /// - /// Kick.xaml の相互作用ロジック - /// - public partial class Kick : Page, IPlayerPage - { - #region EndedEvent - public event EventHandler Ended; - protected virtual void OnEnded(EventArgs e) - { - Ended?.Invoke(this, e); - } - #endregion - - public Kick(IMainWindowTelnet telnet, string playerId = "") - { - InitializeComponent(); - - var model = new KickModel(telnet) - { - Name = playerId - }; - model.Ended += Model_Ended; - - var vm = new KickViewModel(model); - DataContext = vm; - } - - private void Model_Ended(object sender, EventArgs e) - { - OnEnded(e); - } - } -} diff --git a/SavannahManager/PlayerController/Views/PlayerInfoView.xaml.cs b/SavannahManager/PlayerController/Views/PlayerInfoView.xaml.cs deleted file mode 100644 index beb518ff..00000000 --- a/SavannahManager/PlayerController/Views/PlayerInfoView.xaml.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Shapes; - -namespace _7dtd_svmanager_fix_mvvm.PlayerController.Views -{ - /// - /// PlayerInfoView.xaml の相互作用ロジック - /// - public partial class PlayerInfoView : Window - { - public PlayerInfoView() - { - InitializeComponent(); - } - } -} diff --git a/SavannahManager/SavannahManager.csproj b/SavannahManager/SavannahManager.csproj index fd990f04..e920b6a1 100644 --- a/SavannahManager/SavannahManager.csproj +++ b/SavannahManager/SavannahManager.csproj @@ -1,4 +1,4 @@ - + WinExe @@ -9,16 +9,13 @@ SavannahManager2 Aona Suzutsuki Kimama Lab. - Copyright (C) Aona Suzutsuki 2014 - 2021 - 2.5.45.1 - 2.5.45.1 - 2.5.45.1 + Copyright (C) Aona Suzutsuki 2014 - 2022 + 2.5.46.2 + 2.5.46.2 + 2.5.46.2 - - - @@ -32,16 +29,17 @@ - - - + + + - - + + + @@ -70,7 +68,7 @@ Code App.xaml - + BackupSelector.xaml @@ -128,58 +126,55 @@ True True - + GetSteamId.xaml - + PermissionEditor.xaml - + UnBanDateSetting.xaml - + AdminAdd.xaml - + Ban.xaml - + Kick.xaml - + PlayerBase.xaml - + PlayerInfoView.xaml - + KeyConfig.xaml - + SettingWindow.xaml - + AdminPage.xaml - + ConfigPage.xaml - + ExecutablePage.xaml - + FinishPage.xaml - + FirstPage.xaml - - NavigationBase.xaml - - + Loading.xaml - + UpdForm.xaml @@ -264,55 +259,52 @@ - - Designer - - + Designer - + Designer - + Designer - + Designer - + Designer - + Designer - + Designer - + Designer - + Designer - + Designer - + Designer - + Designer - + Designer - + Designer - + Designer - + Designer @@ -328,10 +320,10 @@ $(DefaultXamlRuntime) Designer - + Designer - + Designer diff --git a/SavannahManager/Settings/ViewModels/SettingWindowViewModel.cs b/SavannahManager/Settings/ViewModels/SettingWindowViewModel.cs deleted file mode 100644 index 4ad98adb..00000000 --- a/SavannahManager/Settings/ViewModels/SettingWindowViewModel.cs +++ /dev/null @@ -1,127 +0,0 @@ -using _7dtd_svmanager_fix_mvvm.Settings.Models; -using CommonStyleLib.ViewModels; -using Prism.Commands; -using Reactive.Bindings; -using Reactive.Bindings.Extensions; -using System.Windows; -using System.Windows.Input; -using _7dtd_svmanager_fix_mvvm.Settings.Views; -using CommonStyleLib.ExMessageBox; -using CommonStyleLib.ExMessageBox.Views; -using CommonStyleLib.Views; - -namespace _7dtd_svmanager_fix_mvvm.Settings.ViewModels -{ - public class SettingWindowViewModel : ViewModelBase - { - private readonly SettingModel _model; - public SettingWindowViewModel(WindowService windowService, SettingModel model) : base(windowService, model) - { - _model = model; - - #region Event Initialize - GetSvFilePathCommand = new DelegateCommand(GetSvFilePathBt_Click); - GetConfFilePathCommand = new DelegateCommand(GetConfFilePathBt_Click); - GetAdminFilePathCommand = new DelegateCommand(GetAdminFilePathBt_Click); - HelpHyperlinkCommand = new DelegateCommand(OpenHelpHyperlink); - - KeyEditCommand = new DelegateCommand(KeyEditBt_Click); - - GetBackupDirCommand = new DelegateCommand(GetBackupDirBt_Click); - GetRestoreDirCommand = new DelegateCommand(GetRestoreDirBt_Click); - - SaveBtCommand = new DelegateCommand(SaveBt_Click); - #endregion - - #region Property Initialize - ExeFilePathText = model.ToReactivePropertyAsSynchronized(m => m.ExeFilePath); - ConfigFilePathText = model.ToReactivePropertyAsSynchronized(m => m.ConfigFilePath); - AdminFilePathText = model.ToReactivePropertyAsSynchronized(m => m.AdminFilePath); - - IsLogGetterChecked = model.ToReactivePropertyAsSynchronized(m => m.IsLogGetter); - ConsoleLengthText = model.ToReactivePropertyAsSynchronized(m => m.ConsoleLengthText); - - TelnetWaitTime = model.ToReactivePropertyAsSynchronized(m => m.TelnetWaitTime); - - IsBetaModeChecked = model.ToReactivePropertyAsSynchronized(m => m.IsBetaMode); - IsAutoUpdateChecked = model.ToReactivePropertyAsSynchronized(m => m.IsAutoUpdate); - BackupDirPath = model.ToReactivePropertyAsSynchronized(m => m.BackupDirPath); - RestoreDirPath = model.ToReactivePropertyAsSynchronized(m => m.RestoreDirPath); - #endregion - } - - #region Properties - public ReactiveProperty ExeFilePathText { get; set; } - public ReactiveProperty ConfigFilePathText { get; set; } - public ReactiveProperty AdminFilePathText { get; set; } - - public ReactiveProperty IsLogGetterChecked { get; set; } - public ReactiveProperty ConsoleLengthText { get; set; } - - public ReactiveProperty TelnetWaitTime { get; set; } - - public ReactiveProperty IsBetaModeChecked { get; set; } - public ReactiveProperty IsAutoUpdateChecked { get; set; } - public ReactiveProperty BackupDirPath { get; set; } - public ReactiveProperty RestoreDirPath { get; set; } - #endregion - - #region Event Properties - public ICommand GetSvFilePathCommand { get; set; } - public ICommand GetConfFilePathCommand { get; set; } - public ICommand GetAdminFilePathCommand { get; set; } - - public ICommand HelpHyperlinkCommand { get; set; } - - public ICommand KeyEditCommand { get; set; } - - public ICommand GetBackupDirCommand { get; set; } - public ICommand GetRestoreDirCommand { get; set; } - - public ICommand SaveBtCommand { get; set; } - #endregion - - #region Event Methods - private void GetSvFilePathBt_Click() - { - _model.GetServerFilePath(); - } - private void GetConfFilePathBt_Click() - { - _model.GetConfFilePath(); - } - private void GetAdminFilePathBt_Click() - { - _model.GetAdminFilePath(); - } - - private void OpenHelpHyperlink(string text) - { - ExMessageBoxBase.Show(text, "Help", ExMessageBoxBase.MessageType.Question); - } - - private void KeyEditBt_Click() - { - var shortcutManager = _model.ShortcutKeyManager; - var keyConfModel = new KeyConfigModel(shortcutManager); - var vm = new KeyConfigViewModel(new WindowService(), keyConfModel); - WindowManageService.ShowDialog(vm); - } - - private void GetBackupDirBt_Click() - { - _model.GetBackupDirPath(); - } - private void GetRestoreDirBt_Click() - { - _model.GetRestoreDirPath(); - } - - private void SaveBt_Click() - { - _model.Save(); - WindowManageService.Close(); - } - #endregion - } -} diff --git a/SavannahManager/Settings/Views/SettingWindow.xaml.cs b/SavannahManager/Settings/Views/SettingWindow.xaml.cs deleted file mode 100644 index 029f613c..00000000 --- a/SavannahManager/Settings/Views/SettingWindow.xaml.cs +++ /dev/null @@ -1,30 +0,0 @@ -using _7dtd_svmanager_fix_mvvm.Models; -using _7dtd_svmanager_fix_mvvm.Settings.Models; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Shapes; -using CommonStyleLib.Views; - -namespace _7dtd_svmanager_fix_mvvm.Settings.Views -{ - /// - /// SettingWindow.xaml の相互作用ロジック - /// - public partial class SettingWindow : Window - { - public SettingWindow() - { - InitializeComponent(); - } - } -} diff --git a/SavannahManager/Setup/ViewModels/NavigationBaseViewModel.cs b/SavannahManager/Setup/ViewModels/NavigationBaseViewModel.cs deleted file mode 100644 index e7637e11..00000000 --- a/SavannahManager/Setup/ViewModels/NavigationBaseViewModel.cs +++ /dev/null @@ -1,276 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Input; -using System.Windows.Navigation; -using CommonExtensionLib.Extensions; -using CommonStyleLib.ExMessageBox; -using CommonStyleLib.Models; -using CommonStyleLib.ViewModels; -using CommonStyleLib.Views; -using Prism.Commands; -using Prism.Mvvm; -using Reactive.Bindings; -using Reactive.Bindings.Extensions; -using CommonNavigationControlLib.Navigation.Views; - -namespace _7dtd_svmanager_fix_mvvm.Setup.ViewModels -{ - public class NavigationBindableValue : BindableBase - { - - private bool _canGoNext; - private bool _canGoBack; - - private Visibility _backBtVisibility; - private Visibility _nextBtVisibility; - private Visibility _closeBtVisibility; - private Visibility _cancelBtVisibility; - - private string _nextBtContent; - private string _windowTitle; - - public string WindowTitle - { - get => _windowTitle; - set => SetProperty(ref _windowTitle, value); - } - - public string NextBtContent - { - get => _nextBtContent; - set => SetProperty(ref _nextBtContent, value); - } - - public bool CanGoNext - { - get => _canGoNext; - set => SetProperty(ref _canGoNext, value); - } - - public bool CanGoBack - { - get => _canGoBack; - set => SetProperty(ref _canGoBack, value); - } - - public Visibility BackBtVisibility - { - get => _backBtVisibility; - set => SetProperty(ref _backBtVisibility, value); - } - - public Visibility NextBtVisibility - { - get => _nextBtVisibility; - set => SetProperty(ref _nextBtVisibility, value); - } - - public Visibility CloseBtVisibility - { - get => _closeBtVisibility; - set => SetProperty(ref _closeBtVisibility, value); - } - - public Visibility CancelBtVisibility - { - get => _cancelBtVisibility; - set => SetProperty(ref _cancelBtVisibility, value); - } - - public Action CloseAction { get; set; } - - public virtual void InitDefaultValue() - { - NextBtContent = LangResources.CommonResources.UI_Next; - CanGoNext = true; - BackBtVisibility = Visibility.Visible; - NextBtVisibility = Visibility.Visible; - CancelBtVisibility = Visibility.Visible; - CloseBtVisibility = Visibility.Collapsed; - } - } - - public class NavigationWindowService : WindowService where T : new() - { - private readonly Dictionary> _cacheDictionary = new Dictionary>(); - - public IList> Pages { get; set; } - public ITransitionNavigationService Navigation { get; set; } - - public NavigationBindableValue NavigationValue { get; set; } - - public T Share { get; set; } = new T(); - - public NavigationWindowService() - { - NavigationValue = new NavigationBindableValue(); - NavigationValue.InitDefaultValue(); - } - - public void Initialize() - { - Navigation.GetItemFunc = i => - { - var type = Navigation.ItemSource[i] as Type; - if (type == null || Pages.Count - 1 < i) - return (new object(), false); - - var page = _cacheDictionary.GetCallback(type, () => new Tuple(Activator.CreateInstance(type, this), Pages[i].Item2)); - if (!_cacheDictionary.ContainsKey(type)) - _cacheDictionary.Add(type, page); - return (page.Item1, page.Item2); - }; - Navigation.HorizontalOffsetAction = () => Owner.Width + 10; - Navigation.ItemSource = (from x in Pages select x.Item1).ToList(); - - var page = Navigation.ContentValue; - RefreshValues(page); - - NavigationValue.CanGoBack = Navigation.CanGoBack; - NavigationValue.CanGoNext = Navigation.CanGoNext; - } - - public void GoNext() - { - Navigation.NavigateNext(); - - NavigationValue.CanGoNext = Navigation.CanGoNext; - NavigationValue.CanGoBack = Navigation.CanGoBack; - - var page = Navigation.ContentValue; - RefreshValues(page); - DoLoaded(page); - } - - public void GoBack() - { - Navigation.NavigateBack(); - - NavigationValue.CanGoNext = Navigation.CanGoNext; - NavigationValue.CanGoBack = Navigation.CanGoBack; - - var page = Navigation.ContentValue; - RefreshValues(page); - DoLoaded(page); - } - - private void DoLoaded(object page) - { - if (page is UserControl cPage) - { - var refresh = cPage.DataContext as NavigationPageViewModelBase; - refresh?.LoadedCommand?.Execute(null); - } - } - - private static void RefreshValues(object page) - { - if (page is UserControl cPage) - { - var refresh = cPage.DataContext as INavigationRefresh; - refresh?.RefreshValues(); - } - } - } - - public class NavigationBaseViewModel : ViewModelBase where T : new() - { - public NavigationBaseViewModel(NavigationWindowService service, ModelBase model) : base(service, model) - { - _navigationService = service; - - WindowTitle = service.NavigationValue.ObserveProperty(m => m.WindowTitle).ToReactiveProperty(); - NextBtContent = service.NavigationValue.ObserveProperty(m => m.NextBtContent).ToReactiveProperty(); - BackBtIsEnabled = service.NavigationValue.ObserveProperty(m => m.CanGoBack).ToReactiveProperty(); - NextBtIsEnabled = service.NavigationValue.ObserveProperty(m => m.CanGoNext).ToReactiveProperty(); - BackBtVisibility = service.NavigationValue.ObserveProperty(m => m.BackBtVisibility).ToReactiveProperty(); - NextBtVisibility = service.NavigationValue.ObserveProperty(m => m.NextBtVisibility).ToReactiveProperty(); - CloseBtVisibility = service.NavigationValue.ObserveProperty(m => m.CloseBtVisibility).ToReactiveProperty(); - CancelBtVisibility = service.NavigationValue.ObserveProperty(m => m.CancelBtVisibility).ToReactiveProperty(); - - BackBtCommand = new DelegateCommand(GoBack); - NextBtCommand = new DelegateCommand(GoNext); - CloseBtCommand = new DelegateCommand(Close); - CancelCommand = new DelegateCommand(Cancel); - } - - #region Fields - - private readonly NavigationWindowService _navigationService; - - #endregion - - #region Properties - - public ReactiveProperty WindowTitle { get; set; } - - public ReactiveProperty NextBtContent { get; set; } - - public ReactiveProperty BackBtIsEnabled { get; set; } - public ReactiveProperty NextBtIsEnabled { get; set; } - public ReactiveProperty BackBtVisibility { get; set; } - public ReactiveProperty NextBtVisibility { get; set; } - public ReactiveProperty CloseBtVisibility { get; set; } - public ReactiveProperty CancelBtVisibility { get; set; } - - public Action CloseAction { get; set; } - - #endregion - - #region Event Properties - - public ICommand BackBtCommand { get; set; } - public ICommand NextBtCommand { get; set; } - public ICommand CloseBtCommand { get; set; } - public ICommand CancelCommand { get; set; } - - #endregion - - - #region Event Methods - - public void GoBack() - { - _navigationService.GoBack(); - } - - public void GoNext() - { - _navigationService.GoNext(); - } - - public void Close() - { - _navigationService?.NavigationValue?.CloseAction?.Invoke(); - base.MainWindowCloseBt_Click(); - } - - public void Cancel() - { - base.MainWindowCloseBt_Click(); - } - - - protected override void MainWindowCloseBt_Click() - { - CloseAction?.Invoke(_navigationService.Share); - - base.MainWindowCloseBt_Click(); - } - - protected override void MainWindow_Closing() - { - var share = _navigationService.Share; - if (share is IDisposable cPage) - cPage.Dispose(); - } - - #endregion - } -} diff --git a/SavannahManager/Setup/ViewModels/NavigationPageViewModelBase.cs b/SavannahManager/Setup/ViewModels/NavigationPageViewModelBase.cs deleted file mode 100644 index 4bfd2f29..00000000 --- a/SavannahManager/Setup/ViewModels/NavigationPageViewModelBase.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Input; -using Prism.Commands; -using Prism.Mvvm; - -namespace _7dtd_svmanager_fix_mvvm.Setup.ViewModels -{ - public class NavigationPageViewModel : NavigationPageViewModelBase - { - public NavigationPageViewModel(NavigationBindableValue bindableValue) : base(bindableValue) - { - } - } - - public abstract class NavigationPageViewModelBase : BindableBase, INavigationRefresh - { - protected NavigationPageViewModelBase(NavigationBindableValue bindableValue) - { - BindableValue = bindableValue; - - LoadedCommand = new DelegateCommand(Loaded); - } - - protected NavigationBindableValue BindableValue { get; } - - public ICommand LoadedCommand { get; set; } - - public virtual void Loaded() - { - - } - - public virtual void RefreshValues() - { - BindableValue.InitDefaultValue(); - } - } -} diff --git a/SavannahManager/Setup/Views/FinishPage.xaml.cs b/SavannahManager/Setup/Views/FinishPage.xaml.cs deleted file mode 100644 index 430a77d6..00000000 --- a/SavannahManager/Setup/Views/FinishPage.xaml.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; -using _7dtd_svmanager_fix_mvvm.Models; -using _7dtd_svmanager_fix_mvvm.Setup.Models; -using _7dtd_svmanager_fix_mvvm.Setup.ViewModels; - -namespace _7dtd_svmanager_fix_mvvm.Setup.Views -{ - /// - /// FinishPage.xaml の相互作用ロジック - /// - public partial class FinishPage : UserControl - { - public FinishPage(NavigationWindowService service) - { - InitializeComponent(); - - DataContext = new FinishPageViewModel(service, new FinishPageModel(service.Share)); - } - } -} diff --git a/SavannahManager/Setup/Views/FirstPage.xaml.cs b/SavannahManager/Setup/Views/FirstPage.xaml.cs deleted file mode 100644 index 543d5c91..00000000 --- a/SavannahManager/Setup/Views/FirstPage.xaml.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; -using _7dtd_svmanager_fix_mvvm.Setup.Models; -using _7dtd_svmanager_fix_mvvm.Setup.ViewModels; - -namespace _7dtd_svmanager_fix_mvvm.Setup.Views -{ - /// - /// FirstPage.xaml の相互作用ロジック - /// - public partial class FirstPage : UserControl - { - public FirstPage(NavigationWindowService service) - { - InitializeComponent(); - - DataContext = new FirstPageViewModel(service, new FirstPageModel(service.Share)); - } - } -} diff --git a/SavannahManager/Setup/Views/NavigationBase.xaml b/SavannahManager/Setup/Views/NavigationBase.xaml deleted file mode 100644 index fc8ec2f1..00000000 --- a/SavannahManager/Setup/Views/NavigationBase.xaml +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + public partial class UnBanDateSetting : Window + { + public UnBanDateSetting() + { + InitializeComponent(); + } + + public void SetDisplayDate(DateTime dateTime) + { + DateCalendar.DisplayDate = dateTime; + } + } +} diff --git a/SavannahManager/PlayerController/Views/Pages/AddType.cs b/SavannahManager/Views/PlayerController/Pages/AddType.cs similarity index 77% rename from SavannahManager/PlayerController/Views/Pages/AddType.cs rename to SavannahManager/Views/PlayerController/Pages/AddType.cs index dd43037b..b27fd27d 100644 --- a/SavannahManager/PlayerController/Views/Pages/AddType.cs +++ b/SavannahManager/Views/PlayerController/Pages/AddType.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace _7dtd_svmanager_fix_mvvm.PlayerController.Views.Pages +namespace _7dtd_svmanager_fix_mvvm.Views.PlayerController.Pages { public class AddType { diff --git a/SavannahManager/PlayerController/Views/Pages/AdminAdd.xaml b/SavannahManager/Views/PlayerController/Pages/AdminAdd.xaml similarity index 97% rename from SavannahManager/PlayerController/Views/Pages/AdminAdd.xaml rename to SavannahManager/Views/PlayerController/Pages/AdminAdd.xaml index 6a7b3bef..3208569e 100644 --- a/SavannahManager/PlayerController/Views/Pages/AdminAdd.xaml +++ b/SavannahManager/Views/PlayerController/Pages/AdminAdd.xaml @@ -1,4 +1,4 @@ - + /// Add.xaml の相互作用ロジック + /// + public partial class AdminAdd : Page, IPlayerPage + { + #region EndedEvent + public event EventHandler Ended; + protected virtual void OnEnded(EventArgs e) + { + Ended?.Invoke(this, e); + } + #endregion + + #region Fiels + #endregion + + public AdminAdd(AdminAddViewModel vm, AdminAddModel adminModel) + { + InitializeComponent(); + + adminModel.Ended += Model_Ended; + + DataContext = vm; + } + + private void Model_Ended(object sender, EventArgs e) + { + OnEnded(e); + } + } +} diff --git a/SavannahManager/PlayerController/Views/Pages/Ban.xaml b/SavannahManager/Views/PlayerController/Pages/Ban.xaml similarity index 97% rename from SavannahManager/PlayerController/Views/Pages/Ban.xaml rename to SavannahManager/Views/PlayerController/Pages/Ban.xaml index 6e0d3af9..5727eeb3 100644 --- a/SavannahManager/PlayerController/Views/Pages/Ban.xaml +++ b/SavannahManager/Views/PlayerController/Pages/Ban.xaml @@ -1,4 +1,4 @@ - + /// Ban.xaml の相互作用ロジック + /// + public partial class Ban : Page, IPlayerPage + { + #region EndedEvent + public event EventHandler Ended; + protected virtual void OnEnded(EventArgs e) + { + Ended?.Invoke(this, e); + } + #endregion + + public Ban(BanViewModel banViewModel, BanModel banModel) + { + InitializeComponent(); + + banModel.Ended += Model_Ended; + DataContext = banViewModel; + } + + private void Model_Ended(object sender, EventArgs e) + { + OnEnded(e); + } + } +} diff --git a/SavannahManager/Views/PlayerController/Pages/IPlayerPage.cs b/SavannahManager/Views/PlayerController/Pages/IPlayerPage.cs new file mode 100644 index 00000000..33ee480b --- /dev/null +++ b/SavannahManager/Views/PlayerController/Pages/IPlayerPage.cs @@ -0,0 +1,9 @@ +using System; + +namespace _7dtd_svmanager_fix_mvvm.Views.PlayerController.Pages +{ + public interface IPlayerPage + { + event EventHandler Ended; + } +} diff --git a/SavannahManager/PlayerController/Views/Pages/Kick.xaml b/SavannahManager/Views/PlayerController/Pages/Kick.xaml similarity index 97% rename from SavannahManager/PlayerController/Views/Pages/Kick.xaml rename to SavannahManager/Views/PlayerController/Pages/Kick.xaml index d5a9e4c2..8be525ec 100644 --- a/SavannahManager/PlayerController/Views/Pages/Kick.xaml +++ b/SavannahManager/Views/PlayerController/Pages/Kick.xaml @@ -1,4 +1,4 @@ - + /// Kick.xaml の相互作用ロジック + /// + public partial class Kick : Page, IPlayerPage + { + #region EndedEvent + public event EventHandler Ended; + protected virtual void OnEnded(EventArgs e) + { + Ended?.Invoke(this, e); + } + #endregion + + public Kick(KickViewModel kickViewModel, KickModel kickModel) + { + InitializeComponent(); + + kickModel.Ended += Model_Ended; + DataContext = kickViewModel; + } + + private void Model_Ended(object sender, EventArgs e) + { + OnEnded(e); + } + } +} diff --git a/SavannahManager/PlayerController/Views/PlayerBase.xaml b/SavannahManager/Views/PlayerController/PlayerBase.xaml similarity index 86% rename from SavannahManager/PlayerController/Views/PlayerBase.xaml rename to SavannahManager/Views/PlayerController/PlayerBase.xaml index 238139b9..93c9b80c 100644 --- a/SavannahManager/PlayerController/Views/PlayerBase.xaml +++ b/SavannahManager/Views/PlayerController/PlayerBase.xaml @@ -1,4 +1,4 @@ - + Title="Settings" Height="200" Width="450" ResizeMode="CanMinimize" + BorderBrush="{Binding AroundBorderColor.Value}" + Opacity="{Binding AroundBorderOpacity.Value}" + Style="{DynamicResource WindowStyle}"> + + + @@ -21,15 +27,10 @@ - - - - + @@ -37,7 +38,6 @@ - diff --git a/SavannahManager/PlayerController/Views/PlayerBase.xaml.cs b/SavannahManager/Views/PlayerController/PlayerBase.xaml.cs similarity index 55% rename from SavannahManager/PlayerController/Views/PlayerBase.xaml.cs rename to SavannahManager/Views/PlayerController/PlayerBase.xaml.cs index 98c06bb2..8373cbf5 100644 --- a/SavannahManager/PlayerController/Views/PlayerBase.xaml.cs +++ b/SavannahManager/Views/PlayerController/PlayerBase.xaml.cs @@ -1,21 +1,8 @@ -using _7dtd_svmanager_fix_mvvm.PlayerController.Views.Pages; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System; using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; -using CommonStyleLib.Views; +using _7dtd_svmanager_fix_mvvm.Views.PlayerController.Pages; -namespace _7dtd_svmanager_fix_mvvm.PlayerController.Views +namespace _7dtd_svmanager_fix_mvvm.Views.PlayerController { /// /// PlayerBase.xaml の相互作用ロジック diff --git a/SavannahManager/PlayerController/Views/PlayerInfoView.xaml b/SavannahManager/Views/PlayerController/PlayerInfoView.xaml similarity index 89% rename from SavannahManager/PlayerController/Views/PlayerInfoView.xaml rename to SavannahManager/Views/PlayerController/PlayerInfoView.xaml index c60153c8..6762a39f 100644 --- a/SavannahManager/PlayerController/Views/PlayerInfoView.xaml +++ b/SavannahManager/Views/PlayerController/PlayerInfoView.xaml @@ -1,4 +1,4 @@ - + Title="PlayerInfoView" Height="400" Width="650" + BorderBrush="{Binding AroundBorderColor.Value}" + Opacity="{Binding AroundBorderOpacity.Value}" + Style="{DynamicResource WindowStyle}"> @@ -23,15 +26,10 @@ - - - - + @@ -40,7 +38,6 @@ - diff --git a/SavannahManager/Views/PlayerController/PlayerInfoView.xaml.cs b/SavannahManager/Views/PlayerController/PlayerInfoView.xaml.cs new file mode 100644 index 00000000..76a399ab --- /dev/null +++ b/SavannahManager/Views/PlayerController/PlayerInfoView.xaml.cs @@ -0,0 +1,15 @@ +using System.Windows; + +namespace _7dtd_svmanager_fix_mvvm.Views.PlayerController +{ + /// + /// PlayerInfoView.xaml の相互作用ロジック + /// + public partial class PlayerInfoView : Window + { + public PlayerInfoView() + { + InitializeComponent(); + } + } +} diff --git a/SavannahManager/Views/PortCheck.xaml b/SavannahManager/Views/PortCheck.xaml index 6922df36..ae0839f2 100644 --- a/SavannahManager/Views/PortCheck.xaml +++ b/SavannahManager/Views/PortCheck.xaml @@ -9,17 +9,33 @@ Icon="pack://application:,,,/CommonStyleLib;component/Resources/1.ico" mc:Ignorable="d" d:DataContext="{d:DesignInstance viewModels:PortCheckViewModel}" - Title="Port Checker" Height="250" Width="400"> + Title="Port Checker" Height="250" Width="400" + BorderBrush="{Binding AroundBorderColor.Value}" + Opacity="{Binding AroundBorderOpacity.Value}" + Style="{DynamicResource WindowStyle}"> - - - + + + + + + + + + + + + + + + + + + @@ -27,7 +43,6 @@ - diff --git a/SavannahManager/Views/Settings/InputWindow.xaml b/SavannahManager/Views/Settings/InputWindow.xaml new file mode 100644 index 00000000..4c60af1f --- /dev/null +++ b/SavannahManager/Views/Settings/InputWindow.xaml @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public partial class FirstPage : UserControl + { + public FirstPage(NavigationWindowService service) + { + InitializeComponent(); + + DataContext = new FirstPageViewModel(service, new FirstPageModel(service.Share)); + } + } +} diff --git a/SavannahManager/Views/TelnetWaitTimeCalculator.xaml b/SavannahManager/Views/TelnetWaitTimeCalculator.xaml index 293eb788..229828fc 100644 --- a/SavannahManager/Views/TelnetWaitTimeCalculator.xaml +++ b/SavannahManager/Views/TelnetWaitTimeCalculator.xaml @@ -10,7 +10,11 @@ xmlns:lang="clr-namespace:_7dtd_svmanager_fix_mvvm.LangResources" mc:Ignorable="d" d:DataContext="{d:DesignInstance viewModels:TelnetWaitTimeCalculatorViewModel}" - Title="TelnetWaitTimeCalculator" Height="250" Width="400"> + Title="TelnetWaitTimeCalculator" Height="250" Width="400" + BorderBrush="{Binding AroundBorderColor.Value}" + Opacity="{Binding AroundBorderOpacity.Value}" + Style="{DynamicResource WindowStyle}"> + @@ -26,15 +30,10 @@ - - - - + @@ -42,7 +41,6 @@ - (FlowDocument)GetValue(DocumentProperty); set => SetValue(DocumentProperty, value); } + + public bool WordWrapping + { + get => (bool)GetValue(WordWrappingProperty); + set => SetValue(WordWrappingProperty, value); + } #endregion // 公開プロパティ #region イベントハンドラ - private static void OnRichTextItemsChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) + private static void DocumentChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) + { + SetDocument(sender, e.NewValue); + } + + private static void WordWrappingChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs e) { - if (sender is RichTextBox control) + if (sender is BindableRichTextBox bindableRichTextBox) { - control.Document = e.NewValue as FlowDocument; + SetDocument(bindableRichTextBox, bindableRichTextBox.Document); + } + } + + private static void SetDocument(object sender, object newValue) + { + if (sender is not RichTextBox control || newValue is not FlowDocument flowDocument) + return; + + control.Document = flowDocument; + + if (control is not BindableRichTextBox bindableRichTextBox) + return; + + if (bindableRichTextBox.WordWrapping) + { + control.Document.PageWidth = double.NaN; + } + else + { + control.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto; + + var size = MeasureString(bindableRichTextBox); + control.Document.PageWidth = size.Width + 12; } } #endregion // イベントハンドラ + + private static Size MeasureString(RichTextBox control) + { + using var graphics = Graphics.FromHwnd(IntPtr.Zero); + var dpiX = graphics.DpiX; + + var text = new TextRange(control.Document.ContentStart, control.Document.ContentEnd).Text; + var formattedText = new FormattedText(text, + CultureInfo.CurrentCulture, + FlowDirection.LeftToRight, + new Typeface(control.FontFamily, control.FontStyle, control.FontWeight, control.FontStretch), + control.FontSize, + Brushes.Black, + dpiX); + + return new Size(formattedText.Width, formattedText.Height); + } } } diff --git a/SavannahManager/Update/Views/CheckCleanFile.xaml b/SavannahManager/Views/Update/CheckCleanFile.xaml similarity index 94% rename from SavannahManager/Update/Views/CheckCleanFile.xaml rename to SavannahManager/Views/Update/CheckCleanFile.xaml index e778284a..d4643ad0 100644 --- a/SavannahManager/Update/Views/CheckCleanFile.xaml +++ b/SavannahManager/Views/Update/CheckCleanFile.xaml @@ -1,17 +1,16 @@ - @@ -39,7 +38,7 @@ - + diff --git a/SavannahManager/Views/Update/CheckCleanFile.xaml.cs b/SavannahManager/Views/Update/CheckCleanFile.xaml.cs new file mode 100644 index 00000000..4348f728 --- /dev/null +++ b/SavannahManager/Views/Update/CheckCleanFile.xaml.cs @@ -0,0 +1,15 @@ +using System.Windows; + +namespace _7dtd_svmanager_fix_mvvm.Views.Update +{ + /// + /// CheckCleanFile.xaml の相互作用ロジック + /// + public partial class CheckCleanFile : Window + { + public CheckCleanFile() + { + InitializeComponent(); + } + } +} diff --git a/SavannahManager/Update/Views/Loading.xaml b/SavannahManager/Views/Update/Loading.xaml similarity index 98% rename from SavannahManager/Update/Views/Loading.xaml rename to SavannahManager/Views/Update/Loading.xaml index 73592768..430509dc 100644 --- a/SavannahManager/Update/Views/Loading.xaml +++ b/SavannahManager/Views/Update/Loading.xaml @@ -1,4 +1,4 @@ - + /// Loading.xaml の相互作用ロジック + /// + public partial class Loading : Window + { + public Loading() + { + InitializeComponent(); + } + } +} diff --git a/SavannahManager/Update/Views/UpdForm.xaml b/SavannahManager/Views/Update/UpdForm.xaml similarity index 89% rename from SavannahManager/Update/Views/UpdForm.xaml rename to SavannahManager/Views/Update/UpdForm.xaml index e93f3eca..17222318 100644 --- a/SavannahManager/Update/Views/UpdForm.xaml +++ b/SavannahManager/Views/Update/UpdForm.xaml @@ -1,15 +1,15 @@ - @@ -39,7 +39,7 @@ - + @@ -88,14 +88,14 @@ - - + + - - + + diff --git a/SavannahManager/Update/Views/UpdForm.xaml.cs b/SavannahManager/Views/Update/UpdForm.xaml.cs similarity index 56% rename from SavannahManager/Update/Views/UpdForm.xaml.cs rename to SavannahManager/Views/Update/UpdForm.xaml.cs index 36eb4351..0fbad7be 100644 --- a/SavannahManager/Update/Views/UpdForm.xaml.cs +++ b/SavannahManager/Views/Update/UpdForm.xaml.cs @@ -1,23 +1,9 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; +using System.Windows; using System.Windows.Documents; using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Shapes; -using _7dtd_svmanager_fix_mvvm.Update.ViewModels; -using CommonStyleLib.ExMessageBox; -using CommonStyleLib.ExMessageBox.Views; -using CommonStyleLib.Views; +using _7dtd_svmanager_fix_mvvm.ViewModels.Update; -namespace _7dtd_svmanager_fix_mvvm.Update.Views +namespace _7dtd_svmanager_fix_mvvm.Views.Update { /// /// UpdForm.xaml の相互作用ロジック diff --git a/SavannahManager/Views/UserControls/AuthMode.cs b/SavannahManager/Views/UserControls/AuthMode.cs new file mode 100644 index 00000000..12e8e976 --- /dev/null +++ b/SavannahManager/Views/UserControls/AuthMode.cs @@ -0,0 +1,27 @@ +using System; + +namespace _7dtd_svmanager_fix_mvvm.Views.UserControls; + +public enum AuthMode +{ + Password, + Key +} + +public static class AuthModeExtensions +{ + public static int ToInt(this AuthMode authMode) + { + return (int)authMode; + } + + public static AuthMode FromInt(this int value) + { + return value switch + { + 0 => AuthMode.Password, + 1 => AuthMode.Key, + _ => AuthMode.Password + }; + } +} \ No newline at end of file diff --git a/SavannahManager/Views/UserControls/SshControl.xaml b/SavannahManager/Views/UserControls/SshControl.xaml new file mode 100644 index 00000000..7e568de8 --- /dev/null +++ b/SavannahManager/Views/UserControls/SshControl.xaml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + public BreakLineType BreakLine { get; set; } = BreakLineType.CrLf; + /// + /// LogStream object for telnet raw logging. + /// + private LogStream LoggingStream { get; set; } + + /// + /// Get the byte array of the line break line code according to BreakLine. + /// public byte[] BreakLineData { get @@ -154,6 +163,19 @@ public TelnetClient() }; } + /// + /// Enable logging. + /// + /// + public void EnableLogging(string directoryName) + { + LoggingStream = new LogStream(directoryName) + { + TextEncoding = Encoding, + AutoFlush = true + }; + } + /// /// Initialize it with the TelnetSocket argument. /// @@ -245,6 +267,11 @@ public string Read() _ = socket.Receive(bytes, SocketFlags.None); var returner = Encoding.GetString(bytes); + if (LoggingStream != null && !string.IsNullOrEmpty(returner)) + { + LoggingStream.Write(returner.TrimEnd('\0')); + } + return returner; }); @@ -427,6 +454,14 @@ protected virtual void Dispose(bool disposing) _clientSocket = null; }); + + if (LoggingStream != null) + { + lock (LoggingStream) + { + LoggingStream.Dispose(); + } + } } _disposedValue = true; diff --git a/SavannahManagerLibTests/SavannahManagerLibTests.csproj b/SavannahManagerLibTests/SavannahManagerLibTests.csproj index 4126db50..af422fba 100644 --- a/SavannahManagerLibTests/SavannahManagerLibTests.csproj +++ b/SavannahManagerLibTests/SavannahManagerLibTests.csproj @@ -1,10 +1,9 @@ - netcoreapp3.1 - + netcoreapp3.1;net48 false - + latest SvManagerLibraryTests2 diff --git a/SavannahXmlEditor/SavannahXmlEditor.csproj b/SavannahXmlEditor/SavannahXmlEditor.csproj index b6d192ca..e4936f6b 100644 --- a/SavannahXmlEditor/SavannahXmlEditor.csproj +++ b/SavannahXmlEditor/SavannahXmlEditor.csproj @@ -1,4 +1,4 @@ - + WinExe @@ -25,7 +25,7 @@ - + diff --git a/SshConsole/AbstractProgram.cs b/SshConsole/AbstractProgram.cs new file mode 100644 index 00000000..98cd256c --- /dev/null +++ b/SshConsole/AbstractProgram.cs @@ -0,0 +1,83 @@ +using System.Text; +using CommonExtensionLib.Extensions; +using SshConsole.Parser; + +namespace SshConsole; + +public abstract class AbstractProgram : IProgram +{ + protected Dictionary, string, string>> _actionMap; + protected Dictionary, string, string>> _funcMap; + + protected AbstractProgram() + { + _funcMap = new Dictionary, string, string>>() + { + { "exit", new Tuple, string, string>((parser) => false, "[]", "Exit this program.") }, + }; + + _actionMap = new Dictionary, string, string>>() + { + { "gc", new Tuple, string, string>(parser => GC.Collect(), "[]", "Run GC.Collect.") }, + { "help", new Tuple, string, string>(ShowHelp, "[] / [comamnd]", "Show the help.") } + }; + } + + protected void ShowHelp(CmdParser parser) + { + var sb = new StringBuilder(); + var command = parser.GetAttribute("command") ?? parser.GetAttribute(0); + if (command != null) + { + if (_funcMap.ContainsKey(command)) + { + var tuple = _funcMap[command]; + sb.AppendFormat(" {0}{1}{2}{3}{4}\n", command, command.MakeSpace(15), tuple.Item2, MakeSpace(tuple.Item2, 55), tuple.Item3); + } + if (_actionMap.ContainsKey(command)) + { + var tuple = _actionMap[command]; + sb.AppendFormat(" {0}{1}{2}{3}{4}\n", command, command.MakeSpace(15), tuple.Item2, MakeSpace(tuple.Item2, 55), tuple.Item3); + } + } + else + { + foreach (var tuple in _funcMap) + { + sb.AppendFormat(" {0}{1}{2}{3}{4}\n", tuple.Key, tuple.Key.MakeSpace(15), tuple.Value.Item2, tuple.Value.Item2.MakeSpace(55), tuple.Value.Item3); + } + + foreach (var tuple in _actionMap) + { + sb.AppendFormat(" {0}{1}{2}{3}{4}\n", tuple.Key, tuple.Key.MakeSpace(15), tuple.Value.Item2, tuple.Value.Item2.MakeSpace(55), tuple.Value.Item3); + } + } + + Console.WriteLine(sb); + } + + protected static string MakeSpace(string text, int max) + { + int count = max - text.Length; + count = count < 0 ? 1 : count; + var sb = new StringBuilder(); + for (int i = 0; i < count; i++) + { + sb.Append(" "); + } + return sb.ToString(); + } + + public virtual bool Parse(string cmd) + { + var parser = new CmdParser(cmd); + var command = parser.Command; + if (_funcMap.ContainsKey(command)) + return _funcMap[command].Item1(parser); + if (_actionMap.ContainsKey(command)) + _actionMap[command].Item1(parser); + return true; + } + + public abstract void Dispose(); +} \ No newline at end of file diff --git a/SshConsole/IProgram.cs b/SshConsole/IProgram.cs new file mode 100644 index 00000000..89921ff0 --- /dev/null +++ b/SshConsole/IProgram.cs @@ -0,0 +1,6 @@ +namespace SshConsole; + +public interface IProgram : IDisposable +{ + bool Parse(string cmd); +} \ No newline at end of file diff --git a/SshConsole/Parser/CmdParser.cs b/SshConsole/Parser/CmdParser.cs new file mode 100644 index 00000000..e7ba8a20 --- /dev/null +++ b/SshConsole/Parser/CmdParser.cs @@ -0,0 +1,117 @@ +using System.Text; +using System.Text.RegularExpressions; +using CommonExtensionLib.Extensions; + +namespace SshConsole.Parser +{ + public class CmdParser + { + /// + /// Command + /// + public string Command { get; } + + public string FullCommand { get; } + + private readonly Dictionary _attributes = new(); + private readonly List _listAttributes = new(); + + public CmdParser(string cmd) + { + FullCommand = cmd; + var parts = SplitWithoutDoubleQuote(cmd); + + Command = parts[0]; + for (int i = 1; i < parts.Count; i++) + { + var name = parts[i]; + if (name[0].Equals('-')) + { + name = name.Remove(0, 1); + _attributes.Add(name, parts[i + 1]); + i++; + } + else + { + _listAttributes.Add(name); + } + } + } + + public string GetAttribute(string attrName) + { + if (_attributes.ContainsKey(attrName)) + return _attributes[attrName]; + return null; + } + + public string GetAttribute(int index) + { + if (index >= 0 && index < _listAttributes.Count) + return _listAttributes[index]; + return null; + } + + public override string ToString() + { + var sb = new StringBuilder(); + sb.AppendFormat("[\n Command:\t{0}\n", Command); + foreach (var attribute in _attributes) + { + sb.AppendFormat(" Attribute:\t{0}:{1}\n", attribute.Key, attribute.Value); + } + sb.Append("]\n"); + + return sb.ToString(); + } + + #region Static Function + public static List SplitWithoutDoubleQuote(string text) + { + var table = new List(); + + RegexDoMached(text, "(?\"+([^\"]+)\"+)", m => + { + var val = m.Groups["quote"].Value; + table.Add(val); + text = text.Replace(val, "[{0}]".FormatString(table.Count - 1)); + }); + + var spl = text.Split(' '); + var res = new List(); + foreach (var elem in spl) + { + int num = RegexGetNumber(elem, "\\[(?[0-9]+)\\]"); + if (num > -1) + res.Add(elem.Replace("[{0}]".FormatString(num), table[num]).Replace("\"", "")); + else + res.Add(elem); + } + + return res; + } + + public static void RegexDoMached(string text, string pattern, Action callback) + { + var r = new Regex(pattern, RegexOptions.IgnoreCase); + var m = r.Match(text); + while (m.Success) + { + callback(m); + m = m.NextMatch(); + } + } + + public static int RegexGetNumber(string text, string pattern) + { + var r = new Regex(pattern, RegexOptions.IgnoreCase); + var m = r.Match(text); + if (m.Success) + { + return m.Groups["num"].Value.ToInt(); + } + return -1; + } + #endregion + } +} diff --git a/SshConsole/Parser/EnvArgumentParser.cs b/SshConsole/Parser/EnvArgumentParser.cs new file mode 100644 index 00000000..c91ff7fa --- /dev/null +++ b/SshConsole/Parser/EnvArgumentParser.cs @@ -0,0 +1,89 @@ +using CommonExtensionLib.Extensions; + +namespace SshConsole.Parser +{ + public class EnvArgumentParser + { + private readonly string[] arguments; + + protected readonly Dictionary parameters = new Dictionary(); + + protected readonly List values = new List(); + + public Dictionary optionCountMap = new Dictionary(); + + public EnvArgumentParser(string[] args) + { + arguments = args; + } + + public void AddOptionCount(string key, int count) + { + optionCountMap.Put(key, count); + } + + public void Analyze() + { + for (int i = 0; i < arguments.Length; i++) + { + var arg = arguments[i]; + if (arg.StartsWith("-")) + { + var count = optionCountMap.Get(arg, 1); + if (count > 0) + { + if (arguments.Length > i + 1) + { + var value = arguments[++i]; + parameters.Add(arg, value); + } + } + else + { + parameters.Add(arg, ""); + } + } + else + { + values.Add(arg); + } + } + } + + public string GetOutputFilepath(string option = "-o") + { + return GetOption(option); + } + + public bool IsExtract(string option = "-m") + { + var mode = GetOption(option); + return mode.Equals("e"); + } + + public bool IsInsert(string option = "-m") + { + var mode = GetOption(option); + return mode.Equals("i"); + } + + public string GetOption(string option) + { + if (parameters.ContainsKey(option)) + return parameters[option]; + return null; + } + + public string[] GetValues() + { + return values.ToArray(); + } + + public string GetValue() + { + if (values.Count > 0) + return values[0]; + return null; + } + } +} diff --git a/SshConsole/Program.cs b/SshConsole/Program.cs new file mode 100644 index 00000000..323d230e --- /dev/null +++ b/SshConsole/Program.cs @@ -0,0 +1,243 @@ +using System.Diagnostics; +using SshConsole.Parser; +using SvManagerLibrary.Ssh; + +namespace SshConsole +{ + class MainClass + { + public static void Main(string[] args) + { + Console.Write("mode> "); + var mode = Console.ReadLine() ?? ""; + IProgram program; + + switch (mode.ToLower()) + { + case "ssh": + program = new SshProgram(); + break; + case "sftp": + program = new SftpProgram(); + break; + default: + return; + } + + try + { + + while (true) + { + Console.Write("> "); + var cmd = Console.ReadLine() ?? ""; + var sw = new Stopwatch(); + sw.Start(); + + if (!program.Parse(cmd)) + break; + + sw.Stop(); + var msec = sw.ElapsedMilliseconds; + Console.WriteLine($"{msec}ms"); + } + } + finally + { + program?.Dispose(); + } + } + } + + public class SftpProgram : AbstractProgram + { + + private SftpServerConnector _connector; + + private bool _connected; + private SshProgram.Mode _mode = SshProgram.Mode.Pass; + + public SftpProgram() + { + _actionMap = new Dictionary, string, string>>(_actionMap) + { + { "auth", new Tuple, string, string>(ChangeMode, "[pass/key]", "default pass") }, + { "connect", new Tuple, string, string>(Connect, "[address] [port] [user] [pass] | [address] [port] [user] [pass] [key path]", "") }, + { "pwd", new Tuple, string, string>(ShowWorkingDirectory, "", "") }, + { "cd", new Tuple, string, string>(ChangeDirectory, "", "") }, + { "ls", new Tuple, string, string>(ShowFiles, "", "") } + }; + } + + private void ChangeMode(CmdParser parser) + { + var mode = parser.GetAttribute(0) ?? ""; + switch (mode.ToLower()) + { + case "pass": + _mode = SshProgram.Mode.Pass; + break; + case "key": + _mode = SshProgram.Mode.Key; + break; + default: + _mode = SshProgram.Mode.Pass; + break; + } + } + + private void Connect(CmdParser parser) + { + var address = parser.GetAttribute(0); + var portText = parser.GetAttribute(1); + var user = parser.GetAttribute(2); + var pass = parser.GetAttribute(3); + + int.TryParse(portText, out var port); + + _connector = new SftpServerConnector(address, port); + + if (_mode == SshProgram.Mode.Pass) + { + _connector.SetLoginInformation(user, pass); + } + else + { + var keyPath = parser.GetAttribute(4); + _connector.SetLoginInformation(user, pass, keyPath); + } + + _connector.Connect(); + _connected = true; + } + + private void ShowWorkingDirectory(CmdParser parser) + { + Console.WriteLine(_connector.WorkingDirectory); + } + + private void ChangeDirectory(CmdParser parser) + { + var path = parser.GetAttribute(0) ?? "~/"; + _connector.ChangeDirectory(path); + } + + private void ShowFiles(CmdParser parser) + { + var items = _connector.GetItems(); + foreach (var item in items.Where(x => x.IsDirectory)) + { + Console.WriteLine($"{item.Path} {item.IsDirectory}"); + } + foreach (var item in items.Where(x => !x.IsDirectory)) + { + Console.WriteLine($"{item.Path} {item.IsDirectory}"); + } + } + + public override void Dispose() + { + _connector?.Dispose(); + } + } + + public class SshProgram : AbstractProgram + { + public enum Mode + { + Pass, + Key + } + + private bool _connected; + + private SshServerConnector _connector; + private Mode _mode = Mode.Pass; + + public SshProgram() + { + _actionMap = new Dictionary, string, string>>(_actionMap) + { + { "auth", new Tuple, string, string>(ChangeMode, "[pass/key]", "default pass") }, + { "connect", new Tuple, string, string>(Connect, "[address] [port] [user] [pass] | [address] [port] [user] [pass] [key path]", "") }, + }; + } + + public override bool Parse(string cmd) + { + if (!_connected || _funcMap.ContainsKey(cmd)) + { + var parser = new CmdParser(cmd); + var command = parser.Command; + if (_funcMap.ContainsKey(command)) + return _funcMap[command].Item1(parser); + if (_actionMap.ContainsKey(command)) + _actionMap[command].Item1(parser); + } + else + { + SendCommand(cmd); + } + return true; + } + + private void SendCommand(string cmd) + { + if (_connector == null) + return; + + _connector.WriteLine(cmd); + } + + private void ChangeMode(CmdParser parser) + { + var mode = parser.GetAttribute(0) ?? ""; + switch (mode.ToLower()) + { + case "pass": + _mode = Mode.Pass; + break; + case "key": + _mode = Mode.Key; + break; + default: + _mode = Mode.Pass; + break; + } + } + + private void Connect(CmdParser parser) + { + var address = parser.GetAttribute(0); + var portText = parser.GetAttribute(1); + var user = parser.GetAttribute(2); + var pass = parser.GetAttribute(3); + + int.TryParse(portText, out var port); + + _connector = new SshServerConnector(address, port); + _connector.SshDataReceived.Subscribe(stream => + { + Console.WriteLine(stream.ReadToEnd()); + }); + + if (_mode == Mode.Pass) + { + _connector.SetLoginInformation(user, pass); + } + else + { + var keyPath = parser.GetAttribute(4); + _connector.SetLoginInformation(user, pass, keyPath); + } + + _connector.Connect(); + _connected = true; + } + + public override void Dispose() + { + _connector?.Dispose(); + } + } +} \ No newline at end of file diff --git a/SshConsole/SshConsole.csproj b/SshConsole/SshConsole.csproj new file mode 100644 index 00000000..a7fdc255 --- /dev/null +++ b/SshConsole/SshConsole.csproj @@ -0,0 +1,13 @@ + + + + Exe + net6.0 + enable + + + + + + + diff --git a/UpdateLogs/updates.en.xml b/UpdateLogs/updates.en.xml index 8d8dc4e0..a36b0ce5 100644 --- a/UpdateLogs/updates.en.xml +++ b/UpdateLogs/updates.en.xml @@ -1,5 +1,21 @@  + + 1. Support japanese in settings backup tab. + 2. Support auto restarting server. + If you want to use it, please enable the beta mode. + You can also set a detailed restart time in the Restart tab of the settings. + 3. Fixed an issue where logs could not be retrieved when a task error occurred. + 4. Support to change text from history when push up/down key. + 5. Support to encrypt password. + 6. Fixed an issue that crash to open calendar window in permission editor when date text is null. + 7. Fixed the Japanese translation of a20 in ConfigEditor. + 8. Changed the directory to output error log when occurs exception to "errors" directory. + 9. Fixed the method of getting Telnet logs. + 10. Added the ability to start a server via SSH. + You can start a Linux 7dtd server. + Note that the environment I'm checking is Ubuntu 18.04 only. + 1. The player list display now supports a20. 2. Support a20 server config on ConfigEditor. diff --git a/UpdateLogs/updates.ja.xml b/UpdateLogs/updates.ja.xml index a610fb5a..5edecbbf 100644 --- a/UpdateLogs/updates.ja.xml +++ b/UpdateLogs/updates.ja.xml @@ -1,5 +1,21 @@  + + 1. 設定のバックアップタブ内を日本語対応しました。 + 2. 自動再起動機能を追加しました。 + 使用するには設定のその他タブより、ベータモードを有効にしてください。 + また、設定のRestartタブで詳細なリスタート時間を設定することが出来ます。 + 3. 非同期タスクエラーが発生した場合に正しくログが取得できなくなる問題を修正しました。 + 4. キーボードの上下でコマンド実行履歴を入力できるようになりました。 + 5. パスワードの暗号化保存に対応しました。 + 6. 日付がNULLのとき、パーミッションエディターでカレンダーウィンドウを開くとクラッシュする問題を修正しました。 + 7. ConfigEditorのa20の日本語翻訳を修正しました。 + 8. エラー発生時にエラーログを出力するディレクトリを「errors」に変更しました。 + 9. Telnetログの取得方法を修正しました。 + 10. SSH経由でサーバを起動できるようにしました。 + これによりLinuxの7dtdサーバを起動できるようになります。 + なお、確認している環境はUbuntu 18.04のみです。 + 1. プレイヤーリストの表示がa20に対応しました。 2. ConfigEditorのa20 コンフィグテンプレートを追加しました。 diff --git a/Updater/Updater.csproj b/Updater/Updater.csproj index 99eb0a3f..698ac49a 100644 --- a/Updater/Updater.csproj +++ b/Updater/Updater.csproj @@ -1,4 +1,4 @@ - + WinExe @@ -22,7 +22,7 @@ - +