diff --git a/ASM/ArkServerManager_1.1.411.exe b/ASM/ArkServerManager_1.1.411.exe
new file mode 100644
index 00000000..29077470
Binary files /dev/null and b/ASM/ArkServerManager_1.1.411.exe differ
diff --git a/ASM/ArkServerManager_1.1.411.zip b/ASM/ArkServerManager_1.1.411.zip
new file mode 100644
index 00000000..2efee118
Binary files /dev/null and b/ASM/ArkServerManager_1.1.411.zip differ
diff --git a/ASM/ArkServerManager_1.1.412.exe b/ASM/ArkServerManager_1.1.412.exe
new file mode 100644
index 00000000..3b854b72
Binary files /dev/null and b/ASM/ArkServerManager_1.1.412.exe differ
diff --git a/ASM/ArkServerManager_1.1.412.zip b/ASM/ArkServerManager_1.1.412.zip
new file mode 100644
index 00000000..350e1255
Binary files /dev/null and b/ASM/ArkServerManager_1.1.412.zip differ
diff --git a/ASM/VersionFeed.xml b/ASM/VersionFeed.xml
index 7a82ae25..36923baa 100644
--- a/ASM/VersionFeed.xml
+++ b/ASM/VersionFeed.xml
@@ -5,7 +5,84 @@
Ark Server Manager Version Feed
This is the Ark Server Manager release version feed.
- 2021-12-05T00:00:00Z
+ 2021-12-15T00:00:00Z
+
+
+ urn:uuid:18276A38-2C71-4BB8-9A83-96D5EBFE9C87
+ 1.1.412 (1.1.412.4)
+ 1.1.412.4
+
+ 2021-12-15T00:00:00Z
+
+
+
+ BUGFIX
+
+
+ Fixed a bug with the Server Shutdown when the CheckForOnlinePlayers option not selected.
+ Fixed a bug when the backup path was a root directory that caused a 'Invalid URI: A Dos path must be rooted' crash.
+ Added additional validation when setting directories in the global setting, to ensure they are rooted correctly.
+ Fixed a bug when starting the server manager and it tries to download steamcmd, but fails as steamcmd is unavailable for download.
+
+
CHANGE
+
+
+ fr-FR Translation file updated.
+ zh-CN Translation file updated.
+ Added LostIsland to official mods in the SurvivalEvolved gamedata file.
+ Added coloring to the setting grids for the Lost Island DLC engrams, creatures and resources.
+
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
+
+
+ urn:uuid:DBAFCE91-2235-4B6C-AE9B-5E4EF9FEC8F5
+ 1.1.411 (1.1.411.10)
+ 1.1.411.10
+
+ 2021-12-14T00:00:00Z
+
+
+
+ NEW
+
+
+
+ A new Discord Bot has been added to the server manager.
+ This new discord bot will allow you to send Start, Stop, Shutdown, Restart, Backup and Update commands to the server manager from within your discord client.
+ To setup the new discord bot, open the global settings and scroll down to the Discord section.
+
+ NOTE: This is long process to get the discord bot working, and I have created a forum post with detailed instructions how to do it.
+
+
+ Server Settings - Dino Section - Added MutagenLevelBoost and MutagenLevelBoostBred settings.
+ Added gamedata file for the Lost Island DLC - only contains the map name for the Map droplist - do not use until the DLC is officially released!
+
+
CHANGE
+
+
+ Global Settings - Added reset button to the Data Directory Location.
+ Server Monitor window now stores it's location.
+ Removed MOTD and Alternate Save Directory from the Administration section of the Sync.
+ fr-FR Translation file updated.
+ pt-BR Translation file updated.
+ ru-RU Translation file updated.
+ zh-CN Translation file updated.
+
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
urn:uuid:BE37B3FD-B498-4B1C-9D4D-754EA0F4A357
diff --git a/ASM/beta/VersionFeed.xml b/ASM/beta/VersionFeed.xml
index b066b3e4..03eb394c 100644
--- a/ASM/beta/VersionFeed.xml
+++ b/ASM/beta/VersionFeed.xml
@@ -5,22 +5,22 @@
Ark Server Manager Version Feed
This is the Ark Server Manager beta version feed.
- 2021-12-12T00:00:00Z
+ 2021-12-16T00:00:00Z
- urn:uuid:C02D44F9-E3AA-4CA0-BF2F-110F8C83CC21
- 1.1.411 (1.1.411.7)
- 1.1.411.7
+ urn:uuid:8EE5659C-18E6-47D3-941D-C32B129D2E06
+ 1.1.413 (1.1.413.7)
+ 1.1.413.7
- 2021-12-12T00:00:00Z
+ 2021-12-17T00:00:00Z
NEW
- Added gamedata file for the Lost Island DLC - only contains the map name for the Map droplist - do not use until the DLC is officially released!
- Added Lost Island to the language files for translation.
+ Main Window - Added Discord Bot Status and a button to Stop/Start the discord bot.
+ Global Settings - Discord Bot section - Added a checkbox to allow all bots.
@@ -32,42 +32,18 @@
- urn:uuid:F75C6AFF-2A27-49BE-917A-7EAAACCCBF17
- 1.1.411 (1.1.411.6)
- 1.1.411.6
+ urn:uuid:65A7E6B1-98D1-422D-B42F-B0EBB1D20E41
+ 1.1.413 (1.1.413.6)
+ 1.1.413.6
- 2021-12-12T00:00:00Z
+ 2021-12-17T00:00:00Z
CHANGE
- fr-FR Translation file updated.
-
-
-
-
-
- bletch
- bletch1971@hotmail.com
-
-
-
-
- urn:uuid:0BCB8BBA-330F-4063-8B7E-5B144589999A
- 1.1.411 (1.1.411.5)
- 1.1.411.5
-
- 2021-12-10T00:00:00Z
-
-
-
- CHANGE
-
-
- Server Monitor window now stores it's location.
- Reference library updates.
+ Added additional message logging when log level set to debug.
pt-BR Translation file updated.
ru-RU Translation file updated.
@@ -81,29 +57,69 @@
- urn:uuid:7697EBD7-DEF6-422B-B9A6-D4B77F31D572
- 1.1.411 (1.1.411.4)
- 1.1.411.4
+ urn:uuid:65A7E6B1-98D1-422D-B42F-B0EBB1D20E41
+ 1.1.413 (1.1.413.5)
+ 1.1.413.5
- 2021-12-09T00:00:00Z
+ 2021-12-16T00:00:00Z
+
+
+
+ NEW
+
+
+ Global Settings - Discord Bot section - Added a log level droplist.
+
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
+
+
+ urn:uuid:98FFBFA1-4E99-4801-BF2B-CA68BE300C27
+ 1.1.413 (1.1.413.4)
+ 1.1.413.4
+
+ 2021-12-16T00:00:00Z
BUGFIX
- Fixed a minor issue when clicking the data directory reset button - fringe case that I found during testing.
+ Fixed a bug that would prevent a bot on the whitelist processing the message.
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
+
+
+ urn:uuid:8958A494-DE13-4F6F-ACA2-10026D5FB8A9
+ 1.1.413 (1.1.413.3)
+ 1.1.413.3
+
+ 2021-12-16T00:00:00Z
+
+
+
NEW
- Server Settings - Dino Section - Added MutagenLevelBoost and MutagenLevelBoostBred settings.
+ Server Settings - Discord Bot section - Added an alias that can be used with the discord command instead of the profile id.
CHANGE
- pt-BR Translation file updated.
- ru-RU Translation file updated.
+ Removed the mandatory requirement to enter the '!' after the discord prefix. The '!' has been added to the existing prefix so no change to existing functionality, but you can now change it.
zh-CN Translation file updated.
@@ -116,73 +132,41 @@
- urn:uuid:8290F43D-98F4-4F4D-8DD8-0A3EF5A45656
- 1.1.411 (1.1.411.3)
- 1.1.411.3
+ urn:uuid:8958A494-DE13-4F6F-ACA2-10026D5FB8A9
+ 1.1.413 (1.1.413.2)
+ 1.1.413.2
- 2021-12-08T00:00:00Z
-
-
-
- BUGFIX
-
-
- Fixed language translation of Data Directory window.
-
-
-
-
-
- bletch
- bletch1971@hotmail.com
-
-
-
-
- urn:uuid:ADBF3FE0-017C-4E23-8FE8-EFE75E7C8BA1
- 1.1.411 (1.1.411.2)
- 1.1.411.2
-
- 2021-12-08T00:00:00Z
-
-
-
- CHANGE
-
-
- Global Settings - Added reset button to the Data Directory Location.
- pt-BR Translation file updated.
- zh-CN Translation file updated.
-
-
-
-
-
- bletch
- bletch1971@hotmail.com
-
-
-
-
- urn:uuid:DBAFCE91-2235-4B6C-AE9B-5E4EF9FEC8F5
- 1.1.411 (1.1.411.1)
- 1.1.411.1
-
- 2021-12-06T00:00:00Z
+ 2021-12-16T00:00:00Z
NEW
-
- A new Discord Bot has been added to the server manager.
- This new discord bot will allow you to send Start, Stop, Shutdown, Restart, Backup and Update commands to the server manager from within your discord client.
- To setup the new discord bot, open the global settings and scroll down to the Discord section.
-
- NOTE: This is long process to get the discord bot working, and I have created a forum post with detailed instructions how to do it.
-
-
+ Global Settings - Discord Bot section - Added a whitelist to allow bots to send commands to the server manager.
+
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
+
+
+ urn:uuid:3E33DCB2-ECFE-4489-B1A4-56F5D386F9DC
+ 1.1.413 (1.1.413.1)
+ 1.1.413.1
+
+ 2021-12-16T00:00:00Z
+
+
+
+ CHANGE
+
+
+ Made changes to the code to help improve performance.
diff --git a/ASM/beta/en-US.xaml b/ASM/beta/en-US.xaml
index 12c4e7fe..4ad2bee2 100644
--- a/ASM/beta/en-US.xaml
+++ b/ASM/beta/en-US.xaml
@@ -83,12 +83,21 @@
All
-
+
Normal
Minimized
Maximized
+
+ Critical
+ Error
+ Warning
+ Info
+ Verbose
+ Debug
+
+
Run as Administrator
This application requires administration priviledges to access ALL functionality. Would you like to Run as Administrator?
@@ -127,6 +136,7 @@
Server download complete
Complete
Cancelled
+ Failed
Cancel
@@ -621,8 +631,17 @@
The id of the discord server the bot will listen to.
Prefix:
The prefix that must be used when sending a command via discord.
+ Log Level:
Get Token...
Help...
+ Allow All Bots
+ If enabled, the server manager bot will respond to all other bots, otherwise they will be ignored unless they are in the whitelist.
+ Bot Whitelist
+ Bot ID
+ The id of the bot to whitelist.
+ Add Whitelist
+ Clear Whitelists
+ Delete Whitelist
If enabled, the backup command can be sent from discord.
If enabled, the restart command can be sent from discord.
If enabled, the shutdown command can be sent from discord.
@@ -773,12 +792,18 @@
Enable
Enable the auto-update scheduled task
Next Run Time:
+ Discord Bot:
+ Start
+ Start the discord bot
+ Stop
+ Stop the discord bot
Unknown
Disabled
Queued
Ready
Running
+ Stopped
Profile failed to load
The profile at {0} failed to load. The error was: {1}\r\n{2}
@@ -1207,6 +1232,8 @@
Discord Bot Details
Channel Id:
The id of the discord server channel this profile will listen to.
+ Alias:
+ A unique name to identify your server when using the discord commands, can be used instead of the profile id.
Allow Backup
If enabled, the profile will listen for backup commands from discord.
Allow Restart
@@ -5495,6 +5522,23 @@
Boss Inventory - Crystal Wyvern Queen (Gamma)
Boss Inventory - Crystal Wyvern Queen (Beta)
Boss Inventory - Crystal Wyvern Queen (Alpha)
+
+ Boss Inventory - Dragon (Gamma)
+ Boss Inventory - Dragon (Beta)
+ Boss Inventory - Dragon (Alpha)
+ Boss Inventory - Manticore (Gamma)
+ Boss Inventory - Manticore (Beta)
+ Boss Inventory - Manticore (Alpha)
+
+ Boss Inventory - Dragon (Easy)
+ Boss Inventory - Dragon (Medium)
+ Boss Inventory - Dragon (Hard)
+ Boss Inventory - Manticore (Easy)
+ Boss Inventory - Manticore (Medium)
+ Boss Inventory - Manticore (Hard)
+ Boss Inventory - Megapithecus (Easy)
+ Boss Inventory - Megapithecus (Medium)
+ Boss Inventory - Megapithecus (Hard)
@@ -5580,8 +5624,9 @@
Another command '{0}' is currently running against profile '{1}'.
Command '{0}' has been disabled for profile '{1}'.
- The '{0}' command requires a profile id.
+ The '{0}' command requires a profile id or alias.
Profile '{0}' was not found or is not associated with the channel.
+ Multiple profiles with '{0}' were found in the channel, command aborted.
Profile '{0}' is in a state '{1}' that cannot run this command.
Profile '{0}' is currently being updated.
diff --git a/ASM/beta/latest.txt b/ASM/beta/latest.txt
index b64b069b..359dfd67 100644
--- a/ASM/beta/latest.txt
+++ b/ASM/beta/latest.txt
@@ -1 +1 @@
-1.1.411.7
+1.1.413.7
diff --git a/ASM/beta/latest.zip b/ASM/beta/latest.zip
index ef2570a1..b0a9e9b9 100644
Binary files a/ASM/beta/latest.zip and b/ASM/beta/latest.zip differ
diff --git a/ASM/en-US.xaml b/ASM/en-US.xaml
index 2384aae1..f6281726 100644
--- a/ASM/en-US.xaml
+++ b/ASM/en-US.xaml
@@ -24,6 +24,7 @@
Genesis: Part 1
Crystal Isles
Genesis: Part 2
+ Lost Island
@@ -56,6 +57,7 @@
Genesis: Part 1
Crystal Isles
Genesis: Part 2
+ Lost Island
PGM
@@ -125,6 +127,7 @@
Server download complete
Complete
Cancelled
+ Failed
Cancel
@@ -610,7 +613,24 @@
This message will be displayed when the server shutdown has been cancelled.
Show shutdown reason with ALL shutdown messages
If enabled, the shutdown reason will be shown with all shutdown message; otherwise it will only be shown at the start of the server shutdown.
-
+
+ Enable Discord Bot
+ You will need to restart the server manager if you change any settings for the Discord Bot.
+ Token:
+ The token associated with the discord bot.
+ Server Id:
+ The id of the discord server the bot will listen to.
+ Prefix:
+ The prefix that must be used when sending a command via discord.
+ Get Token...
+ Help...
+ If enabled, the backup command can be sent from discord.
+ If enabled, the restart command can be sent from discord.
+ If enabled, the shutdown command can be sent from discord.
+ If enabled, the start command can be sent from discord.
+ If enabled, the stop command can be sent from discord.
+ If enabled, the update command can be sent from discord.
+
SMTP Email Settings
Host:
The name or IP address of the host used for SMTP transmissions.
@@ -662,6 +682,8 @@
Changing the data directory will move any existing profiles to the new location, but it will not move any server installations. Do you still want to change this directory?
Failed to change data directory
There was an error changing the data directory: {0}\r\nPlease correct the error and try again, or contact technical support for assistance.
+ Confirm Data Directory Reset
+ Click 'Yes' to confirm you want to reset the location of the data directory. Once reset, the server manager will shutdown and you will need to restart.
Select Backup Directory
Select Cache Directory
@@ -775,6 +797,9 @@
Reinstall SteamCMD Error
An error occured while trying to reinstall SteamCMD. This has left SteamCmd in an unstable state, try reinstalling again or please report this.\r\nException: {0}
+ Discord Bot Running Commands
+ The discord bot has one or more running commands, do you want to continue shutting down the server manager?
+
Start Server Confirmation
You are about to start the server, do you want to continue?
Shutdown Server Confirmation
@@ -1179,6 +1204,24 @@
If enabled, the server will be restarted even if shutdown for Auto-Restarts and Auto-Updates.
+
+ Discord Bot Details
+ Channel Id:
+ The id of the discord server channel this profile will listen to.
+ Allow Backup
+ If enabled, the profile will listen for backup commands from discord.
+ Allow Restart
+ If enabled, the profile will listen for restart commands from discord.
+ Allow Shutdown
+ If enabled, the profile will listen for shutdown commands from discord.
+ Allow Start
+ If enabled, the profile will listen for start commands from discord.
+ Allow Stop
+ If enabled, the profile will listen for stop commands from discord.
+ Allow Update
+ If enabled, the profile will listen for update commands from discord.
+
+
Rules
Enable Hardcore Mode
@@ -1598,14 +1641,18 @@
Per-Level Stat Multipliers (Tamed) - Add
Per-Level Stat Multipliers (Tamed) - Affinity
Per-Level Stat Multipliers (Wild)
+ Mutagen Level Boost (Wild)
+ Mutagen Level Boost (Bred)
Dino Breeding Multipliers
If enabled, allows scale factors to be applied to each base stat.
If enabled, allows scale factors to be applied to each stat.
If enabled, allows scale factors to be applied to the Taming Addition for each stat.
If enabled, allows scale factors to be applied to the Taming Multiplier for each stat.
If enabled, allows scale factors to be applied to the Tamed Stat Increase for each stat.
- Reset all multipliers back to defaults.
- Reset all multipliers back to defaults.
+ If enabled, allows scale factors to be applied to the Number of levels Mutagen adds to tames with wild ancestry.
+ If enabled, allows scale factors to be applied to the Number of levels Mutagen adds to tames with bred ancestry.
+ Reset all values back to defaults.
+ Reset all values back to defaults.
Mating Interval:
Specifies the multiplier for time between tamed dino mating. Lower values decrease the time between mating.
@@ -5449,6 +5496,23 @@
Boss Inventory - Crystal Wyvern Queen (Gamma)
Boss Inventory - Crystal Wyvern Queen (Beta)
Boss Inventory - Crystal Wyvern Queen (Alpha)
+
+ Boss Inventory - Dragon (Gamma)
+ Boss Inventory - Dragon (Beta)
+ Boss Inventory - Dragon (Alpha)
+ Boss Inventory - Manticore (Gamma)
+ Boss Inventory - Manticore (Beta)
+ Boss Inventory - Manticore (Alpha)
+
+ Boss Inventory - Dragon (Easy)
+ Boss Inventory - Dragon (Medium)
+ Boss Inventory - Dragon (Hard)
+ Boss Inventory - Manticore (Easy)
+ Boss Inventory - Manticore (Medium)
+ Boss Inventory - Manticore (Hard)
+ Boss Inventory - Megapithecus (Easy)
+ Boss Inventory - Megapithecus (Medium)
+ Boss Inventory - Megapithecus (Hard)
@@ -5523,4 +5587,32 @@
There was a problem while performing the server update. This may leave your server in a incomplete state.\r\n\r\nDo you want to continue with the server start, this could cause problems?
+
+ Discord Bot Error
+ The discord bot requires a valid token so it can log into the discord server\r\nThis can be set in the global settings.
+ The discord bot prefix contains invalid characters. Only letters and numbers are allowed.
+
+ Command '{0}' has not been enabled.
+ Unknown command '{0}'.
+ Another command is currently being processed.
+ Another command '{0}' is currently running against profile '{1}'.
+ Command '{0}' has been disabled for profile '{1}'.
+
+ The '{0}' command requires a profile id.
+ Profile '{0}' was not found or is not associated with the channel.
+ Profile '{0}' is in a state '{1}' that cannot run this command.
+ Profile '{0}' is currently being updated.
+
+ Call to server '{0}' failed.
+ A backup request for server '{0}' has been sent.
+ A restart request for server '{0}' has been sent.
+ A shutdown request for server '{0}' has been sent.
+ A start request for server '{0}' has been sent.
+ A stop request for server '{0}' has been sent.
+ An update request for server '{0}' has been sent.
+
+ Count:
+ Map:
+
+
\ No newline at end of file
diff --git a/ASM/latest.exe b/ASM/latest.exe
index 8964a320..3b854b72 100644
Binary files a/ASM/latest.exe and b/ASM/latest.exe differ
diff --git a/ASM/latest.txt b/ASM/latest.txt
index 73a41c03..a03f4f61 100644
--- a/ASM/latest.txt
+++ b/ASM/latest.txt
@@ -1 +1 @@
-1.1.410
+1.1.412
diff --git a/ASM/latest.zip b/ASM/latest.zip
index eb8ad6cc..350e1255 100644
Binary files a/ASM/latest.zip and b/ASM/latest.zip differ
diff --git a/CSM/ConanServerManager_1.1.56.exe b/CSM/ConanServerManager_1.1.56.exe
new file mode 100644
index 00000000..54cb8dc3
Binary files /dev/null and b/CSM/ConanServerManager_1.1.56.exe differ
diff --git a/CSM/ConanServerManager_1.1.56.zip b/CSM/ConanServerManager_1.1.56.zip
new file mode 100644
index 00000000..e03e666f
Binary files /dev/null and b/CSM/ConanServerManager_1.1.56.zip differ
diff --git a/CSM/ConanServerManager_1.1.57.exe b/CSM/ConanServerManager_1.1.57.exe
new file mode 100644
index 00000000..ff86db29
Binary files /dev/null and b/CSM/ConanServerManager_1.1.57.exe differ
diff --git a/CSM/ConanServerManager_1.1.57.zip b/CSM/ConanServerManager_1.1.57.zip
new file mode 100644
index 00000000..c039f9a4
Binary files /dev/null and b/CSM/ConanServerManager_1.1.57.zip differ
diff --git a/CSM/VersionFeed.xml b/CSM/VersionFeed.xml
index 6b861df7..9d75ce81 100644
--- a/CSM/VersionFeed.xml
+++ b/CSM/VersionFeed.xml
@@ -5,7 +5,69 @@
Conan Server Manager Version Feed
This is the Conan Server Manager release version feed.
- 2021-12-02T00:00:00Z
+ 2021-12-15T00:00:00Z
+
+
+ urn:uuid:6383E79A-C31F-462B-9730-B26B28DC5EFF
+ 1.1.57 (1.1.57.3)
+ 1.1.57.3
+
+ 2021-12-15T00:00:00Z
+
+
+
+ BUGFIX
+
+
+ Fixed a bug with the Server Shutdown when the CheckForOnlinePlayers option not selected.
+ Fixed a bug when the backup path was a root directory that caused a 'Invalid URI: A Dos path must be rooted' crash.
+ Added additional validation when setting directories in the global setting, to ensure they are rooted correctly.
+ Fixed a bug when starting the server manager and it tries to download steamcmd, but fails as steamcmd is unavailable for download.
+
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
+
+
+ urn:uuid:F8A08616-749B-48E7-87D5-D97E86AB3926
+ 1.1.56 (1.1.56.6)
+ 1.1.56.6
+
+ 2021-12-12T00:00:00Z
+
+
+
+ NEW
+
+
+
+ A new Discord Bot has been added to the server manager.
+ This new discord bot will allow you to send Start, Stop, Shutdown, Restart, Backup and Update commands to the server manager from within your discord client.
+ To setup the new discord bot, open the global settings and scroll down to the Discord section.
+
+ NOTE: This is long process to get the discord bot working, and I have created a forum post with detailed instructions how to do it.
+
+
+
+
CHANGE
+
+
+ Global Settings - Added reset button to the Data Directory Location.
+ Server Monitor window now stores it's location.
+
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
urn:uuid:A3A790A9-D511-4CE8-AC15-A36B3DAB4385
diff --git a/CSM/beta/VersionFeed.xml b/CSM/beta/VersionFeed.xml
index 9a499dcf..4fc8f6e2 100644
--- a/CSM/beta/VersionFeed.xml
+++ b/CSM/beta/VersionFeed.xml
@@ -5,144 +5,165 @@
Conan Server Manager Version Feed
This is the Conan Server Manager beta version feed.
- 2021-12-12T00:00:00Z
+ 2021-12-17T00:00:00Z
- urn:uuid:4C15C7A9-317C-4A9B-B426-6E885B918D3B
- 1.1.56 (1.1.56.6)
- 1.1.56.6
+ urn:uuid:9A427D82-9904-44F5-8C1E-7C943049869A
+ 1.1.58 (1.1.58.7)
+ 1.1.58.7
- 2021-12-12T00:00:00Z
-
-
-
- BUGFIX
-
-
- Reference library updates.
-
-
-
-
-
- bletch
- bletch1971@hotmail.com
-
-
-
-
- urn:uuid:126E8E9F-7FF2-4239-88D6-5FFC89925463
- 1.1.56 (1.1.56.5)
- 1.1.56.5
-
- 2021-12-10T00:00:00Z
-
-
-
- BUGFIX
-
-
- Server Monitor window now stores it's location.
- Reference library updates.
-
-
-
-
-
- bletch
- bletch1971@hotmail.com
-
-
-
-
- urn:uuid:BECA74AB-1107-40B0-932A-A851E978EABF
- 1.1.56 (1.1.56.4)
- 1.1.56.4
-
- 2021-12-09T00:00:00Z
-
-
-
- BUGFIX
-
-
- Fixed a minor issue when clicking the data directory reset button - fringe case that I found during testing.
-
-
-
-
-
- bletch
- bletch1971@hotmail.com
-
-
-
-
- urn:uuid:8C834060-F20F-4ACE-8F49-0B459531BA3C
- 1.1.56 (1.1.56.3)
- 1.1.56.3
-
- 2021-12-08T00:00:00Z
-
-
-
- BUGFIX
-
-
- Fixed language translation of Data Directory window.
-
-
-
-
-
- bletch
- bletch1971@hotmail.com
-
-
-
-
- urn:uuid:339F72FC-920A-4425-AF86-AF9B34611A21
- 1.1.56 (1.1.56.2)
- 1.1.56.2
-
- 2021-12-08T00:00:00Z
-
-
-
- CHANGE
-
-
- Global Settings - Added reset button to the Data Directory Location.
-
-
-
-
-
- bletch
- bletch1971@hotmail.com
-
-
-
-
- urn:uuid:F8A08616-749B-48E7-87D5-D97E86AB3926
- 1.1.56 (1.1.56.1)
- 1.1.56.1
-
- 2021-12-06T00:00:00Z
+ 2021-12-17T00:00:00Z
NEW
-
- A new Discord Bot has been added to the server manager.
- This new discord bot will allow you to send Start, Stop, Shutdown, Restart, Backup and Update commands to the server manager from within your discord client.
- To setup the new discord bot, open the global settings and scroll down to the Discord section.
-
- NOTE: This is long process to get the discord bot working, and I have created a forum post with detailed instructions how to do it.
-
-
+ Main Window - Added Discord Bot Status and a button to Stop/Start the discord bot.
+ Global Settings - Discord Bot section - Added a checkbox to allow all bots.
+
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
+
+
+ urn:uuid:A189668E-DA03-471A-9C5A-7FF2A7264F9C
+ 1.1.58 (1.1.58.6)
+ 1.1.58.6
+
+ 2021-12-17T00:00:00Z
+
+
+
+ CHANGE
+
+
+ Added additional message logging when log level set to debug.
+
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
+
+
+ urn:uuid:A189668E-DA03-471A-9C5A-7FF2A7264F9C
+ 1.1.58 (1.1.58.5)
+ 1.1.58.5
+
+ 2021-12-16T00:00:00Z
+
+
+
+ NEW
+
+
+ Global Settings - Discord Bot section - Added a log level droplist.
+
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
+
+
+ urn:uuid:F3C22842-A089-46F7-AB1A-5D3DED105412
+ 1.1.58 (1.1.58.4)
+ 1.1.58.4
+
+ 2021-12-16T00:00:00Z
+
+
+
+ BUGFIX
+
+
+ Fixed a bug that would prevent a bot on the whitelist processing the message.
+
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
+
+
+ urn:uuid:F3C22842-A089-46F7-AB1A-5D3DED105412
+ 1.1.58 (1.1.58.3)
+ 1.1.58.3
+
+ 2021-12-16T00:00:00Z
+
+
+
+ NEW
+
+
+ Server Settings - Discord Bot section - Added an alias that can be used with the discord command instead of the profile id.
+
+
CHANGE
+
+
+ Removed the mandatory requirement to enter the '!' after the discord prefix. The '!' has been added to the existing prefix so no change to existing functionality, but you can now change it.
+
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
+
+
+ urn:uuid:C566D9D2-3566-46DF-8AD4-39F5FC0FFEF2
+ 1.1.58 (1.1.58.2)
+ 1.1.58.2
+
+ 2021-12-16T00:00:00Z
+
+
+
+ NEW
+
+
+ Global Settings - Discord Bot section - Added a whitelist to allow bots to send commands to the server manager.
+
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
+
+
+ urn:uuid:19B09A66-43F2-4D5F-AF33-5C77D7EA9A6B
+ 1.1.58 (1.1.58.1)
+ 1.1.58.1
+
+ 2021-12-16T00:00:00Z
+
+
+
+ CHANGE
+
+
+ Made changes to the code to help improve performance.
diff --git a/CSM/beta/en-US.xaml b/CSM/beta/en-US.xaml
index 9a6c123b..db8c265c 100644
--- a/CSM/beta/en-US.xaml
+++ b/CSM/beta/en-US.xaml
@@ -57,12 +57,21 @@
All
-
+
Normal
Minimized
Maximized
+
+ Critical
+ Error
+ Warning
+ Info
+ Verbose
+ Debug
+
+
x
%
@@ -120,6 +129,7 @@
Server download complete
Complete
Cancelled
+ Failed
Cancel
@@ -605,12 +615,18 @@
Enable
Enable the auto-update scheduled task
Next Run Time:
+ Discord Bot:
+ Start
+ Start the discord bot
+ Stop
+ Stop the discord bot
Unknown
Disabled
Queued
Ready
Running
+ Stopped
Profile failed to load
The profile at {0} failed to load. The error was: {1}\r\n{2}
@@ -779,8 +795,17 @@
The id of the discord server the bot will listen to.
Prefix:
The prefix that must be used when sending a command via discord.
+ Log Level:
Get Token...
Help...
+ Allow All Bots
+ If enabled, the server manager bot will respond to all other bots, otherwise they will be ignored unless they are in the whitelist.
+ Bot Whitelist
+ Bot ID
+ The id of the bot to whitelist.
+ Add Whitelist
+ Clear Whitelists
+ Delete Whitelist
If enabled, the backup command can be sent from discord.
If enabled, the restart command can be sent from discord.
If enabled, the shutdown command can be sent from discord.
@@ -1147,6 +1172,8 @@
Discord Bot Details
Channel Id:
The id of the discord server channel this profile will listen to.
+ Alias:
+ A unique name to identify your server when using the discord commands, can be used instead of the profile id.
Allow Backup
If enabled, the profile will listen for backup commands from discord.
Allow Restart
@@ -1244,8 +1271,9 @@
Another command '{0}' is currently running against profile '{1}'.
Command '{0}' has been disabled for profile '{1}'.
- The '{0}' command requires a profile id.
+ The '{0}' command requires a profile id or alias.
Profile '{0}' was not found or is not associated with the channel.
+ Multiple profiles with '{0}' were found in the channel, command aborted.
Profile '{0}' is in a state '{1}' that cannot run this command.
Profile '{0}' is currently being updated.
diff --git a/CSM/beta/latest.txt b/CSM/beta/latest.txt
index 20d52c3e..96ec7d2c 100644
--- a/CSM/beta/latest.txt
+++ b/CSM/beta/latest.txt
@@ -1 +1 @@
-1.1.56.6
+1.1.58.7
diff --git a/CSM/beta/latest.zip b/CSM/beta/latest.zip
index aac86862..e0b87bc2 100644
Binary files a/CSM/beta/latest.zip and b/CSM/beta/latest.zip differ
diff --git a/CSM/en-US.xaml b/CSM/en-US.xaml
index e61a9e28..50e599fb 100644
--- a/CSM/en-US.xaml
+++ b/CSM/en-US.xaml
@@ -120,6 +120,7 @@
Server download complete
Complete
Cancelled
+ Failed
Cancel
@@ -628,6 +629,9 @@
Reinstall SteamCMD Error
An error occured while trying to reinstall SteamCMD. This has left SteamCmd in an unstable state, try reinstalling again or please report this.\r\nException: {0}
+ Discord Bot Running Commands
+ The discord bot has one or more running commands, do you want to continue shutting down the server manager?
+
Start Server Confirmation
You are about to start the server, do you want to continue?
Shutdown Server Confirmation
@@ -768,6 +772,23 @@
Show shutdown reason with ALL shutdown messages
If enabled, the shutdown reason will be shown with all shutdown message; otherwise it will only be shown at the start of the server shutdown.
+ Enable Discord Bot
+ You will need to restart the server manager if you change any settings for the Discord Bot.
+ Token:
+ The token associated with the discord bot.
+ Server Id:
+ The id of the discord server the bot will listen to.
+ Prefix:
+ The prefix that must be used when sending a command via discord.
+ Get Token...
+ Help...
+ If enabled, the backup command can be sent from discord.
+ If enabled, the restart command can be sent from discord.
+ If enabled, the shutdown command can be sent from discord.
+ If enabled, the start command can be sent from discord.
+ If enabled, the stop command can be sent from discord.
+ If enabled, the update command can be sent from discord.
+
SMTP Email Settings
Host:
The name or IP address of the host used for SMTP transmissions.
@@ -815,6 +836,8 @@
Changing the data directory will move any existing profiles to the new location, but it will not move any server installations. Do you still want to change this directory?
Failed to change data directory
There was an error changing the data directory: {0}\r\nPlease correct the error and try again, or contact technical support for assistance.
+ Confirm Data Directory Reset
+ Click 'Yes' to confirm you want to reset the location of the data directory. Once reset, the server manager will shutdown and you will need to restart.
Select Backup Directory
Select Cache Directory
@@ -1121,6 +1144,24 @@
If enabled, the server will be restarted even if shutdown for Auto-Restarts and Auto-Updates.
+
+ Discord Bot Details
+ Channel Id:
+ The id of the discord server channel this profile will listen to.
+ Allow Backup
+ If enabled, the profile will listen for backup commands from discord.
+ Allow Restart
+ If enabled, the profile will listen for restart commands from discord.
+ Allow Shutdown
+ If enabled, the profile will listen for shutdown commands from discord.
+ Allow Start
+ If enabled, the profile will listen for start commands from discord.
+ Allow Stop
+ If enabled, the profile will listen for stop commands from discord.
+ Allow Update
+ If enabled, the profile will listen for update commands from discord.
+
+
Server File Details
NOTE: Any changes will require a server restart to take effect.
@@ -1193,4 +1234,32 @@
There was a problem while performing the server update. This may leave your server in a incomplete state.\r\n\r\nDo you want to continue with the server start, this could cause problems?
+
+ Discord Bot Error
+ The discord bot requires a valid token so it can log into the discord server\r\nThis can be set in the global settings.
+ The discord bot prefix contains invalid characters. Only letters and numbers are allowed.
+
+ Command '{0}' has not been enabled.
+ Unknown command '{0}'.
+ Another command is currently being processed.
+ Another command '{0}' is currently running against profile '{1}'.
+ Command '{0}' has been disabled for profile '{1}'.
+
+ The '{0}' command requires a profile id.
+ Profile '{0}' was not found or is not associated with the channel.
+ Profile '{0}' is in a state '{1}' that cannot run this command.
+ Profile '{0}' is currently being updated.
+
+ Call to server '{0}' failed.
+ A backup request for server '{0}' has been sent.
+ A restart request for server '{0}' has been sent.
+ A shutdown request for server '{0}' has been sent.
+ A start request for server '{0}' has been sent.
+ A stop request for server '{0}' has been sent.
+ An update request for server '{0}' has been sent.
+
+ Count:
+ Map:
+
+
\ No newline at end of file
diff --git a/CSM/latest.exe b/CSM/latest.exe
index 33267533..ff86db29 100644
Binary files a/CSM/latest.exe and b/CSM/latest.exe differ
diff --git a/CSM/latest.txt b/CSM/latest.txt
index 5ebc7199..5df20b4e 100644
--- a/CSM/latest.txt
+++ b/CSM/latest.txt
@@ -1 +1 @@
-1.1.55
+1.1.57
diff --git a/CSM/latest.zip b/CSM/latest.zip
index cc4e3efc..c039f9a4 100644
Binary files a/CSM/latest.zip and b/CSM/latest.zip differ
diff --git a/GameData/Template/Template.gamedata b/GameData/Template/Template.gamedata
index f7c58ff7..47765c96 100644
--- a/GameData/Template/Template.gamedata
+++ b/GameData/Template/Template.gamedata
@@ -2,7 +2,7 @@
"Application": "ark",
"Version": "1.0.0",
"Created": "2020-03-04T00:00:00.0000000Z",
- "Mod": "ArkPrime|TheCenter|PrimitivePlus|ScorchedEarth|Ragnarok|Aberration|Extinction|Genesis|CrystalIsles|Genesis2|LostIsland|",
+ "Mod": "ArkPrime|TheCenter|PrimitivePlus|ScorchedEarth|Ragnarok|Aberration|Extinction|Genesis|Valguero|CrystalIsles|Genesis2|LostIsland|",
"Creatures": [
{
"NameTag": "Achatina",
diff --git a/Plugins/Discord/ServerManager.Plugin.Discord_1.0.19.zip b/Plugins/Discord/ServerManager.Plugin.Discord_1.0.19.zip
new file mode 100644
index 00000000..f8f09d75
Binary files /dev/null and b/Plugins/Discord/ServerManager.Plugin.Discord_1.0.19.zip differ
diff --git a/Plugins/Discord/VersionFeed.xml b/Plugins/Discord/VersionFeed.xml
index 981fd7c5..52a870db 100644
--- a/Plugins/Discord/VersionFeed.xml
+++ b/Plugins/Discord/VersionFeed.xml
@@ -5,7 +5,39 @@
Discord Plugin Version Feed
This is the Discord Plugin release version feed.
- 2021-12-03T00:00:00Z
+ 2021-12-12T00:00:00Z
+
+
+ urn:uuid:A9EC2F32-E026-485F-BD7B-C657DBA95B54
+ 1.0.19 (1.0.19.5)
+ 1.0.19.5
+
+ 2021-12-12T00:00:00Z
+
+
+
+ BUGFIX
+
+
+ Fixed alert test message to support globalization.
+
+
CHANGE
+
+
+ Changed the plugin initialization so it throws an exception if unable to load config file, rather than creating a new config file.
+ de-DE Translation file updated.
+ fr-FR Translation file added.
+ pt-BR Translation file updated.
+ ru-RU Translation file added.
+
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
urn:uuid:C01A4AA0-D839-4732-9814-301DAC6EB094
diff --git a/Plugins/Discord/beta/VersionFeed.xml b/Plugins/Discord/beta/VersionFeed.xml
index 3c7cbb83..48b3f9c8 100644
--- a/Plugins/Discord/beta/VersionFeed.xml
+++ b/Plugins/Discord/beta/VersionFeed.xml
@@ -7,6 +7,52 @@
2021-12-12T00:00:00Z
+
+ urn:uuid:A0D7BFD2-F2F0-481A-A22D-3C193BFB4C99
+ 1.0.19 (1.0.19.5)
+ 1.0.19.5
+
+ 2021-12-12T00:00:00Z
+
+
+
+ CHANGE
+
+
+ ru-RU Translation file updated.
+
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
+
+
+ urn:uuid:38A61493-CA4E-479E-A3FD-266565E83D90
+ 1.0.19 (1.0.19.4)
+ 1.0.19.4
+
+ 2021-12-12T00:00:00Z
+
+
+
+ CHANGE
+
+
+ ru-RU Translation file added.
+
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
+
urn:uuid:DDB25735-1D20-4580-B5FE-1AD4BD107376
1.0.19 (1.0.19.3)
diff --git a/Plugins/Discord/beta/latest.txt b/Plugins/Discord/beta/latest.txt
index 4821a307..a9fd2b1c 100644
--- a/Plugins/Discord/beta/latest.txt
+++ b/Plugins/Discord/beta/latest.txt
@@ -1 +1 @@
-1.0.19.3
+1.0.19.5
diff --git a/Plugins/Discord/beta/latest.zip b/Plugins/Discord/beta/latest.zip
index 4838a11d..0c59dc88 100644
Binary files a/Plugins/Discord/beta/latest.zip and b/Plugins/Discord/beta/latest.zip differ
diff --git a/Plugins/Discord/en-US.xaml b/Plugins/Discord/en-US.xaml
index 82a5f111..0ff41e2c 100644
--- a/Plugins/Discord/en-US.xaml
+++ b/Plugins/Discord/en-US.xaml
@@ -118,6 +118,8 @@
Test Action Error
An error occurred while trying to test the config profile.
The profile is not enabled and cannot be tested.
+
+ Test '{0}' alert type message for profile name '{1}'
diff --git a/Plugins/Discord/latest.txt b/Plugins/Discord/latest.txt
index 54473825..ecba93a4 100644
--- a/Plugins/Discord/latest.txt
+++ b/Plugins/Discord/latest.txt
@@ -1 +1 @@
-1.0.18
+1.0.19
diff --git a/Plugins/Discord/latest.zip b/Plugins/Discord/latest.zip
index c5f1d7a8..f8f09d75 100644
Binary files a/Plugins/Discord/latest.zip and b/Plugins/Discord/latest.zip differ
diff --git a/src/ARKServerManager/ARKServerManager.csproj b/src/ARKServerManager/ARKServerManager.csproj
index b7242f38..380bd3cd 100644
--- a/src/ARKServerManager/ARKServerManager.csproj
+++ b/src/ARKServerManager/ARKServerManager.csproj
@@ -145,7 +145,6 @@
-
diff --git a/src/ARKServerManager/App.config b/src/ARKServerManager/App.config
index febac3a6..f74ceca5 100644
--- a/src/ARKServerManager/App.config
+++ b/src/ARKServerManager/App.config
@@ -353,6 +353,9 @@
https://arkservermanager.freeforums.net/thread/8764/get-own-discord-bot
+
+ 10
+
@@ -814,7 +817,7 @@
False
- asm
+ asm!
@@ -849,6 +852,20 @@
50
+
+
+
+
+
+
+ False
+
+
+ Info
+
+
+ False
+
diff --git a/src/ARKServerManager/App.xaml.cs b/src/ARKServerManager/App.xaml.cs
index 2e79faa1..aded5630 100644
--- a/src/ARKServerManager/App.xaml.cs
+++ b/src/ARKServerManager/App.xaml.cs
@@ -11,6 +11,7 @@ using ServerManagerTool.Plugin.Common;
using ServerManagerTool.Utils;
using ServerManagerTool.Windows;
using System;
+using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
@@ -38,7 +39,7 @@ namespace ServerManagerTool
public event PropertyChangedEventHandler PropertyChanged;
- private CancellationTokenSource _tokenSource;
+ private CancellationTokenSource _tokenSourceDiscordBot;
private GlobalizedApplication _globalizer;
private bool _applicationStarted;
private string _args;
@@ -49,7 +50,45 @@ namespace ServerManagerTool
public App()
{
if (string.IsNullOrWhiteSpace(Config.Default.ASMUniqueKey))
+ {
Config.Default.ASMUniqueKey = Guid.NewGuid().ToString();
+ }
+
+ if (!string.IsNullOrWhiteSpace(Config.Default.DataDir))
+ {
+ var root = Path.GetPathRoot(Config.Default.DataDir);
+ if (!root.EndsWith("\\"))
+ {
+ Config.Default.DataDir = Config.Default.DataDir.Replace(root, root + "\\");
+ }
+ }
+
+ if (!string.IsNullOrWhiteSpace(Config.Default.ConfigDirectory))
+ {
+ var root = Path.GetPathRoot(Config.Default.ConfigDirectory);
+ if (!root.EndsWith("\\"))
+ {
+ Config.Default.ConfigDirectory = Config.Default.ConfigDirectory.Replace(root, root + "\\");
+ }
+ }
+
+ if (!string.IsNullOrWhiteSpace(Config.Default.BackupPath))
+ {
+ var root = Path.GetPathRoot(Config.Default.BackupPath);
+ if (!root.EndsWith("\\"))
+ {
+ Config.Default.BackupPath = Config.Default.BackupPath.Replace(root, root + "\\");
+ }
+ }
+
+ if (!string.IsNullOrWhiteSpace(Config.Default.AutoUpdate_CacheDir))
+ {
+ var root = Path.GetPathRoot(Config.Default.AutoUpdate_CacheDir);
+ if (!root.EndsWith("\\"))
+ {
+ Config.Default.AutoUpdate_CacheDir = Config.Default.AutoUpdate_CacheDir.Replace(root, root + "\\");
+ }
+ }
App.Instance = this;
ApplicationStarted = false;
@@ -112,6 +151,18 @@ namespace ServerManagerTool
}
}
+ public bool DiscordBotStarted
+ {
+ get
+ {
+ return _tokenSourceDiscordBot != null;
+ }
+ set
+ {
+ OnPropertyChanged();
+ }
+ }
+
public string Title
{
get
@@ -246,6 +297,14 @@ namespace ServerManagerTool
CommonConfig.Default.Save();
}
}
+ if (!Config.Default.DiscordBotPrefixFixed)
+ {
+ if (!Config.Default.DiscordBotPrefix.EndsWith("!"))
+ Config.Default.DiscordBotPrefix += "!";
+ Config.Default.DiscordBotPrefixFixed = true;
+ Config.Default.Save();
+ Config.Default.Reload();
+ }
Config.Default.SteamCmdRedirectOutput = false;
}
@@ -451,21 +510,7 @@ namespace ServerManagerTool
if (Config.Default.DiscordBotEnabled)
{
- _tokenSource = new CancellationTokenSource();
-
- Task discordTask = Task.Run(async () =>
- {
- await ServerManagerBotFactory.GetServerManagerBot()?.StartAsync(Config.Default.DiscordBotToken, Config.Default.DiscordBotPrefix, Config.Default.DataDir, DiscordBotHelper.HandleDiscordCommand, DiscordBotHelper.HandleTranslation, _tokenSource.Token);
- }, _tokenSource.Token)
- .ContinueWith(t => {
- var message = t.Exception.InnerException is null ? t.Exception.Message : t.Exception.InnerException.Message;
- if (message.StartsWith("#"))
- {
- message = _globalizer.GetResourceString(message.Substring(1)) ?? message.Substring(1);
- }
-
- MessageBox.Show(message, _globalizer.GetResourceString("DiscordBot_ErrorTitle"), MessageBoxButton.OK, MessageBoxImage.Error);
- }, TaskContinuationOptions.OnlyOnFaulted);
+ StartDiscordBot();
}
}
@@ -507,11 +552,7 @@ namespace ServerManagerTool
private void ShutDownApplication()
{
- if (!(_tokenSource is null))
- {
- _tokenSource.Cancel();
- _tokenSource.Dispose();
- }
+ StopDiscordBot();
if (ApplicationStarted)
{
@@ -544,13 +585,68 @@ namespace ServerManagerTool
var installFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var backupFolder = includeBackup
- ? IOUtils.NormalizePath(string.IsNullOrWhiteSpace(Config.Default.BackupPath)
+ ? string.IsNullOrWhiteSpace(Config.Default.BackupPath)
? Path.Combine(Config.Default.DataDir, Config.Default.BackupDir)
- : Path.Combine(Config.Default.BackupPath))
+ : Path.Combine(Config.Default.BackupPath)
: null;
SettingsUtils.BackupUserConfigSettings(Config.Default, "userconfig.json", installFolder, backupFolder);
SettingsUtils.BackupUserConfigSettings(CommonConfig.Default, "commonconfig.json", installFolder, backupFolder);
}
+
+ public void StartDiscordBot()
+ {
+ if (_tokenSourceDiscordBot != null)
+ {
+ return;
+ }
+
+ _tokenSourceDiscordBot = new CancellationTokenSource();
+ DiscordBotStarted = true;
+
+ Task discordTask = Task.Run(async () =>
+ {
+ var discordWhiteList = new List();
+ if (Config.Default.DiscordBotWhitelist != null)
+ {
+ discordWhiteList.AddRange(Config.Default.DiscordBotWhitelist.Cast());
+ }
+
+ await ServerManagerBotFactory.GetServerManagerBot()?.StartAsync(Config.Default.DiscordBotLogLevel, Config.Default.DiscordBotToken, Config.Default.DiscordBotPrefix, Config.Default.DataDir, Config.Default.DiscordBotAllowAllBots, discordWhiteList, DiscordBotHelper.HandleDiscordCommand, DiscordBotHelper.HandleTranslation, _tokenSourceDiscordBot.Token);
+
+ if (_tokenSourceDiscordBot != null)
+ {
+ // cleanup the token
+ _tokenSourceDiscordBot.Dispose();
+ _tokenSourceDiscordBot = null;
+ }
+ DiscordBotStarted = false;
+ }, _tokenSourceDiscordBot.Token)
+ .ContinueWith(t => {
+ var message = t.Exception.InnerException is null ? t.Exception.Message : t.Exception.InnerException.Message;
+ if (message.StartsWith("#"))
+ {
+ message = _globalizer.GetResourceString(message.Substring(1)) ?? message.Substring(1);
+ }
+
+ MessageBox.Show(message, _globalizer.GetResourceString("DiscordBot_ErrorTitle"), MessageBoxButton.OK, MessageBoxImage.Error);
+
+ if (_tokenSourceDiscordBot != null)
+ {
+ // cleanup the token
+ _tokenSourceDiscordBot.Dispose();
+ _tokenSourceDiscordBot = null;
+ }
+ DiscordBotStarted = false;
+ }, TaskContinuationOptions.OnlyOnFaulted);
+ }
+
+ public void StopDiscordBot()
+ {
+ if (!(_tokenSourceDiscordBot is null))
+ {
+ _tokenSourceDiscordBot.Cancel();
+ }
+ }
}
}
diff --git a/src/ARKServerManager/Config.Designer.cs b/src/ARKServerManager/Config.Designer.cs
index 5f9d64bb..ae20bf76 100644
--- a/src/ARKServerManager/Config.Designer.cs
+++ b/src/ARKServerManager/Config.Designer.cs
@@ -2827,7 +2827,7 @@ namespace ServerManagerTool {
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("asm")]
+ [global::System.Configuration.DefaultSettingValueAttribute("asm!")]
public string DiscordBotPrefix {
get {
return ((string)(this["DiscordBotPrefix"]));
@@ -2986,5 +2986,63 @@ namespace ServerManagerTool {
this["ServerMonitorWindow_Top"] = value;
}
}
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("\r\n ")]
+ public global::System.Collections.Specialized.StringCollection DiscordBotWhitelist {
+ get {
+ return ((global::System.Collections.Specialized.StringCollection)(this["DiscordBotWhitelist"]));
+ }
+ set {
+ this["DiscordBotWhitelist"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("False")]
+ public bool DiscordBotPrefixFixed {
+ get {
+ return ((bool)(this["DiscordBotPrefixFixed"]));
+ }
+ set {
+ this["DiscordBotPrefixFixed"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("Info")]
+ public global::ServerManagerTool.DiscordBot.Enums.LogLevel DiscordBotLogLevel {
+ get {
+ return ((global::ServerManagerTool.DiscordBot.Enums.LogLevel)(this["DiscordBotLogLevel"]));
+ }
+ set {
+ this["DiscordBotLogLevel"] = value;
+ }
+ }
+
+ [global::System.Configuration.ApplicationScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("10")]
+ public int DiscordBotStatusCheckTime {
+ get {
+ return ((int)(this["DiscordBotStatusCheckTime"]));
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("False")]
+ public bool DiscordBotAllowAllBots {
+ get {
+ return ((bool)(this["DiscordBotAllowAllBots"]));
+ }
+ set {
+ this["DiscordBotAllowAllBots"] = value;
+ }
+ }
}
}
diff --git a/src/ARKServerManager/Config.settings b/src/ARKServerManager/Config.settings
index c11d5ae4..6f6869f6 100644
--- a/src/ARKServerManager/Config.settings
+++ b/src/ARKServerManager/Config.settings
@@ -783,7 +783,7 @@
False
- asm
+ asm!
@@ -824,5 +824,21 @@
50
+
+ <?xml version="1.0" encoding="utf-16"?>
+<ArrayOfString xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
+
+
+ False
+
+
+ Info
+
+
+ 10
+
+
+ False
+
\ No newline at end of file
diff --git a/src/ARKServerManager/Enums/ServerProcessType.cs b/src/ARKServerManager/Enums/ServerProcessType.cs
index 7298dfd9..cced8642 100644
--- a/src/ARKServerManager/Enums/ServerProcessType.cs
+++ b/src/ARKServerManager/Enums/ServerProcessType.cs
@@ -8,8 +8,9 @@
AutoShutdown1,
AutoShutdown2,
Backup,
- Shutdown,
Restart,
+ Shutdown,
+ Stop,
Update,
}
}
diff --git a/src/ARKServerManager/GameData/SurvivalEvolved.gamedata b/src/ARKServerManager/GameData/SurvivalEvolved.gamedata
index 55d5a720..3c7e8e42 100644
--- a/src/ARKServerManager/GameData/SurvivalEvolved.gamedata
+++ b/src/ARKServerManager/GameData/SurvivalEvolved.gamedata
@@ -13406,6 +13406,10 @@
{
"ModId": "CrystalIsles",
"ModName": "Crystal Isles"
+ },
+ {
+ "ModId": "LostIsland",
+ "ModName": "Lost Island"
}
]
}
\ No newline at end of file
diff --git a/src/ARKServerManager/Globalization/en-US/en-US.xaml b/src/ARKServerManager/Globalization/en-US/en-US.xaml
index c59fab28..d905aa52 100644
--- a/src/ARKServerManager/Globalization/en-US/en-US.xaml
+++ b/src/ARKServerManager/Globalization/en-US/en-US.xaml
@@ -83,12 +83,21 @@
All
-
+
Normal
Minimized
Maximized
+
+ Critical
+ Error
+ Warning
+ Info
+ Verbose
+ Debug
+
+
Run as Administrator
This application requires administration priviledges to access ALL functionality. Would you like to Run as Administrator?
@@ -127,6 +136,7 @@
Server download complete
Complete
Cancelled
+ Failed
Cancel
@@ -621,8 +631,17 @@
The id of the discord server the bot will listen to.
Prefix:
The prefix that must be used when sending a command via discord.
+ Log Level:
Get Token...
Help...
+ Allow All Bots
+ If enabled, the server manager bot will respond to all other bots, otherwise they will be ignored unless they are in the whitelist.
+ Bot Whitelist
+ Bot ID
+ The id of the bot to whitelist.
+ Add Whitelist
+ Clear Whitelists
+ Delete Whitelist
If enabled, the backup command can be sent from discord.
If enabled, the restart command can be sent from discord.
If enabled, the shutdown command can be sent from discord.
@@ -773,12 +792,18 @@
Enable
Enable the auto-update scheduled task
Next Run Time:
+ Discord Bot:
+ Start
+ Start the discord bot
+ Stop
+ Stop the discord bot
Unknown
Disabled
Queued
Ready
Running
+ Stopped
Profile failed to load
The profile at {0} failed to load. The error was: {1}\r\n{2}
@@ -1207,6 +1232,8 @@
Discord Bot Details
Channel Id:
The id of the discord server channel this profile will listen to.
+ Alias:
+ A unique name to identify your server when using the discord commands, can be used instead of the profile id.
Allow Backup
If enabled, the profile will listen for backup commands from discord.
Allow Restart
@@ -5495,6 +5522,23 @@
Boss Inventory - Crystal Wyvern Queen (Gamma)
Boss Inventory - Crystal Wyvern Queen (Beta)
Boss Inventory - Crystal Wyvern Queen (Alpha)
+
+ Boss Inventory - Dragon (Gamma)
+ Boss Inventory - Dragon (Beta)
+ Boss Inventory - Dragon (Alpha)
+ Boss Inventory - Manticore (Gamma)
+ Boss Inventory - Manticore (Beta)
+ Boss Inventory - Manticore (Alpha)
+
+ Boss Inventory - Dragon (Easy)
+ Boss Inventory - Dragon (Medium)
+ Boss Inventory - Dragon (Hard)
+ Boss Inventory - Manticore (Easy)
+ Boss Inventory - Manticore (Medium)
+ Boss Inventory - Manticore (Hard)
+ Boss Inventory - Megapithecus (Easy)
+ Boss Inventory - Megapithecus (Medium)
+ Boss Inventory - Megapithecus (Hard)
@@ -5580,8 +5624,9 @@
Another command '{0}' is currently running against profile '{1}'.
Command '{0}' has been disabled for profile '{1}'.
- The '{0}' command requires a profile id.
+ The '{0}' command requires a profile id or alias.
Profile '{0}' was not found or is not associated with the channel.
+ Multiple profiles with '{0}' were found in the channel, command aborted.
Profile '{0}' is in a state '{1}' that cannot run this command.
Profile '{0}' is currently being updated.
diff --git a/src/ARKServerManager/Globalization/fr-FR/fr-FR.xaml b/src/ARKServerManager/Globalization/fr-FR/fr-FR.xaml
index 89e0c5d0..35f838cb 100644
--- a/src/ARKServerManager/Globalization/fr-FR/fr-FR.xaml
+++ b/src/ARKServerManager/Globalization/fr-FR/fr-FR.xaml
@@ -24,6 +24,7 @@
Genesis
Crystal Isles
Genesis: Part 2
+ Lost Island
@@ -44,8 +45,8 @@
- All
- Unknown
+ Tout
+ Inconnu
ARK Prime
The Center
Primitive Plus
@@ -56,6 +57,7 @@
Genesis
Crystal Isles
Genesis: Part 2
+ Lost Island
PGM
@@ -610,6 +612,23 @@
Ce message sera affiché lorsque la fermeture du serveur a été annulée.
Afficher le motif d'arrêt avec TOUS les messages d'arrêt
Si elle est activée, la raison de l'arrêt s'affichera avec tous les messages d'arrêt; sinon, il ne sera affiché qu'au début de l'arrêt du serveur.
+
+ Activer le Bot Discord
+ Vous devrez redémarrer le gestionnaire de serveur si vous modifiez les paramètres du Bot Discord..
+ Token:
+ Le token associé au bot discord.
+ ID Serveur:
+ L'ID du serveur que le Bot discord écoutera.
+ Prefixe:
+ Le préfixe qui doit être utilisé lors de l'envoi d'une commande via discord.
+ Faire desToken...
+ Help...
+ Si activé, la commande de sauvegarde peut être envoyée du Discord.
+ Si activé, la commande de redémarrage peut être envoyée du discord.
+ Si activé, la commande d'arrêt peut être envoyée du discord.
+ Si activé, la commande de démarrage peut être envoyée du discord.
+ Si activé, la commande stop peut être envoyée du discord.
+ Si activé, la commande de mise à jour peut être envoyée du discord.
Paramètres de messagerie SMTP
Host:
@@ -662,6 +681,8 @@
La modification du répertoire de données déplacera tous les profils existants vers le nouvel emplacement, mais ne déplacera aucune installation de serveur. Voulez-vous toujours changer ce répertoire?
Échec de la modification du répertoire de données
Une erreur s'est produite lors de la modification du répertoire de données: {0}\r\nVeuillez corriger l'erreur et réessayer, ou contactez le support technique pour obtenir de l'aide.
+ Confirmer la réinitialisation du répertoire de données
+ Cliquez sur "Oui" pour confirmer que vous souhaitez réinitialiser l'emplacement du répertoire de données. Une fois réinitialisé, le gestionnaire de serveur va arrêter et vous devrez redémarrer.
Sélectionnez le répertoire de sauvegarde
Sélectionnez le répertoire du cache
@@ -775,6 +796,9 @@
Erreur lors de la réinstallation de SteamCMD
Une erreur est survenue lors de la réinstallation de SteamCMD. Cela a laissé SteamCmd dans un état instable, essayez de le réinstaller à nouveau ou signalez-le.\r\nException: {0}
+ Discord Bot Exécute des commandes
+ Le Bot discord à une ou plusieurs commandes en cours d'exécution, voulez-vous continuer à arrêter le gestionnaire de serveur?
+
Confirmer le démarage du serveur
Vous êtes sur le point de démarrer le serveur, voulez-vous continuer?
Confirmer l'arrêt du serveur
@@ -1178,6 +1202,24 @@
Redémarrer le serveur en cas d'arrêt
Si cette option est activée, le serveur sera redémarré même s'il est arrêté pour les redémarrages automatiques et les mises à jour automatiques.
+
+
+ Détail du bot Discord
+ Id DU canal:
+ L'ID du canal de Discord Server que ce profil écoutera.
+ Autoriser la sauvegarde
+ Si activé, le profil écoutera les commandes de sauvegarde de discord.
+ Autoriser le redémarrage
+ Si activé, le profil écoutera les commandes de redémarrage de discord.
+ Autoriser l'arrêt
+ Si activé, le profil écoutera les commandes d'arrêt de discord.
+ Autoriser le démarrage
+ Si activé, le profil écoutera les commandes de démarrage de discord.
+ Autoriser l'arrêt
+ Si activé, le profil écoutera les commandes d'arrêt de discord.
+ Autoriser la mise à jour
+ Si activé, le profil écoutera les commandes de mise à jour de discord.
+
Règles
@@ -1598,12 +1640,16 @@
Multiplicateurs de statistiques par niveau (apprivoisés) - Ajouter
Multiplicateurs de statistiques par niveau (apprivoisés)- Affinité
Multiplicateurs de statistiques par niveau (sauvage)
+ Boost de niveau mutagène (sauvage)
+ Boost de niveau mutagène (élevée)
Multiplicateurs d'élevage de dinosaures
Si activé, permet d'appliquer des facteurs d'échelle à chaque statistique de base.
Si activé, permet d'appliquer des facteurs d'échelle à chaque statistique.
Si activé, permet d'appliquer des facteurs d'échelle à l'ajout d'apprivoisement pour chaque statistique.
Si activé, permet d'appliquer des facteurs d'échelle au multiplicateur d'apprivoisement pour chaque statistique.
Si activé, permet d'appliquer des facteurs d'échelle à l'augmentation de la statistique apprivoisée pour chaque statistique.
+ Si activé, permet aux facteurs d'échelle d'être appliqués au nombre de niveaux mutagen ajoute aux Tames avec une ascendance sauvage.
+ Si activé, permet aux facteurs d'échelle d'être appliqués au nombre de niveaux mutagen ajoute aux Tames avec ascendance élevée.
Réinitialiser tous les multiplicateurs aux valeurs par défaut.
Réinitialiser tous les multiplicateurs aux valeurs par défaut.
@@ -5449,6 +5495,23 @@
Boss Inventory - Crystal Wyvern Queen (Gamma)
Boss Inventory - Crystal Wyvern Queen (Beta)
Boss Inventory - Crystal Wyvern Queen (Alpha)
+
+ Boss Inventory - Dragon (Gamma)
+ Boss Inventory - Dragon (Beta)
+ Boss Inventory - Dragon (Alpha)
+ Boss Inventory - Manticore (Gamma)
+ Boss Inventory - Manticore (Beta)
+ Boss Inventory - Manticore (Alpha)
+
+ Boss Inventory - Dragon (Easy)
+ Boss Inventory - Dragon (Medium)
+ Boss Inventory - Dragon (Hard)
+ Boss Inventory - Manticore (Easy)
+ Boss Inventory - Manticore (Medium)
+ Boss Inventory - Manticore (Hard)
+ Boss Inventory - Megapithecus (Easy)
+ Boss Inventory - Megapithecus (Medium)
+ Boss Inventory - Megapithecus (Hard)
@@ -5523,4 +5586,32 @@
Un problème est survenu lors de la mise à jour du serveur. Cela peut laisser votre serveur dans un état incomplet.\r\n\r\n Souhaitez-vous continuer le démarrage du serveur, cela pourrait provoquer des problèmes?
+
+ Erreur Bot Discord Bot
+ Le bot de la discussion nécessite un Token valide afin qu'il puisse se connecter au serveur de discord\r\nthis peut être défini dans les paramètres globaux..
+ Le préfixe du Bot discord contient des caractères non valides. Seules les lettres et les chiffres sont autorisés.
+
+ Commande '{0}' n'a pas été activée.
+ Commande inconnue '{0}'.
+ Une autre commande est en cours de traitement.
+ Une autre commande '{0}' fonctionne actuellement contre le profil'{1}'.
+ Commande '{0}' a été désactivé pour le profil '{1}'.
+
+ The '{0}' commande nécessite un ID du profil.
+ Profile '{0}' n'a pas été trouvé ou n'est pas associé au canal.
+ Profile '{0}' est dans un état '{1}' qui ne peut pas exécuter cette commande.
+ Profile '{0}' est actuellement mis à jour.
+
+ Appeler au serveur '{0}' a échoué.
+ Une demande de sauvegarde pour serveur '{0}' a été envoyée.
+ Une demande de redémarrage de serveur '{0}' a été envoyée.
+ Une demande d'arrêt pour serveur '{0}' a été envoyée.
+ Une demande de démarrage pour le serveur '{0}' a été envoyée.
+ Une demande d'arrêt de serveur '{0}' a été envoyée.
+ Une demande de mise à jour du serveur '{0}' a été envoyée.
+
+ Dénombrer:
+ Map:
+
+
\ No newline at end of file
diff --git a/src/ARKServerManager/Globalization/pt-BR/pt-BR.xaml b/src/ARKServerManager/Globalization/pt-BR/pt-BR.xaml
index beb43096..e7e3acdb 100644
--- a/src/ARKServerManager/Globalization/pt-BR/pt-BR.xaml
+++ b/src/ARKServerManager/Globalization/pt-BR/pt-BR.xaml
@@ -24,6 +24,7 @@
Genesis: Part 1
Crystal Isles
Genesis: Part 2
+ Lost Island
@@ -56,6 +57,7 @@
Genesis: Part 1
Crystal Isles
Genesis: Part 2
+ Lost Island
PGM
@@ -81,10 +83,19 @@
Todos
-
+
Normal
Minimizado
Maximizado
+
+
+
+ Crítico
+ Erro
+ Aviso
+ Informações
+ Verboso
+ Debug
@@ -125,6 +136,7 @@
Download do servidor concluído
Completo
Cancelado
+ Falhou
Cancela
@@ -619,8 +631,15 @@
O id do servidor discord que o bot usará.
Prefix:
O prefixo que deve ser usado ao enviar um comando via discord.
+ Nível de registro:
Obter Token...
Ajuda...
+ Bot Whitelist
+ Bot ID
+ O id do bot a ser colocado na whitelist.
+ Add Whitelist
+ Limpar Whitelists
+ Deletar Whitelist
Se ativado, o comando de backup pode ser enviado do discord.
Se ativado, o comando de reiniciar pode ser enviado do discord.
Se habilitado, o comando de desligar pode ser enviado do discord.
@@ -1205,6 +1224,8 @@
Detalhes do Discord Bot
Id do canal:
O id do canal do discord que este perfil irá usar.
+ Nome exclusivo:
+ Um nome exclusivo para identificar seu servidor ao usar os comandos discord, pode ser usado em vez do ID do perfil.
Permitir backup
Se ativado, o perfil usará os comandos de backup pelo discord.
Permitir Reinício
@@ -5504,6 +5525,10 @@
Boss Inventory - Crystal Wyvern Queen (Beta)
Boss Inventory - Crystal Wyvern Queen (Alpha)
+ Boss Inventory - Dinopithecus (Gamma)
+ Boss Inventory - Dinopithecus (Beta)
+ Boss Inventory - Dinopithecus (Alpha)
+
Boss Inventory - Dragon (Gamma)
Boss Inventory - Dragon (Beta)
Boss Inventory - Dragon (Alpha)
@@ -5597,6 +5622,7 @@
O comando '{0}' requer um id de perfil.
O perfil '{0}' não foi encontrado ou não está associado ao canal.
+ Vários perfis com '{0}' foram encontrados no canal, comando abortado.
O perfil '{0}' está em um estado '{1}' que não pode executar este comando.
O perfil '{0}' está sendo atualizado.
diff --git a/src/ARKServerManager/Globalization/ru-RU/ru-RU.xaml b/src/ARKServerManager/Globalization/ru-RU/ru-RU.xaml
index 63d3f224..c4328ce3 100644
--- a/src/ARKServerManager/Globalization/ru-RU/ru-RU.xaml
+++ b/src/ARKServerManager/Globalization/ru-RU/ru-RU.xaml
@@ -9,7 +9,7 @@
Последнее обновление:
- 09.12.2021 от Varlonec, Эдван
+ 16.12.2021 от Varlonec, Эдван
Ошибка
@@ -24,6 +24,7 @@
Genesis: Part 1
Crystal Isles
Genesis: Part 2
+ Lost Island
@@ -56,6 +57,7 @@
Genesis: Part 1
Crystal Isles
Genesis: Part 2
+ Lost Island
PGM
@@ -87,6 +89,15 @@
По максимуму
+
+ Критично
+ Ошибка
+ Внимание
+ Информация
+ Многословный
+ Отладка
+
+
Запустить в режиме Администратора.
Это приложение требует Административных привилегий для доступа ко всем функциям. Вы хотите запустить как из режима Администратора?
@@ -125,6 +136,7 @@
Загрузка сервера завершена
Завершено
Отменено
+ Ошибка
Отмена
@@ -619,8 +631,15 @@
Идентификатор сервера Discord, который бот будет слушать.
Префикс:
Префикс, который необходимо использовать при отправке команды через Discord.
+ Лог уровня:
Получить токен ...
Помощь...
+ Белый лист бота
+ Бот ID
+ ID бота для внесения в белый список.
+ Добавить в белый лист
+ Очистить белый лист
+ Удалить белый лист
Если включено, команду резервного копирования можно отправить из Discord.
Если этот параметр включен, команда перезапуска может быть отправлена из Discord.
Если включено, команду выключения можно отправить из Discord.
@@ -1205,6 +1224,8 @@
Детали бота Discord
Канал Id:
ID канала сервера Discord, который будет слушать этот профиль.
+ Псевдоним:
+ Вместо идентификатора профиля можно использовать уникальное имя для идентификации вашего сервера при использовании команд discord.
Разрешить Бекап
Если этот параметр включен, профиль будет прослушивать команды Бекапа от Discord.
Разрешить Перезагрузку
@@ -1255,7 +1276,7 @@
Увеличение множителя позволяет размещать структуры дальше от края платформы.
Макс количество ворот на седлах-платформах
Ограничивает количество ворот, которые можно разместить на седлах-платформах. Этот вариант не имеет обратной силы, поэтому применение этого изменения потребует некоторой ручной административной работы, чтобы очистить все существующие платформы, превышающие лимит.
-
+
Включить перераспределение сложности
Если включено, это позволит изменить максимальный уровень существ в мире.
Максимальный уровень динозавров:
@@ -1264,7 +1285,7 @@
Определяет максимальные уровни существ в мире. Чем выше значение, тем выше максимальный уровень существа.
Destroy Tames Over Level:
Tames that exceed this level will be deleted on server start. To disable deletion set to 0.
-
+
Вкл загрузку из данных кластера
Если включено, это позволит загружать выживших/предметов/динозавров на сервер.
Откл загрузку выживших на сервер
@@ -5678,6 +5699,7 @@
Для команды '{0}' требуется идентификатор профиля.
Профиль '{0}' не найден или не связан с каналом.
+ В канале было обнаружено несколько профилей с "{0}", команда прервана.
Профиль '{0}' находится в состоянии '{1}', и эта команда не может быть запущена.
Профиль '{0}' в настоящее время обновляется.
diff --git a/src/ARKServerManager/Globalization/zh-CN/zh-CN.xaml b/src/ARKServerManager/Globalization/zh-CN/zh-CN.xaml
index 8a40b837..db610027 100644
--- a/src/ARKServerManager/Globalization/zh-CN/zh-CN.xaml
+++ b/src/ARKServerManager/Globalization/zh-CN/zh-CN.xaml
@@ -9,7 +9,7 @@
翻译:
- 2021.12.09(龍柒)
+ 2021.12.13(龍柒)
错误
@@ -24,6 +24,7 @@
创世纪 1(Genesis: Part 1)
创世纪 2(Genesis: Part 2)
水晶岛(Crystal Isles)
+ 迷失岛(Lost Island)
@@ -57,6 +58,7 @@
创世纪 2(Genesis: Part 2)
水晶岛(Crystal Isles)
程序生成地图(PGM)
+ 迷失岛(Lost Island)
瓦尔盖罗(Valguero)
@@ -103,8 +105,8 @@
选择一个数据目录
确认位置
方舟服务器管理工具将存储配置文件和steamcmd以下目录:\r\n\r\n配置文件: {0}\r\nSteamCMD: {1}\r\n\r\n这样可以吗?
- 数据目录选择错误
- 您选择的目录在服务器管理器安装文件夹中。 不建议这样做,请选择另一个文件夹。
+ 数据目录选择错误
+ 您选择的目录在服务器管理器安装文件夹中。 不建议这样做,请选择另一个文件夹。
保存配置文件失败
保存配置文件失败 {0}. {1}\n{2}
@@ -383,9 +385,9 @@
该文件无效。 它可能包含错误或格式不正确。
选择游戏数据文件
- 游戏数据
+ gamedata
游戏数据文件
- *.游戏数据
+ *.gamedata
@@ -3002,6 +3004,22 @@
罗克韦尔节点 BOSS(困难)
+
+ 阿马加龙
+ 中华大眼翼龙
+ 恐狒
+
+
+
+ BOSS-恐狒
+ BOSS-恐狒(简单)
+ BOSS-恐狒(中等)
+ BOSS-恐狒(困难)
+ 狒狒BOSS爪牙[阿马加龙]
+ 狒狒BOSS爪牙
+ 狒狒BOSS爪牙[中华大眼翼龙]
+
+
@@ -3768,6 +3786,10 @@
脊颌翼龙的鞍
+
+ 阿马加龙鞍
+
+
@@ -5236,6 +5258,16 @@
植物R-5 种子(优质生鱼肉)
+
+ 阿马加龙鞍
+ 恐狒皮肤
+ 阿马加龙尖刺
+ 恐狒BOSS战利品(迷失岛)
+ 恐狒BOSS战利品(简单)(迷失岛)
+ 恐狒BOSS战利品(中等)(迷失岛)
+ 恐狒BOSS战利品(困难)(迷失岛)
+
+
恐龙洗点卡
泰克一键解锁
@@ -5757,9 +5789,9 @@
极品飞艇(简单){任务}
极品飞艇(中等){任务}
极品飞艇(困难){任务}
- 资源包1级
- 资源包2级
- 资源包3级
+ 一等战利品箱
+ 二等战利品箱
+ 三等战利品箱
空投_白色(创世2)
空投_绿色(创世2)
@@ -5814,6 +5846,7 @@
Boss 清单 - (水晶岛)水晶女王 (简单)
Boss 清单 - (水晶岛)水晶女王 (中等)
Boss 清单 - (水晶岛)水晶女王 (困难)
+ 水晶飞龙
Boss 清单 - 喷火龙 (简单)
Boss 清单 - 喷火龙 (中等)
diff --git a/src/ARKServerManager/Lib/GameData.cs b/src/ARKServerManager/Lib/GameData.cs
index 2f0117fe..a904a434 100644
--- a/src/ARKServerManager/Lib/GameData.cs
+++ b/src/ARKServerManager/Lib/GameData.cs
@@ -52,7 +52,7 @@ namespace ServerManagerTool.Lib
items = gameData.Items.ConvertAll(item => new PrimalItem { ClassName = item.ClassName, Mod = item.Mod, KnownItem = true, Category = item.Category }).ToArray();
// resources
- resourceMultipliers = gameData.Items.Where(item => item.IsHarvestable).ToList().ConvertAll(item => new ResourceClassMultiplier { ClassName = item.ClassName, Mod = item.Mod, KnownResource = true }).ToArray();
+ resourceMultipliers = gameData.Items.Where(item => item.IsHarvestable).Select(item => new ResourceClassMultiplier { ClassName = item.ClassName, Mod = item.Mod, KnownResource = true }).ToArray();
// map spawners
gameData.MapSpawners.AddRange(userGameData.MapSpawners);
@@ -77,9 +77,9 @@ namespace ServerManagerTool.Lib
if (gameData.GameMaps.Count > 0)
{
var maps1 = gameMaps.ToList();
- maps1.AddRange(gameData.GameMaps.Where(item => !item.IsSotF).ToList().ConvertAll(item => new ComboBoxItem { ValueMember = item.ClassName, DisplayMember = item.Description }));
+ maps1.AddRange(gameData.GameMaps.Where(item => !item.IsSotF).Select(item => new ComboBoxItem { ValueMember = item.ClassName, DisplayMember = item.Description }));
var maps2 = gameMapsSotF.ToList();
- maps2.AddRange(gameData.GameMaps.Where(item => item.IsSotF).ToList().ConvertAll(item => new ComboBoxItem { ValueMember = item.ClassName, DisplayMember = item.Description }));
+ maps2.AddRange(gameData.GameMaps.Where(item => item.IsSotF).Select(item => new ComboBoxItem { ValueMember = item.ClassName, DisplayMember = item.Description }));
gameMaps = maps1.ToArray();
gameMapsSotF = maps2.ToArray();
@@ -91,9 +91,9 @@ namespace ServerManagerTool.Lib
if (gameData.TotalConversions.Count > 0)
{
var mods1 = totalConversions.ToList();
- mods1.AddRange(gameData.TotalConversions.Where(item => !item.IsSotF).ToList().ConvertAll(item => new ComboBoxItem { ValueMember = item.ClassName, DisplayMember = item.Description }));
+ mods1.AddRange(gameData.TotalConversions.Where(item => !item.IsSotF).Select(item => new ComboBoxItem { ValueMember = item.ClassName, DisplayMember = item.Description }));
var mods2 = totalConversionsSotF.ToList();
- mods2.AddRange(gameData.TotalConversions.Where(item => item.IsSotF).ToList().ConvertAll(item => new ComboBoxItem { ValueMember = item.ClassName, DisplayMember = item.Description }));
+ mods2.AddRange(gameData.TotalConversions.Where(item => item.IsSotF).Select(item => new ComboBoxItem { ValueMember = item.ClassName, DisplayMember = item.Description }));
totalConversions = mods1.ToArray();
totalConversionsSotF = mods2.ToArray();
@@ -130,9 +130,9 @@ namespace ServerManagerTool.Lib
if (gameData.Branches.Count > 0)
{
var branches1 = branches.ToList();
- branches1.AddRange(gameData.Branches.Where(item => !item.IsSotF).ToList().ConvertAll(item => new ComboBoxItem { ValueMember = item.BranchName, DisplayMember = item.Description }));
+ branches1.AddRange(gameData.Branches.Where(item => !item.IsSotF).Select(item => new ComboBoxItem { ValueMember = item.BranchName, DisplayMember = item.Description }));
var branches2 = branchesSotF.ToList();
- branches2.AddRange(gameData.Branches.Where(item => item.IsSotF).ToList().ConvertAll(item => new ComboBoxItem { ValueMember = item.BranchName, DisplayMember = item.Description }));
+ branches2.AddRange(gameData.Branches.Where(item => item.IsSotF).Select(item => new ComboBoxItem { ValueMember = item.BranchName, DisplayMember = item.Description }));
branches = branches1.ToArray();
branchesSotF = branches2.ToArray();
@@ -144,9 +144,9 @@ namespace ServerManagerTool.Lib
if (gameData.Events.Count > 0)
{
var events1 = events.ToList();
- events1.AddRange(gameData.Events.Where(item => !item.IsSotF).ToList().ConvertAll(item => new ComboBoxItem { ValueMember = item.EventName, DisplayMember = item.Description }));
+ events1.AddRange(gameData.Events.Where(item => !item.IsSotF).Select(item => new ComboBoxItem { ValueMember = item.EventName, DisplayMember = item.Description }));
var events2 = eventsSotF.ToList();
- events2.AddRange(gameData.Events.Where(item => item.IsSotF).ToList().ConvertAll(item => new ComboBoxItem { ValueMember = item.EventName, DisplayMember = item.Description }));
+ events2.AddRange(gameData.Events.Where(item => item.IsSotF).Select(item => new ComboBoxItem { ValueMember = item.EventName, DisplayMember = item.Description }));
events = events1.ToArray();
eventsSotF = events2.ToArray();
@@ -157,7 +157,7 @@ namespace ServerManagerTool.Lib
if (gameData.OfficialMods.Count > 0)
{
- ModUtils.AddOfficialMods(gameData.OfficialMods.Where(m => !string.IsNullOrWhiteSpace(m.ModId)).Select(m => m.ModId));
+ ModUtils.AddOfficialMods(gameData.OfficialMods.Where(m => !string.IsNullOrWhiteSpace(m.ModId)).Select(m => m.ModId).ToList());
}
}
diff --git a/src/ARKServerManager/Lib/Model/EngramAutoUnlock.cs b/src/ARKServerManager/Lib/Model/EngramAutoUnlock.cs
index 92c836c2..588ef774 100644
--- a/src/ARKServerManager/Lib/Model/EngramAutoUnlock.cs
+++ b/src/ARKServerManager/Lib/Model/EngramAutoUnlock.cs
@@ -17,15 +17,13 @@ namespace ServerManagerTool.Lib
public override void FromIniValues(IEnumerable iniValues)
{
- var items = iniValues?.Select(AggregateIniValue.FromINIValue).ToArray();
+ var items = iniValues?.Select(AggregateIniValue.FromINIValue);
Clear();
- var itemsToAdd = items.Where(i => !this.Any(e => e.IsEquivalent(i))).ToArray();
- AddRange(itemsToAdd);
+ AddRange(items.Where(i => !this.Any(e => e.IsEquivalent(i))));
- var itemsToUpdate = items.Where(i => this.Any(e => e.IsEquivalent(i))).ToArray();
- foreach (var item in itemsToUpdate)
+ foreach (var item in items.Where(i => this.Any(e => e.IsEquivalent(i))))
{
var e = this.FirstOrDefault(r => r.IsEquivalent(item));
e.LevelToAutoUnlock = item.LevelToAutoUnlock;
diff --git a/src/ARKServerManager/Lib/Model/EngramEntry.cs b/src/ARKServerManager/Lib/Model/EngramEntry.cs
index f446055c..611a52f3 100644
--- a/src/ARKServerManager/Lib/Model/EngramEntry.cs
+++ b/src/ARKServerManager/Lib/Model/EngramEntry.cs
@@ -18,15 +18,13 @@ namespace ServerManagerTool.Lib
public override void FromIniValues(IEnumerable iniValues)
{
- var items = iniValues?.Select(AggregateIniValue.FromINIValue).ToArray();
+ var items = iniValues?.Select(AggregateIniValue.FromINIValue);
Clear();
- var itemsToAdd = items.Where(i => !this.Any(e => e.IsEquivalent(i))).ToArray();
- AddRange(itemsToAdd);
+ AddRange(items.Where(i => !this.Any(e => e.IsEquivalent(i))));
- var itemsToUpdate = items.Where(i => this.Any(e => e.IsEquivalent(i))).ToArray();
- foreach (var item in itemsToUpdate)
+ foreach (var item in items.Where(i => this.Any(e => e.IsEquivalent(i))))
{
var e = this.FirstOrDefault(r => r.IsEquivalent(item));
e.EngramLevelRequirement = item.EngramLevelRequirement;
diff --git a/src/ARKServerManager/Lib/Model/Level.cs b/src/ARKServerManager/Lib/Model/Level.cs
index 4c243b1d..40959641 100644
--- a/src/ARKServerManager/Lib/Model/Level.cs
+++ b/src/ARKServerManager/Lib/Model/Level.cs
@@ -61,7 +61,7 @@ namespace ServerManagerTool.Lib
int index = 0;
int xpTotal = 0;
int engramTotal = 0;
- foreach (var existingLevel in this.OrderBy(l => l.XPRequired).ToArray())
+ foreach (var existingLevel in this.OrderBy(l => l.XPRequired))
{
xpTotal += existingLevel.XPRequired;
engramTotal += existingLevel.EngramPoints;
diff --git a/src/ARKServerManager/Lib/Model/NPCSpawner.cs b/src/ARKServerManager/Lib/Model/NPCSpawner.cs
index 61922efc..5784f182 100644
--- a/src/ARKServerManager/Lib/Model/NPCSpawner.cs
+++ b/src/ARKServerManager/Lib/Model/NPCSpawner.cs
@@ -6,7 +6,6 @@ using ServerManagerTool.Enums;
using ServerManagerTool.Interface;
using System;
using System.Collections.Generic;
-using System.ComponentModel;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
diff --git a/src/ARKServerManager/Lib/Model/PreventTransferOverride.cs b/src/ARKServerManager/Lib/Model/PreventTransferOverride.cs
index 29600480..ef151823 100644
--- a/src/ARKServerManager/Lib/Model/PreventTransferOverride.cs
+++ b/src/ARKServerManager/Lib/Model/PreventTransferOverride.cs
@@ -14,11 +14,9 @@ namespace ServerManagerTool.Lib
{
}
- public string[] RenderToView()
+ public IEnumerable RenderToView()
{
- List errors = new List();
-
- return errors.ToArray();
+ return new List();
}
public void RenderToModel()
diff --git a/src/ARKServerManager/Lib/Model/ResourceClassMultiplier.cs b/src/ARKServerManager/Lib/Model/ResourceClassMultiplier.cs
index b01adbde..5183d1e1 100644
--- a/src/ARKServerManager/Lib/Model/ResourceClassMultiplier.cs
+++ b/src/ARKServerManager/Lib/Model/ResourceClassMultiplier.cs
@@ -1,5 +1,4 @@
using ServerManagerTool.Common.Model;
-using ServerManagerTool.Enums;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -18,22 +17,20 @@ namespace ServerManagerTool.Lib
public override void FromIniValues(IEnumerable iniValues)
{
- var items = iniValues?.Select(AggregateIniValue.FromINIValue).ToArray();
+ var items = iniValues?.Select(AggregateIniValue.FromINIValue);
Clear();
if (this._resetFunc != null)
this.AddRange(this._resetFunc());
- var itemsToAdd = items.Where(i => !this.Any(r => r.IsEquivalent(i))).ToArray();
- AddRange(itemsToAdd);
+ AddRange(items.Where(i => !this.Any(r => r.IsEquivalent(i))));
- var itemsToUpdate = items.Where(i => this.Any(r => r.IsEquivalent(i))).ToArray();
- foreach (var item in itemsToUpdate)
+ foreach (var item in items.Where(i => this.Any(r => r.IsEquivalent(i))))
{
this.FirstOrDefault(r => r.IsEquivalent(item)).Multiplier = item.Multiplier;
}
- IsEnabled = (items.Length > 0);
+ IsEnabled = (Count > 0);
Sort(AggregateIniValue.SortKeySelector);
}
diff --git a/src/ARKServerManager/Lib/Model/StackSizeOverride.cs b/src/ARKServerManager/Lib/Model/StackSizeOverride.cs
index ea6fe876..f86af661 100644
--- a/src/ARKServerManager/Lib/Model/StackSizeOverride.cs
+++ b/src/ARKServerManager/Lib/Model/StackSizeOverride.cs
@@ -14,7 +14,7 @@ namespace ServerManagerTool.Lib
{
}
- public string[] RenderToView()
+ public IEnumerable RenderToView()
{
List errors = new List();
@@ -27,7 +27,7 @@ namespace ServerManagerTool.Lib
}
}
- return errors.ToArray();
+ return errors;
}
public void RenderToModel()
diff --git a/src/ARKServerManager/Lib/Model/SupplyCrateOverride.cs b/src/ARKServerManager/Lib/Model/SupplyCrateOverride.cs
index 16abf720..82104834 100644
--- a/src/ARKServerManager/Lib/Model/SupplyCrateOverride.cs
+++ b/src/ARKServerManager/Lib/Model/SupplyCrateOverride.cs
@@ -17,7 +17,7 @@ namespace ServerManagerTool.Lib
{
}
- public string[] RenderToView()
+ public IEnumerable RenderToView()
{
List errors = new List();
@@ -48,7 +48,7 @@ namespace ServerManagerTool.Lib
Update();
- return errors.ToArray();
+ return errors;
}
public void RenderToModel()
diff --git a/src/ARKServerManager/Lib/ServerApp.cs b/src/ARKServerManager/Lib/ServerApp.cs
index 0f433ad8..a2715ef4 100644
--- a/src/ARKServerManager/Lib/ServerApp.cs
+++ b/src/ARKServerManager/Lib/ServerApp.cs
@@ -422,6 +422,16 @@ namespace ServerManagerTool.Lib
LogProfileMessage("Starting shutdown timer...");
var minutesLeft = ShutdownInterval;
+ if (ServerProcess == ServerProcessType.Stop)
+ {
+ LogProfileMessage($"Server shutdown type is {ServerProcess}, shutdown timer cancelled.");
+ minutesLeft = 0;
+ }
+ else if (!CheckForOnlinePlayers)
+ {
+ LogProfileMessage("CheckForOnlinePlayers disabled, shutdown timer will not perform online player check.");
+ }
+
while (minutesLeft > 0)
{
if (cancellationToken.IsCancellationRequested)
@@ -442,8 +452,8 @@ namespace ServerManagerTool.Lib
{
try
{
- var playerInfo = gameServer?.GetPlayers()?.Where(p => !string.IsNullOrWhiteSpace(p.Name?.Trim())).ToList();
- var playerCount = playerInfo?.Count ?? -1;
+ var playerInfo = gameServer?.GetPlayers()?.Where(p => !string.IsNullOrWhiteSpace(p.Name?.Trim()));
+ var playerCount = playerInfo?.Count() ?? -1;
// check if anyone is logged into the server
if (playerCount <= 0)
@@ -462,7 +472,6 @@ namespace ServerManagerTool.Lib
else
{
Debug.WriteLine($"CheckForOnlinePlayers disabled, shutdown timer cancelled.");
- break;
}
var message = string.Empty;
@@ -1866,7 +1875,7 @@ namespace ServerManagerTool.Lib
comment.AppendLine($"PGM Server: {_profile.PGM_Enabled}");
comment.AppendLine($"Process: {ServerProcess}");
- ZipUtils.ZipFiles(backupFile, files.ToArray(), comment.ToString(), false);
+ ZipUtils.ZipFiles(backupFile, files, comment.ToString(), false);
LogProfileMessage($"Backup file created - {backupFile}");
}
@@ -2016,7 +2025,7 @@ namespace ServerManagerTool.Lib
comment.AppendLine($"PGM Server: {_profile.PGM_Enabled}");
comment.AppendLine($"Process: {ServerProcess}");
- ZipUtils.ZipFiles(backupFile, files.ToArray(), comment.ToString(), false);
+ ZipUtils.ZipFiles(backupFile, files, comment.ToString(), false);
LogProfileMessage($"Backed up world files - {saveFolder}");
LogProfileMessage($"Backup file created - {backupFile}");
@@ -2989,7 +2998,7 @@ namespace ServerManagerTool.Lib
if (ExitCode == EXITCODE_NORMALEXIT)
{
// get the profile associated with the branch
- var profiles = _profiles.Keys.Where(p => p.EnableAutoUpdate && p.BranchName.Equals(branch.BranchName, StringComparison.OrdinalIgnoreCase)).ToArray();
+ var profiles = _profiles.Keys.Where(p => p.EnableAutoUpdate && p.BranchName.Equals(branch.BranchName, StringComparison.OrdinalIgnoreCase));
var profileExitCodes = new ConcurrentDictionary();
if (Config.Default.AutoUpdate_ParallelUpdate)
@@ -3240,7 +3249,7 @@ namespace ServerManagerTool.Lib
if (exitCode == EXITCODE_NORMALEXIT)
{
- var branches = _profiles.Keys.Where(p => p.EnableAutoUpdate).Select(p => BranchSnapshot.Create(p)).Distinct(new BranchSnapshotComparer()).ToArray();
+ var branches = _profiles.Keys.Where(p => p.EnableAutoUpdate).Select(p => BranchSnapshot.Create(p)).Distinct(new BranchSnapshotComparer());
var exitCodes = new ConcurrentDictionary();
// update the server cache for each branch
diff --git a/src/ARKServerManager/Lib/ServerPlayers.cs b/src/ARKServerManager/Lib/ServerPlayers.cs
index bddaf25e..306c936e 100644
--- a/src/ARKServerManager/Lib/ServerPlayers.cs
+++ b/src/ARKServerManager/Lib/ServerPlayers.cs
@@ -223,7 +223,7 @@ namespace ServerManagerTool.Lib
token.ThrowIfCancellationRequested();
// remove any players that do not have a player file.
- var droppedPlayers = _players.Values.Where(p => dataContainer.Players.FirstOrDefault(pd => pd.PlayerId.Equals(p.PlayerId, StringComparison.OrdinalIgnoreCase)) == null).ToArray();
+ var droppedPlayers = _players.Values.Where(p => dataContainer.Players.FirstOrDefault(pd => pd.PlayerId.Equals(p.PlayerId, StringComparison.OrdinalIgnoreCase)) == null);
foreach (var droppedPlayer in droppedPlayers)
{
_players.TryRemove(droppedPlayer.PlayerId, out PlayerInfo player);
diff --git a/src/ARKServerManager/Lib/ServerProfile.cs b/src/ARKServerManager/Lib/ServerProfile.cs
index d8dbc0c3..09dc1038 100644
--- a/src/ARKServerManager/Lib/ServerProfile.cs
+++ b/src/ARKServerManager/Lib/ServerProfile.cs
@@ -968,6 +968,14 @@ namespace ServerManagerTool.Lib
set { SetValue(DiscordChannelIdProperty, value); }
}
+ public static readonly DependencyProperty DiscordAliasProperty = DependencyProperty.Register(nameof(DiscordAlias), typeof(string), typeof(ServerProfile), new PropertyMetadata(String.Empty));
+ [DataMember]
+ public string DiscordAlias
+ {
+ get { return (string)GetValue(DiscordAliasProperty); }
+ set { SetValue(DiscordAliasProperty, value); }
+ }
+
public static readonly DependencyProperty AllowDiscordBackupProperty = DependencyProperty.Register(nameof(AllowDiscordBackup), typeof(bool), typeof(ServerProfile), new PropertyMetadata(true));
[DataMember]
public bool AllowDiscordBackup
@@ -3473,9 +3481,7 @@ namespace ServerManagerTool.Lib
{
InstallDirectory = folder;
- LoadServerFileAdministrators();
- LoadServerFileExclusive();
- LoadServerFileWhitelisted();
+ LoadServerFiles(true, true, true);
SetupServerFilesWatcher();
}
@@ -3561,9 +3567,7 @@ namespace ServerManagerTool.Lib
settings.MutagenLevelBoostBred.Reset();
settings.PerLevelStatsMultiplier_Player.Reset();
settings.PlayerBaseStatMultipliers.Reset();
- settings.LoadServerFileAdministrators();
- settings.LoadServerFileExclusive();
- settings.LoadServerFileWhitelisted();
+ settings.LoadServerFiles(true, true, true);
settings.SetupServerFilesWatcher();
return settings;
}
@@ -3597,7 +3601,7 @@ namespace ServerManagerTool.Lib
}
}
- private static Enum[] GetExclusions()
+ private static IEnumerable GetExclusions()
{
var exclusions = new List();
@@ -3641,7 +3645,7 @@ namespace ServerManagerTool.Lib
exclusions.Add(ServerProfileCategory.SOTF);
}
- return exclusions.ToArray();
+ return exclusions;
}
private LevelList GetLevelList(LevelProgression levelProgression)
@@ -4026,7 +4030,7 @@ namespace ServerManagerTool.Lib
return profile;
}
- public static ServerProfile LoadFromINIFiles(string file, ServerProfile profile, Enum[] exclusions = null)
+ public static ServerProfile LoadFromINIFiles(string file, ServerProfile profile, IEnumerable exclusions = null)
{
if (string.IsNullOrWhiteSpace(file) || !File.Exists(file))
return null;
@@ -4140,9 +4144,7 @@ namespace ServerManagerTool.Lib
if (Config.Default.SectionPreventTransferOverridesEnabled)
profile.PreventTransferForClassNames.RenderToView();
- profile.LoadServerFileAdministrators();
- profile.LoadServerFileExclusive();
- profile.LoadServerFileWhitelisted();
+ profile.LoadServerFiles(true, true, true);
profile.SetupServerFilesWatcher();
profile._lastSaveLocation = file;
@@ -4400,7 +4402,7 @@ namespace ServerManagerTool.Lib
SaveINIFile(configDir);
}
- public void SaveINIFile(string profileIniDir, Enum[] exclusions = null)
+ public void SaveINIFile(string profileIniDir, IEnumerable exclusions = null)
{
if (exclusions == null)
exclusions = GetExclusions();
@@ -4424,7 +4426,7 @@ namespace ServerManagerTool.Lib
filteredValues.AddRange(this.PlayerLevels.ToINIValuesForEngramPoints());
}
- iniFile.WriteSection(IniFiles.Game, IniSections.Game_ShooterGameMode, filteredValues.ToArray());
+ iniFile.WriteSection(IniFiles.Game, IniSections.Game_ShooterGameMode, filteredValues);
}
public bool UpdateDirectoryPermissions()
@@ -4984,7 +4986,7 @@ namespace ServerManagerTool.Lib
var csvMapper = new CsvDinoLevelMapping();
var csvParser = new CsvParser(csvParserOptions, csvMapper);
- var result = csvParser.ReadFromFile(fileName, Encoding.ASCII).ToList();
+ var result = csvParser.ReadFromFile(fileName, Encoding.ASCII);
if (result.Any(r => !r.IsValid))
{
var error = result.First(r => r.Error != null);
@@ -5011,7 +5013,7 @@ namespace ServerManagerTool.Lib
var csvMapper = new CsvPlayerLevelMapping();
var csvParser = new CsvParser(csvParserOptions, csvMapper);
- var result = csvParser.ReadFromFile(fileName, Encoding.ASCII).ToList();
+ var result = csvParser.ReadFromFile(fileName, Encoding.ASCII);
if (result.Any(r => !r.IsValid))
{
var error = result.First(r => r.Error != null);
@@ -5762,9 +5764,9 @@ namespace ServerManagerTool.Lib
this.SetValue(AutoSavePeriodMinutesProperty, sourceProfile.AutoSavePeriodMinutes);
- this.SetValue(MOTDProperty, sourceProfile.MOTD);
- this.SetValue(MOTDDurationProperty, sourceProfile.MOTDDuration);
- this.SetNullableValue(MOTDIntervalProperty, sourceProfile.MOTDInterval);
+ //this.SetValue(MOTDProperty, sourceProfile.MOTD);
+ //this.SetValue(MOTDDurationProperty, sourceProfile.MOTDDuration);
+ //this.SetNullableValue(MOTDIntervalProperty, sourceProfile.MOTDInterval);
this.SetValue(EnableExtinctionEventProperty, sourceProfile.EnableExtinctionEvent);
this.SetValue(ExtinctionEventTimeIntervalProperty, sourceProfile.ExtinctionEventTimeInterval);
@@ -5802,7 +5804,7 @@ namespace ServerManagerTool.Lib
this.SetValue(CrossplayProperty, sourceProfile.Crossplay);
this.SetValue(EpicOnlyProperty, sourceProfile.EpicOnly);
this.SetValue(EnablePublicIPForEpicProperty, sourceProfile.EnablePublicIPForEpic);
- this.SetValue(AltSaveDirectoryNameProperty, sourceProfile.AltSaveDirectoryName);
+ //this.SetValue(AltSaveDirectoryNameProperty, sourceProfile.AltSaveDirectoryName);
this.SetValue(CrossArkClusterIdProperty, sourceProfile.CrossArkClusterId);
this.SetValue(ClusterDirOverrideProperty, sourceProfile.ClusterDirOverride);
@@ -5866,7 +5868,7 @@ namespace ServerManagerTool.Lib
this.CustomEngineSettings.Clear();
foreach (var section in sourceProfile.CustomEngineSettings)
{
- this.CustomEngineSettings.Add(section.SectionName, section.ToIniValues().ToArray());
+ this.CustomEngineSettings.Add(section.SectionName, section.ToIniValues());
}
}
@@ -5875,7 +5877,7 @@ namespace ServerManagerTool.Lib
this.CustomGameSettings.Clear();
foreach (var section in sourceProfile.CustomGameSettings)
{
- this.CustomGameSettings.Add(section.SectionName, section.ToIniValues().ToArray());
+ this.CustomGameSettings.Add(section.SectionName, section.ToIniValues());
}
}
@@ -5884,7 +5886,7 @@ namespace ServerManagerTool.Lib
this.CustomGameUserSettings.Clear();
foreach (var section in sourceProfile.CustomGameUserSettings)
{
- this.CustomGameUserSettings.Add(section.SectionName, section.ToIniValues().ToArray());
+ this.CustomGameUserSettings.Add(section.SectionName, section.ToIniValues());
}
}
@@ -6364,18 +6366,24 @@ namespace ServerManagerTool.Lib
#region Server Files
private void ServerFilesWatcher_Changed(object sender, FileSystemEventArgs e)
{
+ var adminFile = false;
+ var exclusiveFile = false;
+ var whitelistFile = false;
+
if (e.Name.Equals(Config.Default.ArkAdminFile, StringComparison.OrdinalIgnoreCase))
{
- TaskUtils.RunOnUIThreadAsync(() => LoadServerFileAdministrators()).DoNotWait();
+ adminFile = true;
}
- else if (e.Name.Equals(Config.Default.ArkExclusiveFile, StringComparison.OrdinalIgnoreCase))
+ if (e.Name.Equals(Config.Default.ArkExclusiveFile, StringComparison.OrdinalIgnoreCase))
{
- TaskUtils.RunOnUIThreadAsync(() => LoadServerFileExclusive()).DoNotWait();
+ exclusiveFile = true;
}
- else if (e.Name.Equals(Config.Default.ArkWhitelistFile, StringComparison.OrdinalIgnoreCase))
+ if (e.Name.Equals(Config.Default.ArkWhitelistFile, StringComparison.OrdinalIgnoreCase))
{
- TaskUtils.RunOnUIThreadAsync(() => LoadServerFileWhitelisted()).DoNotWait();
+ whitelistFile = true;
}
+
+ TaskUtils.RunOnUIThreadAsync(() => LoadServerFiles(adminFile, exclusiveFile, whitelistFile)).DoNotWait();
}
private void ServerFilesWatcher_Error(object sender, ErrorEventArgs e)
@@ -6447,74 +6455,76 @@ namespace ServerManagerTool.Lib
_serverFilesWatcherSaved.EnableRaisingEvents = true;
}
- public void LoadServerFileAdministrators()
+ public void LoadServerFiles(bool adminFile, bool exclusiveFile, bool whitelistFile)
{
try
{
- var list = this.ServerFilesAdmins ?? new PlayerUserList();
+ var list1 = this.ServerFilesAdmins ?? new PlayerUserList();
+ var list2 = this.ServerFilesExclusive ?? new PlayerUserList();
+ var list3 = this.ServerFilesWhitelisted ?? new PlayerUserList();
- var file = Path.Combine(InstallDirectory, Config.Default.SavedRelativePath, Config.Default.ArkAdminFile);
- if (File.Exists(file))
+ var allSteamIds = new List();
+ string[] adminSteamIds = null;
+ string[] exclusiveSteamIds = null;
+ string[] whitelistSteamIds = null;
+
+ if (adminFile)
{
- var steamIds = File.ReadAllLines(file);
- var steamUsers = SteamUtils.GetSteamUserDetails(steamIds.ToList());
-
- list = PlayerUserList.GetList(steamUsers, steamIds);
+ var file = Path.Combine(InstallDirectory, Config.Default.SavedRelativePath, Config.Default.ArkAdminFile);
+ if (File.Exists(file))
+ {
+ adminSteamIds = File.ReadAllLines(file);
+ allSteamIds.AddRange(adminSteamIds);
+ }
}
- this.ServerFilesAdmins = list;
+ if (exclusiveFile)
+ {
+ var file = Path.Combine(InstallDirectory, Config.Default.ServerBinaryRelativePath, Config.Default.ArkExclusiveFile);
+ if (File.Exists(file))
+ {
+ exclusiveSteamIds = File.ReadAllLines(file);
+ allSteamIds.AddRange(exclusiveSteamIds);
+ }
+ }
+
+ if (whitelistFile)
+ {
+ var file = Path.Combine(InstallDirectory, Config.Default.ServerBinaryRelativePath, Config.Default.ArkWhitelistFile);
+ if (File.Exists(file))
+ {
+ whitelistSteamIds = File.ReadAllLines(file);
+ allSteamIds.AddRange(whitelistSteamIds);
+ }
+ }
+
+ // remove all duplicates
+ allSteamIds = allSteamIds.Distinct().ToList();
+
+ // fetch the details of all steam users in the list
+ var steamUsers = SteamUtils.GetSteamUserDetails(allSteamIds);
+
+ if (adminFile && adminSteamIds != null)
+ {
+ list1 = PlayerUserList.GetList(steamUsers, adminSteamIds);
+ }
+
+ if (exclusiveFile && exclusiveSteamIds != null)
+ {
+ list2 = PlayerUserList.GetList(steamUsers, exclusiveSteamIds);
+ }
+
+ if (whitelistFile && whitelistSteamIds != null)
+ {
+ list3 = PlayerUserList.GetList(steamUsers, whitelistSteamIds);
+ }
+
+ this.ServerFilesAdmins = list1;
+ this.ServerFilesExclusive = list2;
+ this.ServerFilesWhitelisted = list3;
}
catch (Exception ex)
{
- this.ServerFilesAdmins = new PlayerUserList();
- MessageBox.Show(ex.Message, _globalizer.GetResourceString("ServerSettings_ServerFilesLoadErrorTitle"), MessageBoxButton.OK, MessageBoxImage.Error);
- }
- }
-
- public void LoadServerFileExclusive()
- {
- try
- {
- var list = this.ServerFilesExclusive ?? new PlayerUserList();
-
- var file = Path.Combine(InstallDirectory, Config.Default.ServerBinaryRelativePath, Config.Default.ArkExclusiveFile);
- if (File.Exists(file))
- {
- var steamIds = File.ReadAllLines(file);
- var steamUsers = SteamUtils.GetSteamUserDetails(steamIds.ToList());
-
- list = PlayerUserList.GetList(steamUsers, steamIds);
- }
-
- this.ServerFilesExclusive = list;
- }
- catch (Exception ex)
- {
- this.ServerFilesExclusive = new PlayerUserList();
- MessageBox.Show(ex.Message, _globalizer.GetResourceString("ServerSettings_ServerFilesLoadErrorTitle"), MessageBoxButton.OK, MessageBoxImage.Error);
- }
- }
-
- public void LoadServerFileWhitelisted()
- {
- try
- {
- var list = this.ServerFilesWhitelisted ?? new PlayerUserList();
-
- var file = Path.Combine(InstallDirectory, Config.Default.ServerBinaryRelativePath, Config.Default.ArkWhitelistFile);
- if (File.Exists(file))
- {
- var steamIds = File.ReadAllLines(file);
- var steamUsers = SteamUtils.GetSteamUserDetails(steamIds.ToList());
-
- list = PlayerUserList.GetList(steamUsers, steamIds);
- }
-
- this.ServerFilesWhitelisted = list;
- }
- catch (Exception ex)
- {
- this.ServerFilesWhitelisted = new PlayerUserList();
MessageBox.Show(ex.Message, _globalizer.GetResourceString("ServerSettings_ServerFilesLoadErrorTitle"), MessageBoxButton.OK, MessageBoxImage.Error);
}
}
@@ -6528,7 +6538,7 @@ namespace ServerManagerTool.Lib
Directory.CreateDirectory(folder);
var file = Path.Combine(folder, Config.Default.ArkAdminFile);
- File.WriteAllLines(file, this.ServerFilesAdmins.ToArray());
+ File.WriteAllLines(file, this.ServerFilesAdmins.ToEnumerable());
}
catch (Exception ex)
{
@@ -6545,7 +6555,7 @@ namespace ServerManagerTool.Lib
Directory.CreateDirectory(folder);
var file = Path.Combine(folder, Config.Default.ArkExclusiveFile);
- File.WriteAllLines(file, this.ServerFilesExclusive.ToArray());
+ File.WriteAllLines(file, this.ServerFilesExclusive.ToEnumerable());
}
catch (Exception ex)
{
@@ -6562,7 +6572,7 @@ namespace ServerManagerTool.Lib
Directory.CreateDirectory(folder);
var file = Path.Combine(folder, Config.Default.ArkWhitelistFile);
- File.WriteAllLines(file, this.ServerFilesWhitelisted.ToArray());
+ File.WriteAllLines(file, this.ServerFilesWhitelisted.ToEnumerable());
}
catch (Exception ex)
{
diff --git a/src/ARKServerManager/Lib/ServerProfileSnapshot.cs b/src/ARKServerManager/Lib/ServerProfileSnapshot.cs
index 0d2238ec..2a02fbe2 100644
--- a/src/ARKServerManager/Lib/ServerProfileSnapshot.cs
+++ b/src/ARKServerManager/Lib/ServerProfileSnapshot.cs
@@ -29,7 +29,7 @@ namespace ServerManagerTool.Lib
public string ServerMap;
public string ServerMapModId;
public string TotalConversionModId;
- public List ServerModIds;
+ public IEnumerable ServerModIds;
public string MOTD;
public int MotDDuration;
public bool MOTDIntervalEnabled;
diff --git a/src/ARKServerManager/Lib/ServerRCON.cs b/src/ARKServerManager/Lib/ServerRCON.cs
index e64b4bd3..5a86d427 100644
--- a/src/ARKServerManager/Lib/ServerRCON.cs
+++ b/src/ARKServerManager/Lib/ServerRCON.cs
@@ -1,5 +1,6 @@
using ArkData;
using NLog;
+using ServerManagerTool.Common.Extensions;
using ServerManagerTool.Common.Interfaces;
using ServerManagerTool.Common.Lib;
using ServerManagerTool.Common.Model;
@@ -325,8 +326,8 @@ namespace ServerManagerTool.Lib
else if (command.command.Equals(RCON_COMMAND_GETCHAT, StringComparison.OrdinalIgnoreCase))
{
// TODO: Extract the player name from the chat
- var lines = command.lines.Where(l => !String.IsNullOrEmpty(l) && l != NoResponseOutput).ToArray();
- if (lines.Length == 0 && command.suppressCommand)
+ var lines = command.lines.Where(l => !string.IsNullOrEmpty(l) && l != NoResponseOutput);
+ if (lines.IsEmpty() && command.suppressCommand)
{
command.suppressOutput = true;
}
@@ -398,7 +399,7 @@ namespace ServerManagerTool.Lib
}
}
- var droppedPlayers = this.players.Values.Where(p => onlinePlayers.FirstOrDefault(np => np.PlayerId.Equals(p.PlayerId, StringComparison.OrdinalIgnoreCase)) == null).ToArray();
+ var droppedPlayers = this.players.Values.Where(p => onlinePlayers.FirstOrDefault(np => np.PlayerId.Equals(p.PlayerId, StringComparison.OrdinalIgnoreCase)) == null);
foreach (var droppedPlayer in droppedPlayers)
{
if (droppedPlayer.IsOnline)
@@ -604,7 +605,7 @@ namespace ServerManagerTool.Lib
token.ThrowIfCancellationRequested();
// remove any players that do not have a player file.
- var droppedPlayers = this.players.Values.Where(p => dataContainer.Players.FirstOrDefault(pd => pd.PlayerId.Equals(p.PlayerId, StringComparison.OrdinalIgnoreCase)) == null).ToArray();
+ var droppedPlayers = this.players.Values.Where(p => dataContainer.Players.FirstOrDefault(pd => pd.PlayerId.Equals(p.PlayerId, StringComparison.OrdinalIgnoreCase)) == null);
foreach (var droppedPlayer in droppedPlayers)
{
players.TryRemove(droppedPlayer.PlayerId, out PlayerInfo player);
diff --git a/src/ARKServerManager/Lib/ViewModel/DinoSettingsList.cs b/src/ARKServerManager/Lib/ViewModel/DinoSettingsList.cs
index c132fb8e..fc8ce102 100644
--- a/src/ARKServerManager/Lib/ViewModel/DinoSettingsList.cs
+++ b/src/ARKServerManager/Lib/ViewModel/DinoSettingsList.cs
@@ -87,20 +87,24 @@ namespace ServerManagerTool.Lib.ViewModel
{
Reset();
- foreach(var entry in this.DinoSpawnWeightMultipliers)
+ foreach(var entry in this.DinoSpawnWeightMultipliers.Where(e => !string.IsNullOrWhiteSpace(e.DinoNameTag)))
{
- if (string.IsNullOrWhiteSpace(entry.DinoNameTag))
- continue;
-
- var dinoSettings = this.Where(vi => vi.NameTag == entry.DinoNameTag).ToArray();
- if (dinoSettings == null || dinoSettings.Length == 0)
+ if (this.Any(d => d.NameTag == entry.DinoNameTag))
{
- this.Add(CreateDinoSetting(entry.DinoNameTag, entry.Mod, entry.KnownDino, true, false));
+ foreach (var dinoSetting in this.Where(d => d.NameTag == entry.DinoNameTag))
+ {
+ dinoSetting.SpawnWeightMultiplier = entry.SpawnWeightMultiplier;
+ dinoSetting.OverrideSpawnLimitPercentage = entry.OverrideSpawnLimitPercentage;
+ dinoSetting.SpawnLimitPercentage = entry.SpawnLimitPercentage;
+
+ dinoSetting.OriginalSpawnWeightMultiplier = entry.SpawnWeightMultiplier;
+ dinoSetting.OriginalOverrideSpawnLimitPercentage = entry.OverrideSpawnLimitPercentage;
+ dinoSetting.OriginalSpawnLimitPercentage = entry.SpawnLimitPercentage;
+ }
}
-
- dinoSettings = this.Where(vi => vi.NameTag == entry.DinoNameTag).ToArray();
- foreach (var dinoSetting in dinoSettings)
+ else
{
+ var dinoSetting = CreateDinoSetting(entry.DinoNameTag, entry.Mod, entry.KnownDino, true, false);
dinoSetting.SpawnWeightMultiplier = entry.SpawnWeightMultiplier;
dinoSetting.OverrideSpawnLimitPercentage = entry.OverrideSpawnLimitPercentage;
dinoSetting.SpawnLimitPercentage = entry.SpawnLimitPercentage;
@@ -108,115 +112,118 @@ namespace ServerManagerTool.Lib.ViewModel
dinoSetting.OriginalSpawnWeightMultiplier = entry.SpawnWeightMultiplier;
dinoSetting.OriginalOverrideSpawnLimitPercentage = entry.OverrideSpawnLimitPercentage;
dinoSetting.OriginalSpawnLimitPercentage = entry.SpawnLimitPercentage;
+
+ this.Add(dinoSetting);
}
}
- foreach(var entry in this.PreventDinoTameClassNames)
+ foreach(var entry in this.PreventDinoTameClassNames.Where(e => !string.IsNullOrWhiteSpace(e)))
{
- if (string.IsNullOrWhiteSpace(entry))
- continue;
-
- var dinoSettings = this.Where(vi => vi.ClassName == entry).ToArray();
- if (dinoSettings == null || dinoSettings.Length == 0)
+ if (this.Any(d => d.ClassName == entry))
{
- this.Add(CreateDinoSetting(entry, GameData.MOD_UNKNOWN, false, false, true));
+ foreach (var dinoSetting in this.Where(d => d.ClassName == entry && !d.CanTame))
+ {
+ dinoSetting.CanTame = false;
+ }
}
-
- dinoSettings = this.Where(vi => vi.ClassName == entry).ToArray();
- foreach (var dinoSetting in dinoSettings)
+ else
{
+ var dinoSetting = CreateDinoSetting(entry, GameData.MOD_UNKNOWN, false, false, true);
dinoSetting.CanTame = false;
+
+ this.Add(dinoSetting);
}
}
- foreach(var entry in this.NpcReplacements)
+ foreach(var entry in this.NpcReplacements.Where(e => !string.IsNullOrWhiteSpace(e.FromClassName)))
{
- if (string.IsNullOrWhiteSpace(entry.FromClassName))
- continue;
-
- var dinoSettings = this.Where(vi => vi.ClassName == entry.FromClassName).ToArray();
- if (dinoSettings == null || dinoSettings.Length == 0)
+ if (this.Any(d => d.ClassName == entry.FromClassName))
{
- this.Add(CreateDinoSetting(entry.FromClassName, GameData.MOD_UNKNOWN, false, false, true));
+ foreach (var dinoSetting in this.Where(d => d.ClassName == entry.FromClassName))
+ {
+ dinoSetting.CanSpawn = !string.IsNullOrWhiteSpace(entry.ToClassName);
+ dinoSetting.ReplacementClass = dinoSetting.CanSpawn ? entry.ToClassName : dinoSetting.ClassName;
+ }
}
-
- dinoSettings = this.Where(vi => vi.ClassName == entry.FromClassName).ToArray();
- foreach (var dinoSetting in dinoSettings)
+ else
{
+ var dinoSetting = CreateDinoSetting(entry.FromClassName, GameData.MOD_UNKNOWN, false, false, true);
dinoSetting.CanSpawn = !string.IsNullOrWhiteSpace(entry.ToClassName);
dinoSetting.ReplacementClass = dinoSetting.CanSpawn ? entry.ToClassName : dinoSetting.ClassName;
+
+ this.Add(dinoSetting);
}
}
- foreach (var entry in this.TamedDinoClassDamageMultipliers)
+ foreach (var entry in this.TamedDinoClassDamageMultipliers.Where(e => !string.IsNullOrWhiteSpace(e.ClassName)))
{
- if (string.IsNullOrWhiteSpace(entry.ClassName))
- continue;
-
- var dinoSettings = this.Where(vi => vi.ClassName == entry.ClassName).ToArray();
- if (dinoSettings == null || dinoSettings.Length == 0)
+ if (this.Any(d => d.ClassName == entry.ClassName))
{
- this.Add(CreateDinoSetting(entry.ClassName, GameData.MOD_UNKNOWN, false, false, true));
+ foreach (var dinoSetting in this.Where(d => d.ClassName == entry.ClassName && d.TamedDamageMultiplier != entry.Multiplier))
+ {
+ dinoSetting.TamedDamageMultiplier = entry.Multiplier;
+ }
}
-
- dinoSettings = this.Where(vi => vi.ClassName == entry.ClassName).ToArray();
- foreach (var dinoSetting in dinoSettings)
+ else
{
+ var dinoSetting = CreateDinoSetting(entry.ClassName, GameData.MOD_UNKNOWN, false, false, true);
dinoSetting.TamedDamageMultiplier = entry.Multiplier;
+
+ this.Add(dinoSetting);
}
}
- foreach(var entry in this.TamedDinoClassResistanceMultipliers)
+ foreach(var entry in this.TamedDinoClassResistanceMultipliers.Where(e => !string.IsNullOrWhiteSpace(e.ClassName)))
{
- if (string.IsNullOrWhiteSpace(entry.ClassName))
- continue;
-
- var dinoSettings = this.Where(vi => vi.ClassName == entry.ClassName).ToArray();
- if (dinoSettings == null || dinoSettings.Length == 0)
+ if (this.Any(d => d.ClassName == entry.ClassName))
{
- this.Add(CreateDinoSetting(entry.ClassName, GameData.MOD_UNKNOWN, false, false, true));
+ foreach (var dinoSetting in this.Where(d => d.ClassName == entry.ClassName && d.TamedResistanceMultiplier != entry.Multiplier))
+ {
+ dinoSetting.TamedResistanceMultiplier = entry.Multiplier;
+ }
}
-
- dinoSettings = this.Where(vi => vi.ClassName == entry.ClassName).ToArray();
- foreach (var dinoSetting in dinoSettings)
+ else
{
+ var dinoSetting = CreateDinoSetting(entry.ClassName, GameData.MOD_UNKNOWN, false, false, true);
dinoSetting.TamedResistanceMultiplier = entry.Multiplier;
+
+ this.Add(dinoSetting);
}
}
- foreach (var entry in this.DinoClassDamageMultipliers)
+ foreach (var entry in this.DinoClassDamageMultipliers.Where(e => !string.IsNullOrWhiteSpace(e.ClassName)))
{
- if (string.IsNullOrWhiteSpace(entry.ClassName))
- continue;
-
- var dinoSettings = this.Where(vi => vi.ClassName == entry.ClassName).ToArray();
- if (dinoSettings == null || dinoSettings.Length == 0)
+ if (this.Any(d => d.ClassName == entry.ClassName))
{
- this.Add(CreateDinoSetting(entry.ClassName, GameData.MOD_UNKNOWN, false, false, true));
+ foreach (var dinoSetting in this.Where(d => d.ClassName == entry.ClassName && d.WildDamageMultiplier != entry.Multiplier))
+ {
+ dinoSetting.WildDamageMultiplier = entry.Multiplier;
+ }
}
-
- dinoSettings = this.Where(vi => vi.ClassName == entry.ClassName).ToArray();
- foreach (var dinoSetting in dinoSettings)
+ else
{
+ var dinoSetting = CreateDinoSetting(entry.ClassName, GameData.MOD_UNKNOWN, false, false, true);
dinoSetting.WildDamageMultiplier = entry.Multiplier;
+
+ this.Add(dinoSetting);
}
}
- foreach (var entry in this.DinoClassResistanceMultipliers)
+ foreach (var entry in this.DinoClassResistanceMultipliers.Where(e => !string.IsNullOrWhiteSpace(e.ClassName)))
{
- if (string.IsNullOrWhiteSpace(entry.ClassName))
- continue;
-
- var dinoSettings = this.Where(vi => vi.ClassName == entry.ClassName).ToArray();
- if (dinoSettings == null || dinoSettings.Length == 0)
+ if (this.Any(d => d.ClassName == entry.ClassName))
{
- this.Add(CreateDinoSetting(entry.ClassName, GameData.MOD_UNKNOWN, false, false, true));
+ foreach (var dinoSetting in this.Where(d => d.ClassName == entry.ClassName && d.WildResistanceMultiplier != entry.Multiplier))
+ {
+ dinoSetting.WildResistanceMultiplier = entry.Multiplier;
+ }
}
-
- dinoSettings = this.Where(vi => vi.ClassName == entry.ClassName).ToArray();
- foreach (var dinoSetting in dinoSettings)
+ else
{
+ var dinoSetting = CreateDinoSetting(entry.ClassName, GameData.MOD_UNKNOWN, false, false, true);
dinoSetting.WildResistanceMultiplier = entry.Multiplier;
+
+ this.Add(dinoSetting);
}
}
@@ -244,22 +251,9 @@ namespace ServerManagerTool.Lib.ViewModel
!entry.SpawnLimitPercentage.Equals(DinoSpawn.DEFAULT_SPAWN_LIMIT_PERCENTAGE) ||
!entry.SpawnWeightMultiplier.Equals(DinoSpawn.DEFAULT_SPAWN_WEIGHT_MULTIPLIER))
{
-
- var dinoSpawns = this.DinoSpawnWeightMultipliers.Where(d => d.DinoNameTag.Equals(entry.NameTag, StringComparison.OrdinalIgnoreCase)).ToArray();
- if (dinoSpawns == null || dinoSpawns.Length == 0)
+ if (this.DinoSpawnWeightMultipliers.Any(d => d.DinoNameTag.Equals(entry.NameTag, StringComparison.OrdinalIgnoreCase)))
{
- this.DinoSpawnWeightMultipliers.Add(new DinoSpawn()
- {
- ClassName = entry.ClassName,
- DinoNameTag = entry.NameTag,
- OverrideSpawnLimitPercentage = entry.OverrideSpawnLimitPercentage,
- SpawnLimitPercentage = entry.SpawnLimitPercentage,
- SpawnWeightMultiplier = entry.SpawnWeightMultiplier
- });
- }
- else
- {
- foreach (var dinoSpawn in dinoSpawns)
+ foreach (var dinoSpawn in this.DinoSpawnWeightMultipliers.Where(d => d.DinoNameTag.Equals(entry.NameTag, StringComparison.OrdinalIgnoreCase)))
{
if (entry.SpawnWeightMultiplier != entry.OriginalSpawnWeightMultiplier ||
entry.OverrideSpawnLimitPercentage != entry.OriginalOverrideSpawnLimitPercentage ||
@@ -271,6 +265,17 @@ namespace ServerManagerTool.Lib.ViewModel
}
}
}
+ else
+ {
+ this.DinoSpawnWeightMultipliers.Add(new DinoSpawn()
+ {
+ ClassName = entry.ClassName,
+ DinoNameTag = entry.NameTag,
+ OverrideSpawnLimitPercentage = entry.OverrideSpawnLimitPercentage,
+ SpawnLimitPercentage = entry.SpawnLimitPercentage,
+ SpawnWeightMultiplier = entry.SpawnWeightMultiplier
+ });
+ }
}
}
@@ -287,20 +292,28 @@ namespace ServerManagerTool.Lib.ViewModel
{
// check if the value has changed.
if (!entry.TamedDamageMultiplier.Equals(ClassMultiplier.DEFAULT_MULTIPLIER))
+ {
this.TamedDinoClassDamageMultipliers.Add(new ClassMultiplier() { ClassName = entry.ClassName, Multiplier = entry.TamedDamageMultiplier });
+ }
// check if the value has changed.
if (!entry.TamedResistanceMultiplier.Equals(ClassMultiplier.DEFAULT_MULTIPLIER))
+ {
this.TamedDinoClassResistanceMultipliers.Add(new ClassMultiplier() { ClassName = entry.ClassName, Multiplier = entry.TamedResistanceMultiplier });
+ }
}
// check if the value has changed.
if (!entry.WildDamageMultiplier.Equals(ClassMultiplier.DEFAULT_MULTIPLIER))
+ {
this.DinoClassDamageMultipliers.Add(new ClassMultiplier() { ClassName = entry.ClassName, Multiplier = entry.WildDamageMultiplier });
+ }
// check if the value has changed.
if (!entry.WildResistanceMultiplier.Equals(ClassMultiplier.DEFAULT_MULTIPLIER))
+ {
this.DinoClassResistanceMultipliers.Add(new ClassMultiplier() { ClassName = entry.ClassName, Multiplier = entry.WildResistanceMultiplier });
+ }
}
}
}
diff --git a/src/ARKServerManager/Lib/ViewModel/EngramSettings.cs b/src/ARKServerManager/Lib/ViewModel/EngramSettings.cs
index df4620f4..56eca10d 100644
--- a/src/ARKServerManager/Lib/ViewModel/EngramSettings.cs
+++ b/src/ARKServerManager/Lib/ViewModel/EngramSettings.cs
@@ -80,14 +80,13 @@ namespace ServerManagerTool.Lib.ViewModel
if (string.IsNullOrWhiteSpace(entry.EngramClassName))
continue;
- var engramSettings = this.Where(vi => vi.EngramClassName == entry.EngramClassName).ToArray();
- if (engramSettings == null || engramSettings.Length == 0)
+ if (!this.Any(vi => vi.EngramClassName == entry.EngramClassName))
{
var engram = GameData.GetEngramForClass(entry.EngramClassName);
this.Add(CreateEngramSetting(entry.EngramClassName, engram?.Mod ?? GameData.MOD_UNKNOWN, engram?.KnownEngram ?? false, engram?.IsTekgram ?? false));
}
- engramSettings = this.Where(vi => vi.EngramClassName == entry.EngramClassName).ToArray();
+ var engramSettings = this.Where(vi => vi.EngramClassName == entry.EngramClassName);
foreach (var engramSetting in engramSettings)
{
engramSetting.EngramLevelRequirement = entry.EngramLevelRequirement;
@@ -117,14 +116,13 @@ namespace ServerManagerTool.Lib.ViewModel
if (string.IsNullOrWhiteSpace(entry.EngramClassName))
continue;
- var engramSettings = this.Where(vi => vi.EngramClassName == entry.EngramClassName).ToArray();
- if (engramSettings == null || engramSettings.Length == 0)
+ if (!this.Any(vi => vi.EngramClassName == entry.EngramClassName))
{
var engram = GameData.GetEngramForClass(entry.EngramClassName);
this.Add(CreateEngramSetting(entry.EngramClassName, engram?.Mod ?? GameData.MOD_UNKNOWN, engram?.KnownEngram ?? false, engram?.IsTekgram ?? false));
}
- engramSettings = this.Where(vi => vi.EngramClassName == entry.EngramClassName).ToArray();
+ var engramSettings = this.Where(vi => vi.EngramClassName == entry.EngramClassName);
foreach (var engramSetting in engramSettings)
{
engramSetting.EngramAutoUnlock = true;
diff --git a/src/ARKServerManager/UserControls/GlobalSettingsControl.xaml b/src/ARKServerManager/UserControls/GlobalSettingsControl.xaml
index 6919def4..b82088fc 100644
--- a/src/ARKServerManager/UserControls/GlobalSettingsControl.xaml
+++ b/src/ARKServerManager/UserControls/GlobalSettingsControl.xaml
@@ -60,22 +60,22 @@
-
+
-
-
+
+
-
-
+
+
-
+
-
+
@@ -141,24 +141,24 @@
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -651,22 +707,22 @@
-
+
-
-
+
+
-
+
-
+
-
-
+
+
-
+
-
+
@@ -688,10 +744,10 @@
-
-
-
-
+
+
+
+
@@ -715,16 +771,16 @@
-
-
+
+
-
-
+
+
-
+
-
+
diff --git a/src/ARKServerManager/UserControls/GlobalSettingsControl.xaml.cs b/src/ARKServerManager/UserControls/GlobalSettingsControl.xaml.cs
index 9dd9dc78..87297eea 100644
--- a/src/ARKServerManager/UserControls/GlobalSettingsControl.xaml.cs
+++ b/src/ARKServerManager/UserControls/GlobalSettingsControl.xaml.cs
@@ -5,13 +5,16 @@ using ServerManagerTool.Common.Lib;
using ServerManagerTool.Common.Model;
using ServerManagerTool.Common.Utils;
using System;
+using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
+using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
+using System.Windows.Data;
using System.Windows.Input;
using System.Xml;
using WPFSharp.Globalizer;
@@ -24,27 +27,46 @@ namespace ServerManagerTool
public partial class GlobalSettingsControl : UserControl
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
- private GlobalizedApplication _globalizer = GlobalizedApplication.Instance;
+ private readonly GlobalizedApplication _globalizer = GlobalizedApplication.Instance;
+ public static readonly DependencyProperty AppInstanceProperty = DependencyProperty.Register(nameof(AppInstance), typeof(App), typeof(GlobalSettingsControl), new PropertyMetadata(null));
public static readonly DependencyProperty IsAdministratorProperty = DependencyProperty.Register(nameof(IsAdministrator), typeof(bool), typeof(GlobalSettingsControl), new PropertyMetadata(false));
- public static readonly DependencyProperty CurrentConfigProperty = DependencyProperty.Register(nameof(CurrentConfig), typeof(Config), typeof(GlobalSettingsControl), new PropertyMetadata(null));
+ public static readonly DependencyProperty ConfigProperty = DependencyProperty.Register(nameof(Config), typeof(Config), typeof(GlobalSettingsControl), new PropertyMetadata(null));
public static readonly DependencyProperty CommonConfigProperty = DependencyProperty.Register(nameof(CommonConfig), typeof(CommonConfig), typeof(GlobalSettingsControl), new PropertyMetadata(null));
public static readonly DependencyProperty WindowStatesProperty = DependencyProperty.Register(nameof(WindowStates), typeof(ComboBoxItemList), typeof(GlobalSettingsControl), new PropertyMetadata(null));
+ public static readonly DependencyProperty DiscordBotLogLevelsProperty = DependencyProperty.Register(nameof(DiscordBotLogLevels), typeof(ComboBoxItemList), typeof(GlobalSettingsControl), new PropertyMetadata(null));
+ public static readonly DependencyProperty DiscordBotWhitelistProperty = DependencyProperty.Register(nameof(DiscordBotWhitelist), typeof(List), typeof(GlobalSettingsControl), new PropertyMetadata(null));
public GlobalSettingsControl()
{
- this.Version = GetDeployedVersion();
-
- this.CurrentConfig = Config.Default;
+ this.AppInstance = App.Instance;
+ this.Config = Config.Default;
this.CommonConfig = CommonConfig.Default;
- this.DataContext = this;
-
- PopulateWindowsStatesComboBox();
+ this.IsAdministrator = SecurityUtils.IsAdministrator();
+ this.Version = GetDeployedVersion();
InitializeComponent();
WindowUtils.RemoveDefaultResourceDictionary(this, Config.Default.DefaultGlobalizationFile);
- this.IsAdministrator = SecurityUtils.IsAdministrator();
+ PopulateWindowsStatesComboBox();
+ PopulateDiscordBotLogLevelsComboBox();
+
+ DiscordBotWhitelist = new List();
+ if (Config.DiscordBotWhitelist != null)
+ {
+ foreach (var item in Config.DiscordBotWhitelist)
+ {
+ DiscordBotWhitelist.Add(new DiscordBotWhitelist() { BotId = item });
+ }
+ }
+
+ this.DataContext = this;
+ }
+
+ public App AppInstance
+ {
+ get { return GetValue(AppInstanceProperty) as App; }
+ set { SetValue(AppInstanceProperty, value); }
}
public string Version
@@ -53,10 +75,10 @@ namespace ServerManagerTool
set;
}
- public Config CurrentConfig
+ public Config Config
{
- get { return GetValue(CurrentConfigProperty) as Config; }
- set { SetValue(CurrentConfigProperty, value); }
+ get { return GetValue(ConfigProperty) as Config; }
+ set { SetValue(ConfigProperty, value); }
}
public CommonConfig CommonConfig
@@ -77,6 +99,27 @@ namespace ServerManagerTool
set { SetValue(WindowStatesProperty, value); }
}
+ public ComboBoxItemList DiscordBotLogLevels
+ {
+ get { return (ComboBoxItemList)GetValue(DiscordBotLogLevelsProperty); }
+ set { SetValue(DiscordBotLogLevelsProperty, value); }
+ }
+
+ public List DiscordBotWhitelist
+ {
+ get { return (List)GetValue(DiscordBotWhitelistProperty); }
+ set { SetValue(DiscordBotWhitelistProperty, value); }
+ }
+
+ public void ApplyChangesToConfig()
+ {
+ if (Config.DiscordBotWhitelist is null)
+ Config.DiscordBotWhitelist = new System.Collections.Specialized.StringCollection();
+
+ Config.DiscordBotWhitelist.Clear();
+ Config.DiscordBotWhitelist.AddRange(DiscordBotWhitelist.Select(i => i.BotId).ToArray());
+ }
+
private string GetDeployedVersion()
{
XmlDocument xmlDoc = new XmlDocument();
@@ -148,14 +191,24 @@ namespace ServerManagerTool
if (result == CommonFileDialogResult.Ok)
{
- if (!String.Equals(dialog.FileName, Config.Default.DataDir))
+ if (!string.Equals(dialog.FileName, Config.Default.DataDir))
{
try
{
+ var newDataDirectory = dialog.FileName;
+ if (!string.IsNullOrWhiteSpace(newDataDirectory))
+ {
+ var root = Path.GetPathRoot(newDataDirectory);
+ if (!root.EndsWith("\\"))
+ {
+ newDataDirectory = newDataDirectory.Replace(root, root + "\\");
+ }
+ }
+
// Set up the destination directories
- string newConfigDirectory = Path.Combine(dialog.FileName, Config.Default.ProfilesDir);
+ string newConfigDirectory = Path.Combine(newDataDirectory, Config.Default.ProfilesDir);
string oldSteamDirectory = Path.Combine(Config.Default.DataDir, Config.Default.SteamCmdDir);
- string newSteamDirectory = Path.Combine(dialog.FileName, Config.Default.SteamCmdDir);
+ string newSteamDirectory = Path.Combine(newDataDirectory, Config.Default.SteamCmdDir);
Directory.CreateDirectory(newConfigDirectory);
Directory.CreateDirectory(newSteamDirectory);
@@ -189,7 +242,7 @@ namespace ServerManagerTool
Directory.Delete(oldSteamDirectory, true);
// Update the config
- Config.Default.DataDir = dialog.FileName;
+ Config.Default.DataDir = newDataDirectory;
Config.Default.ConfigDirectory = newConfigDirectory;
App.ReconfigureLogging();
}
@@ -228,9 +281,18 @@ namespace ServerManagerTool
if (result == CommonFileDialogResult.Ok)
{
- if (!String.Equals(dialog.FileName, Config.Default.BackupPath))
+ if (!string.Equals(dialog.FileName, Config.Default.BackupPath))
{
Config.Default.BackupPath = dialog.FileName;
+
+ if (!string.IsNullOrWhiteSpace(Config.Default.BackupPath))
+ {
+ var root = Path.GetPathRoot(Config.Default.BackupPath);
+ if (!root.EndsWith("\\"))
+ {
+ Config.Default.BackupPath = Config.Default.BackupPath.Replace(root, root + "\\");
+ }
+ }
}
}
}
@@ -250,9 +312,18 @@ namespace ServerManagerTool
if (result == CommonFileDialogResult.Ok)
{
- if (!String.Equals(dialog.FileName, Config.Default.AutoUpdate_CacheDir))
+ if (!string.Equals(dialog.FileName, Config.Default.AutoUpdate_CacheDir))
{
Config.Default.AutoUpdate_CacheDir = dialog.FileName;
+
+ if (!string.IsNullOrWhiteSpace(Config.Default.AutoUpdate_CacheDir))
+ {
+ var root = Path.GetPathRoot(Config.Default.AutoUpdate_CacheDir);
+ if (!root.EndsWith("\\"))
+ {
+ Config.Default.AutoUpdate_CacheDir = Config.Default.AutoUpdate_CacheDir.Replace(root, root + "\\");
+ }
+ }
}
}
}
@@ -328,16 +399,16 @@ namespace ServerManagerTool
private void LanguageSelectionComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
- CurrentConfig.CultureName = AvailableLanguages.Instance.SelectedLanguage;
+ Config.CultureName = AvailableLanguages.Instance.SelectedLanguage;
PopulateWindowsStatesComboBox();
- App.Instance.OnResourceDictionaryChanged(CurrentConfig.CultureName);
+ App.Instance.OnResourceDictionaryChanged(Config.CultureName);
}
private void StyleSelectionComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
- CurrentConfig.StyleName = AvailableStyles.Instance.SelectedStyle;
+ Config.StyleName = AvailableStyles.Instance.SelectedStyle;
}
private void HiddenField_GotFocus(object sender, RoutedEventArgs e)
@@ -419,20 +490,68 @@ namespace ServerManagerTool
private void PopulateWindowsStatesComboBox()
{
- var selectedValue = this.WindowStateComboBox?.SelectedValue ?? CurrentConfig.MainWindow_WindowState;
- var windowStates = new ComboBoxItemList();
+ var selectedValue = this.WindowStateComboBox?.SelectedValue ?? Config.MainWindow_WindowState;
+ var comboBoxList = new ComboBoxItemList();
foreach (WindowState windowState in Enum.GetValues(typeof(WindowState)))
{
var displayMember = _globalizer.GetResourceString($"WindowState_{windowState}") ?? windowState.ToString();
- windowStates.Add(new Common.Model.ComboBoxItem(windowState.ToString(), displayMember));
+ comboBoxList.Add(new Common.Model.ComboBoxItem(windowState.ToString(), displayMember));
}
- this.WindowStates = windowStates;
+ this.WindowStates = comboBoxList;
if (this.WindowStateComboBox != null)
{
this.WindowStateComboBox.SelectedValue = selectedValue;
}
}
+
+ private void PopulateDiscordBotLogLevelsComboBox()
+ {
+ var selectedValue = this.DiscordBotLogLevelComboBox?.SelectedValue ?? Config.DiscordBotLogLevel;
+ var comboBoxList = new ComboBoxItemList();
+
+ foreach (DiscordBot.Enums.LogLevel logLevel in Enum.GetValues(typeof(DiscordBot.Enums.LogLevel)))
+ {
+ var displayMember = _globalizer.GetResourceString($"DiscordBotLogLevel_{logLevel}") ?? logLevel.ToString();
+ comboBoxList.Add(new Common.Model.ComboBoxItem(logLevel.ToString(), displayMember));
+ }
+
+ this.DiscordBotLogLevels = comboBoxList;
+ if (this.DiscordBotLogLevelComboBox != null)
+ {
+ this.DiscordBotLogLevelComboBox.SelectedValue = selectedValue;
+ }
+ }
+
+ #region Discord Bot Whitelist
+ private void AddDiscordBotWhitelist_Click(object sender, RoutedEventArgs e)
+ {
+ DiscordBotWhitelist.Add(new DiscordBotWhitelist());
+
+ CollectionViewSource.GetDefaultView(DiscordBotWhitelistGrid.ItemsSource).Refresh();
+ }
+
+ private void ClearDiscordBotWhitelists_Click(object sender, RoutedEventArgs e)
+ {
+ if (MessageBox.Show(_globalizer.GetResourceString("ServerSettings_ClearLabel"), _globalizer.GetResourceString("ServerSettings_ClearTitle"), MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes)
+ return;
+
+ DiscordBotWhitelist.Clear();
+
+ CollectionViewSource.GetDefaultView(DiscordBotWhitelistGrid.ItemsSource).Refresh();
+ }
+
+ private void RemoveDiscordBotWhitelist_Click(object sender, RoutedEventArgs e)
+ {
+ if (MessageBox.Show(_globalizer.GetResourceString("ServerSettings_DeleteLabel"), _globalizer.GetResourceString("ServerSettings_DeleteTitle"), MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes)
+ return;
+
+ var item = ((DiscordBotWhitelist)((Button)e.Source).DataContext);
+ DiscordBotWhitelist.Remove(item);
+
+ CollectionViewSource.GetDefaultView(DiscordBotWhitelistGrid.ItemsSource).Refresh();
+ }
+ #endregion
}
}
diff --git a/src/ARKServerManager/UserControls/ServerSettingsControl.xaml b/src/ARKServerManager/UserControls/ServerSettingsControl.xaml
index c5475614..c55acc17 100644
--- a/src/ARKServerManager/UserControls/ServerSettingsControl.xaml
+++ b/src/ARKServerManager/UserControls/ServerSettingsControl.xaml
@@ -528,7 +528,7 @@
-
+
@@ -869,7 +869,7 @@
-
+
@@ -1395,7 +1395,7 @@
-
+
@@ -1579,7 +1579,7 @@
-
+
@@ -1618,6 +1618,9 @@
+
+
+
@@ -1628,7 +1631,7 @@
-
+
@@ -2071,7 +2074,7 @@
-
+
@@ -2118,7 +2121,7 @@
-
+
@@ -2170,7 +2173,7 @@
-
+
@@ -2283,7 +2286,7 @@
-
+
@@ -2420,7 +2423,7 @@
-
+
@@ -2729,6 +2732,9 @@
+
+
+
@@ -2976,7 +2982,7 @@
-
+
@@ -3035,7 +3041,7 @@
-
+
@@ -3121,6 +3127,9 @@
+
+
+
@@ -3162,7 +3171,7 @@
-
+
@@ -3283,7 +3292,7 @@
-
+
@@ -3312,7 +3321,7 @@
-
+
@@ -3640,6 +3649,9 @@
+
+
+
@@ -3651,7 +3663,7 @@
-
+
@@ -3675,7 +3687,7 @@
-
+
@@ -3955,7 +3967,7 @@
-
+
@@ -3978,7 +3990,7 @@
-
+
@@ -4114,7 +4126,7 @@
-
+
@@ -4137,7 +4149,7 @@
-
+
@@ -4273,7 +4285,7 @@
-
+
@@ -4296,7 +4308,7 @@
-
+
@@ -4432,7 +4444,7 @@
-
+
@@ -4464,7 +4476,7 @@
-
+
@@ -4650,7 +4662,7 @@
-
+
@@ -4680,7 +4692,7 @@
-
+
@@ -4846,7 +4858,7 @@
-
+
@@ -4876,7 +4888,7 @@
-
+
@@ -4985,7 +4997,7 @@
-
+
@@ -5014,7 +5026,7 @@
-
+
@@ -5185,7 +5197,7 @@
-
+
@@ -5215,13 +5227,13 @@
-
+
-
+
-
+
-
+
@@ -5719,7 +5731,7 @@
-
+
@@ -5749,7 +5761,7 @@
-
+
@@ -5836,7 +5848,7 @@
-
+
@@ -6128,7 +6140,7 @@
-
+
diff --git a/src/ARKServerManager/UserControls/ServerSettingsControl.xaml.cs b/src/ARKServerManager/UserControls/ServerSettingsControl.xaml.cs
index ffb9897e..a33660d6 100644
--- a/src/ARKServerManager/UserControls/ServerSettingsControl.xaml.cs
+++ b/src/ARKServerManager/UserControls/ServerSettingsControl.xaml.cs
@@ -100,7 +100,7 @@ namespace ServerManagerTool
public static readonly DependencyProperty BaseBranchesProperty = DependencyProperty.Register(nameof(BaseBranches), typeof(ComboBoxItemList), typeof(ServerSettingsControl), new PropertyMetadata(null));
public static readonly DependencyProperty BaseEventsProperty = DependencyProperty.Register(nameof(BaseEvents), typeof(ComboBoxItemList), typeof(ServerSettingsControl), new PropertyMetadata(null));
public static readonly DependencyProperty BetaVersionProperty = DependencyProperty.Register(nameof(BetaVersion), typeof(bool), typeof(ServerSettingsControl), new PropertyMetadata(false));
- public static readonly DependencyProperty CurrentConfigProperty = DependencyProperty.Register(nameof(CurrentConfig), typeof(Config), typeof(ServerSettingsControl));
+ public static readonly DependencyProperty ConfigProperty = DependencyProperty.Register(nameof(Config), typeof(Config), typeof(ServerSettingsControl));
public static readonly DependencyProperty IsAdministratorProperty = DependencyProperty.Register(nameof(IsAdministrator), typeof(bool), typeof(ServerSettingsControl), new PropertyMetadata(false));
public static readonly DependencyProperty NetworkInterfacesProperty = DependencyProperty.Register(nameof(NetworkInterfaces), typeof(List), typeof(ServerSettingsControl), new PropertyMetadata(new List()));
public static readonly DependencyProperty RuntimeProperty = DependencyProperty.Register(nameof(Runtime), typeof(ServerRuntime), typeof(ServerSettingsControl));
@@ -201,10 +201,10 @@ namespace ServerManagerTool
set { SetValue(BetaVersionProperty, value); }
}
- public Config CurrentConfig
+ public Config Config
{
- get { return GetValue(CurrentConfigProperty) as Config; }
- set { SetValue(CurrentConfigProperty, value); }
+ get { return GetValue(ConfigProperty) as Config; }
+ set { SetValue(ConfigProperty, value); }
}
public bool IsAdministrator
@@ -367,7 +367,7 @@ namespace ServerManagerTool
public ServerSettingsControl()
{
this.BetaVersion = App.Instance.BetaVersion;
- this.CurrentConfig = Config.Default;
+ this.Config = Config.Default;
this.CurrentCulture = Thread.CurrentThread.CurrentCulture;
InitializeComponent();
@@ -966,7 +966,7 @@ namespace ServerManagerTool
comment.AppendLine($"ServerUpdate_OnServerStart: {Config.Default.ServerUpdate_OnServerStart}");
comment.AppendLine($"DiscordBotEnabled: {Config.Default.DiscordBotEnabled}");
- comment.AppendLine($"HasDiscordBotToken: {string.IsNullOrWhiteSpace(Config.Default.DiscordBotToken)}");
+ comment.AppendLine($"HasDiscordBotToken: {!string.IsNullOrWhiteSpace(Config.Default.DiscordBotToken)}");
comment.AppendLine($"DiscordBotServerId: {Config.Default.DiscordBotServerId}");
comment.AppendLine($"DiscordBotPrefix: {Config.Default.DiscordBotPrefix}");
comment.AppendLine($"AllowDiscordBackup: {Config.Default.AllowDiscordBackup}");
@@ -990,7 +990,7 @@ namespace ServerManagerTool
var zipFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), this.Settings.ProfileID + ".zip");
if (File.Exists(zipFile)) File.Delete(zipFile);
- ZipUtils.ZipFiles(zipFile, files.ToArray(), comment.ToString());
+ ZipUtils.ZipFiles(zipFile, files, comment.ToString());
foreach (var kvp in obfuscateFiles)
{
ZipUtils.ZipAFile(zipFile, kvp.Key, kvp.Value);
@@ -1348,37 +1348,37 @@ namespace ServerManagerTool
foreach (var section in iniFile.Sections.Where(s => s.SectionName != null && !SystemIniFile.IniSectionNames.ContainsValue(s.SectionName)))
{
var dinoSpawnWeightMultipliers = new AggregateIniValueList(nameof(Server.Profile.DinoSpawnWeightMultipliers), null);
- dinoSpawnWeightMultipliers.FromIniValues(section.KeysToStringArray().Where(s => s.StartsWith($"{dinoSpawnWeightMultipliers.IniCollectionKey}=")));
+ dinoSpawnWeightMultipliers.FromIniValues(section.KeysToStringEnumerable().Where(s => s.StartsWith($"{dinoSpawnWeightMultipliers.IniCollectionKey}=")));
Server.Profile.DinoSpawnWeightMultipliers.AddRange(dinoSpawnWeightMultipliers);
Server.Profile.DinoSpawnWeightMultipliers.IsEnabled |= dinoSpawnWeightMultipliers.IsEnabled;
var preventDinoTameClassNames = new StringIniValueList(nameof(Server.Profile.PreventDinoTameClassNames), null);
- preventDinoTameClassNames.FromIniValues(section.KeysToStringArray().Where(s => s.StartsWith($"{preventDinoTameClassNames.IniCollectionKey}=")));
+ preventDinoTameClassNames.FromIniValues(section.KeysToStringEnumerable().Where(s => s.StartsWith($"{preventDinoTameClassNames.IniCollectionKey}=")));
Server.Profile.PreventDinoTameClassNames.AddRange(preventDinoTameClassNames);
Server.Profile.PreventDinoTameClassNames.IsEnabled |= preventDinoTameClassNames.IsEnabled;
var npcReplacements = new AggregateIniValueList(nameof(Server.Profile.NPCReplacements), null);
- npcReplacements.FromIniValues(section.KeysToStringArray().Where(s => s.StartsWith($"{npcReplacements.IniCollectionKey}=")));
+ npcReplacements.FromIniValues(section.KeysToStringEnumerable().Where(s => s.StartsWith($"{npcReplacements.IniCollectionKey}=")));
Server.Profile.NPCReplacements.AddRange(npcReplacements);
Server.Profile.NPCReplacements.IsEnabled |= npcReplacements.IsEnabled;
var tamedDinoClassDamageMultipliers = new AggregateIniValueList(nameof(Server.Profile.TamedDinoClassDamageMultipliers), null);
- tamedDinoClassDamageMultipliers.FromIniValues(section.KeysToStringArray().Where(s => s.StartsWith($"{tamedDinoClassDamageMultipliers.IniCollectionKey}=")));
+ tamedDinoClassDamageMultipliers.FromIniValues(section.KeysToStringEnumerable().Where(s => s.StartsWith($"{tamedDinoClassDamageMultipliers.IniCollectionKey}=")));
Server.Profile.TamedDinoClassDamageMultipliers.AddRange(tamedDinoClassDamageMultipliers);
Server.Profile.TamedDinoClassDamageMultipliers.IsEnabled |= tamedDinoClassDamageMultipliers.IsEnabled;
var tamedDinoClassResistanceMultipliers = new AggregateIniValueList(nameof(Server.Profile.TamedDinoClassResistanceMultipliers), null);
- tamedDinoClassResistanceMultipliers.FromIniValues(section.KeysToStringArray().Where(s => s.StartsWith($"{tamedDinoClassResistanceMultipliers.IniCollectionKey}=")));
+ tamedDinoClassResistanceMultipliers.FromIniValues(section.KeysToStringEnumerable().Where(s => s.StartsWith($"{tamedDinoClassResistanceMultipliers.IniCollectionKey}=")));
Server.Profile.TamedDinoClassResistanceMultipliers.AddRange(tamedDinoClassResistanceMultipliers);
Server.Profile.TamedDinoClassResistanceMultipliers.IsEnabled |= tamedDinoClassResistanceMultipliers.IsEnabled;
var dinoClassDamageMultipliers = new AggregateIniValueList(nameof(Server.Profile.DinoClassDamageMultipliers), null);
- dinoClassDamageMultipliers.FromIniValues(section.KeysToStringArray().Where(s => s.StartsWith($"{dinoClassDamageMultipliers.IniCollectionKey}=")));
+ dinoClassDamageMultipliers.FromIniValues(section.KeysToStringEnumerable().Where(s => s.StartsWith($"{dinoClassDamageMultipliers.IniCollectionKey}=")));
Server.Profile.DinoClassDamageMultipliers.AddRange(dinoClassDamageMultipliers);
Server.Profile.DinoClassDamageMultipliers.IsEnabled |= dinoClassDamageMultipliers.IsEnabled;
var dinoClassResistanceMultipliers = new AggregateIniValueList(nameof(Server.Profile.DinoClassResistanceMultipliers), null);
- dinoClassResistanceMultipliers.FromIniValues(section.KeysToStringArray().Where(s => s.StartsWith($"{dinoClassResistanceMultipliers.IniCollectionKey}=")));
+ dinoClassResistanceMultipliers.FromIniValues(section.KeysToStringEnumerable().Where(s => s.StartsWith($"{dinoClassResistanceMultipliers.IniCollectionKey}=")));
Server.Profile.DinoClassResistanceMultipliers.AddRange(dinoClassResistanceMultipliers);
Server.Profile.DinoClassResistanceMultipliers.IsEnabled |= dinoClassResistanceMultipliers.IsEnabled;
}
@@ -1406,7 +1406,8 @@ namespace ServerManagerTool
{
Settings.DinoSettings.RenderToModel();
- var iniValues = Settings.DinoSpawnWeightMultipliers.ToIniValues().ToList();
+ var iniValues = new List();
+ iniValues.AddRange(Settings.DinoSpawnWeightMultipliers.ToIniValues());
iniValues.AddRange(Settings.PreventDinoTameClassNames.ToIniValues());
iniValues.AddRange(Settings.NPCReplacements.ToIniValues());
iniValues.AddRange(Settings.DinoClassDamageMultipliers.ToIniValues());
@@ -1458,7 +1459,7 @@ namespace ServerManagerTool
foreach (var section in iniFile.Sections.Where(s => s.SectionName != null && !SystemIniFile.IniSectionNames.ContainsValue(s.SectionName)))
{
var harvestResourceItemAmountClassMultipliers = new AggregateIniValueList(nameof(Server.Profile.HarvestResourceItemAmountClassMultipliers), null);
- harvestResourceItemAmountClassMultipliers.FromIniValues(section.KeysToStringArray().Where(s => s.StartsWith($"{harvestResourceItemAmountClassMultipliers.IniCollectionKey}=")));
+ harvestResourceItemAmountClassMultipliers.FromIniValues(section.KeysToStringEnumerable().Where(s => s.StartsWith($"{harvestResourceItemAmountClassMultipliers.IniCollectionKey}=")));
Server.Profile.HarvestResourceItemAmountClassMultipliers.AddRange(harvestResourceItemAmountClassMultipliers);
Server.Profile.HarvestResourceItemAmountClassMultipliers.IsEnabled |= harvestResourceItemAmountClassMultipliers.IsEnabled;
}
@@ -1487,7 +1488,7 @@ namespace ServerManagerTool
private void SaveCustomResources_Click(object sender, RoutedEventArgs e)
{
- var iniValues = Settings.HarvestResourceItemAmountClassMultipliers.ToIniValues().ToList();
+ var iniValues = Settings.HarvestResourceItemAmountClassMultipliers.ToIniValues();
var iniValue = string.Join("\r\n", iniValues);
var window = new CommandLineWindow(iniValue);
@@ -1686,12 +1687,12 @@ namespace ServerManagerTool
foreach (var section in iniFile.Sections.Where(s => s.SectionName != null && !SystemIniFile.IniSectionNames.ContainsValue(s.SectionName)))
{
var overrideNamedEngramEntries = new EngramEntryList(nameof(Server.Profile.OverrideNamedEngramEntries));
- overrideNamedEngramEntries.FromIniValues(section.KeysToStringArray().Where(s => s.StartsWith($"{overrideNamedEngramEntries.IniCollectionKey}=")));
+ overrideNamedEngramEntries.FromIniValues(section.KeysToStringEnumerable().Where(s => s.StartsWith($"{overrideNamedEngramEntries.IniCollectionKey}=")));
Server.Profile.OverrideNamedEngramEntries.AddRange(overrideNamedEngramEntries);
Server.Profile.OverrideNamedEngramEntries.IsEnabled |= overrideNamedEngramEntries.IsEnabled;
var engramEntryAutoUnlocks = new EngramAutoUnlockList(nameof(Server.Profile.EngramEntryAutoUnlocks));
- engramEntryAutoUnlocks.FromIniValues(section.KeysToStringArray().Where(s => s.StartsWith($"{engramEntryAutoUnlocks.IniCollectionKey}=")));
+ engramEntryAutoUnlocks.FromIniValues(section.KeysToStringEnumerable().Where(s => s.StartsWith($"{engramEntryAutoUnlocks.IniCollectionKey}=")));
Server.Profile.EngramEntryAutoUnlocks.AddRange(engramEntryAutoUnlocks);
Server.Profile.EngramEntryAutoUnlocks.IsEnabled |= engramEntryAutoUnlocks.IsEnabled;
}
@@ -1716,7 +1717,8 @@ namespace ServerManagerTool
Settings.EngramSettings.OnlyAllowSpecifiedEngrams = Settings.OnlyAllowSpecifiedEngrams;
Settings.EngramSettings.RenderToModel();
- var iniValues = Settings.OverrideNamedEngramEntries.ToIniValues().ToList();
+ var iniValues = new List();
+ iniValues.AddRange(Settings.OverrideNamedEngramEntries.ToIniValues());
iniValues.AddRange(Settings.EngramEntryAutoUnlocks.ToIniValues());
var iniValue = string.Join("\r\n", iniValues);
@@ -1790,7 +1792,7 @@ namespace ServerManagerTool
foreach (var section in iniFile.Sections.Where(s => s.SectionName != null && !SystemIniFile.IniSectionNames.ContainsValue(s.SectionName)))
{
var configOverrideItemCraftingCosts = new AggregateIniValueList(nameof(Server.Profile.ConfigOverrideItemCraftingCosts), null);
- configOverrideItemCraftingCosts.FromIniValues(section.KeysToStringArray().Where(s => s.StartsWith($"{configOverrideItemCraftingCosts.IniCollectionKey}=")));
+ configOverrideItemCraftingCosts.FromIniValues(section.KeysToStringEnumerable().Where(s => s.StartsWith($"{configOverrideItemCraftingCosts.IniCollectionKey}=")));
Server.Profile.ConfigOverrideItemCraftingCosts.AddRange(configOverrideItemCraftingCosts);
Server.Profile.ConfigOverrideItemCraftingCosts.IsEnabled |= configOverrideItemCraftingCosts.IsEnabled;
}
@@ -1822,7 +1824,8 @@ namespace ServerManagerTool
private void SaveCraftingOverride_Click(object sender, RoutedEventArgs e)
{
- var iniValues = Settings.ConfigOverrideItemCraftingCosts.ToIniValues().ToList();
+ var iniValues = new List();
+ iniValues.AddRange(Settings.ConfigOverrideItemCraftingCosts.ToIniValues());
var iniValue = string.Join("\r\n", iniValues);
var window = new CommandLineWindow(iniValue);
@@ -1898,7 +1901,7 @@ namespace ServerManagerTool
// cycle through the sections, adding them to the custom section list. Will bypass any sections that are named as per the ARK default sections.
foreach (var section in iniFile.Sections.Where(s => !string.IsNullOrWhiteSpace(s.SectionName) && !SystemIniFile.IniSectionNames.ContainsValue(s.SectionName)))
{
- Settings.CustomGameUserSettings.Add(section.SectionName, section.KeysToStringArray(), false);
+ Settings.CustomGameUserSettings.Add(section.SectionName, section.KeysToStringEnumerable(), false);
}
MessageBox.Show(_globalizer.GetResourceString("ServerSettings_LoadCustomConfig_Label"), _globalizer.GetResourceString("ServerSettings_LoadCustomConfig_Title"), MessageBoxButton.OK, MessageBoxImage.Information);
@@ -1957,7 +1960,7 @@ namespace ServerManagerTool
// cycle through the sections, adding them to the custom section list. Will bypass any sections that are named as per the ARK default sections.
foreach (var section in iniFile.Sections.Where(s => !string.IsNullOrWhiteSpace(s.SectionName) && !SystemIniFile.IniSectionNames.ContainsValue(s.SectionName)))
{
- Settings.CustomGameUserSettings.Add(section.SectionName, section.KeysToStringArray(), false);
+ Settings.CustomGameUserSettings.Add(section.SectionName, section.KeysToStringEnumerable(), false);
}
}
@@ -1980,7 +1983,7 @@ namespace ServerManagerTool
var configIniFile = Path.Combine(ServerProfile.GetProfileServerConfigDir(Settings), Config.Default.ServerGameUserSettingsConfigFile);
// load only this section, using the full exclusion list
- var tempServerProfile = ServerProfile.LoadFromINIFiles(configIniFile, null, exclusions.ToArray());
+ var tempServerProfile = ServerProfile.LoadFromINIFiles(configIniFile, null, exclusions);
// perform a profile sync
Settings.SyncSettings(ServerProfileCategory.CustomGameUserSettings, tempServerProfile);
}
@@ -2059,7 +2062,7 @@ namespace ServerManagerTool
// cycle through the sections, adding them to the custom section list. Will bypass any sections that are named as per the ARK default sections.
foreach (var section in iniFile.Sections.Where(s => !string.IsNullOrWhiteSpace(s.SectionName) && !SystemIniFile.IniSectionNames.ContainsValue(s.SectionName)))
{
- Settings.CustomGameSettings.Add(section.SectionName, section.KeysToStringArray(), false);
+ Settings.CustomGameSettings.Add(section.SectionName, section.KeysToStringEnumerable(), false);
}
MessageBox.Show(_globalizer.GetResourceString("ServerSettings_LoadCustomConfig_Label"), _globalizer.GetResourceString("ServerSettings_LoadCustomConfig_Title"), MessageBoxButton.OK, MessageBoxImage.Information);
@@ -2118,7 +2121,7 @@ namespace ServerManagerTool
// cycle through the sections, adding them to the custom section list. Will bypass any sections that are named as per the ARK default sections.
foreach (var section in iniFile.Sections.Where(s => !string.IsNullOrWhiteSpace(s.SectionName) && !SystemIniFile.IniSectionNames.ContainsValue(s.SectionName)))
{
- Settings.CustomGameSettings.Add(section.SectionName, section.KeysToStringArray(), false);
+ Settings.CustomGameSettings.Add(section.SectionName, section.KeysToStringEnumerable(), false);
}
}
@@ -2141,7 +2144,7 @@ namespace ServerManagerTool
var configIniFile = Path.Combine(ServerProfile.GetProfileServerConfigDir(Settings), Config.Default.ServerGameUserSettingsConfigFile);
// load only this section, using the full exclusion list
- var tempServerProfile = ServerProfile.LoadFromINIFiles(configIniFile, null, exclusions.ToArray());
+ var tempServerProfile = ServerProfile.LoadFromINIFiles(configIniFile, null, exclusions);
// perform a profile sync
Settings.SyncSettings(ServerProfileCategory.CustomGameSettings, tempServerProfile);
}
@@ -2220,7 +2223,7 @@ namespace ServerManagerTool
// cycle through the sections, adding them to the custom section list. Will bypass any sections that are named as per the ARK default sections.
foreach (var section in iniFile.Sections.Where(s => !string.IsNullOrWhiteSpace(s.SectionName) && !SystemIniFile.IniSectionNames.ContainsValue(s.SectionName)))
{
- Settings.CustomEngineSettings.Add(section.SectionName, section.KeysToStringArray(), false);
+ Settings.CustomEngineSettings.Add(section.SectionName, section.KeysToStringEnumerable(), false);
}
MessageBox.Show(_globalizer.GetResourceString("ServerSettings_LoadCustomConfig_Label"), _globalizer.GetResourceString("ServerSettings_LoadCustomConfig_Title"), MessageBoxButton.OK, MessageBoxImage.Information);
@@ -2279,7 +2282,7 @@ namespace ServerManagerTool
// cycle through the sections, adding them to the custom section list. Will bypass any sections that are named as per the ARK default sections.
foreach (var section in iniFile.Sections.Where(s => !string.IsNullOrWhiteSpace(s.SectionName) && !SystemIniFile.IniSectionNames.ContainsValue(s.SectionName)))
{
- Settings.CustomEngineSettings.Add(section.SectionName, section.KeysToStringArray(), false);
+ Settings.CustomEngineSettings.Add(section.SectionName, section.KeysToStringEnumerable(), false);
}
}
@@ -2302,7 +2305,7 @@ namespace ServerManagerTool
var configIniFile = Path.Combine(ServerProfile.GetProfileServerConfigDir(Settings), Config.Default.ServerGameUserSettingsConfigFile);
// load only this section, using the full exclusion list
- var tempServerProfile = ServerProfile.LoadFromINIFiles(configIniFile, null, exclusions.ToArray());
+ var tempServerProfile = ServerProfile.LoadFromINIFiles(configIniFile, null, exclusions);
// perform a profile sync
Settings.SyncSettings(ServerProfileCategory.CustomEngineSettings, tempServerProfile);
}
@@ -2693,7 +2696,7 @@ namespace ServerManagerTool
Application.Current.Dispatcher.Invoke(() => this.Cursor = Cursors.Wait);
await Task.Delay(500);
- Settings.LoadServerFileAdministrators();
+ Settings.LoadServerFiles(true, false, false);
}
catch (Exception ex)
{
@@ -2714,7 +2717,7 @@ namespace ServerManagerTool
Application.Current.Dispatcher.Invoke(() => this.Cursor = Cursors.Wait);
await Task.Delay(500);
- Settings.LoadServerFileExclusive();
+ Settings.LoadServerFiles(false, true, false);
}
catch (Exception ex)
{
@@ -2735,7 +2738,7 @@ namespace ServerManagerTool
Application.Current.Dispatcher.Invoke(() => this.Cursor = Cursors.Wait);
await Task.Delay(500);
- Settings.LoadServerFileWhitelisted();
+ Settings.LoadServerFiles(false, false, true);
}
catch (Exception ex)
{
@@ -2919,17 +2922,17 @@ namespace ServerManagerTool
foreach (var section in iniFile.Sections.Where(s => s.SectionName != null && !SystemIniFile.IniSectionNames.ContainsValue(s.SectionName)))
{
var configAddNPCSpawnEntriesContainer = new NPCSpawnContainerList(nameof(Server.Profile.ConfigAddNPCSpawnEntriesContainer), NPCSpawnContainerType.Add);
- configAddNPCSpawnEntriesContainer.FromIniValues(section.KeysToStringArray().Where(s => s.StartsWith($"{configAddNPCSpawnEntriesContainer.IniCollectionKey}=")));
+ configAddNPCSpawnEntriesContainer.FromIniValues(section.KeysToStringEnumerable().Where(s => s.StartsWith($"{configAddNPCSpawnEntriesContainer.IniCollectionKey}=")));
Server.Profile.ConfigAddNPCSpawnEntriesContainer.AddRange(configAddNPCSpawnEntriesContainer);
Server.Profile.ConfigAddNPCSpawnEntriesContainer.IsEnabled |= configAddNPCSpawnEntriesContainer.IsEnabled;
var configSubtractNPCSpawnEntriesContainer = new NPCSpawnContainerList(nameof(Server.Profile.ConfigSubtractNPCSpawnEntriesContainer), NPCSpawnContainerType.Subtract);
- configSubtractNPCSpawnEntriesContainer.FromIniValues(section.KeysToStringArray().Where(s => s.StartsWith($"{configSubtractNPCSpawnEntriesContainer.IniCollectionKey}=")));
+ configSubtractNPCSpawnEntriesContainer.FromIniValues(section.KeysToStringEnumerable().Where(s => s.StartsWith($"{configSubtractNPCSpawnEntriesContainer.IniCollectionKey}=")));
Server.Profile.ConfigSubtractNPCSpawnEntriesContainer.AddRange(configSubtractNPCSpawnEntriesContainer);
Server.Profile.ConfigSubtractNPCSpawnEntriesContainer.IsEnabled |= configSubtractNPCSpawnEntriesContainer.IsEnabled;
var configOverrideNPCSpawnEntriesContainer = new NPCSpawnContainerList(nameof(Server.Profile.ConfigOverrideNPCSpawnEntriesContainer), NPCSpawnContainerType.Override);
- configOverrideNPCSpawnEntriesContainer.FromIniValues(section.KeysToStringArray().Where(s => s.StartsWith($"{configOverrideNPCSpawnEntriesContainer.IniCollectionKey}=")));
+ configOverrideNPCSpawnEntriesContainer.FromIniValues(section.KeysToStringEnumerable().Where(s => s.StartsWith($"{configOverrideNPCSpawnEntriesContainer.IniCollectionKey}=")));
Server.Profile.ConfigOverrideNPCSpawnEntriesContainer.AddRange(configOverrideNPCSpawnEntriesContainer);
Server.Profile.ConfigOverrideNPCSpawnEntriesContainer.IsEnabled |= configOverrideNPCSpawnEntriesContainer.IsEnabled;
}
@@ -2966,7 +2969,8 @@ namespace ServerManagerTool
{
Settings.NPCSpawnSettings.RenderToModel();
- var iniValues = Settings.ConfigAddNPCSpawnEntriesContainer.ToIniValues().ToList();
+ var iniValues = new List();
+ iniValues.AddRange(Settings.ConfigAddNPCSpawnEntriesContainer.ToIniValues());
iniValues.AddRange(Settings.ConfigSubtractNPCSpawnEntriesContainer.ToIniValues());
iniValues.AddRange(Settings.ConfigOverrideNPCSpawnEntriesContainer.ToIniValues());
var iniValue = string.Join("\r\n", iniValues);
@@ -3123,7 +3127,7 @@ namespace ServerManagerTool
foreach (var section in iniFile.Sections.Where(s => s.SectionName != null && !SystemIniFile.IniSectionNames.ContainsValue(s.SectionName)))
{
var configOverrideSupplyCrateItems = new SupplyCrateOverrideList(nameof(Server.Profile.ConfigOverrideSupplyCrateItems));
- configOverrideSupplyCrateItems.FromIniValues(section.KeysToStringArray().Where(s => s.StartsWith($"{configOverrideSupplyCrateItems.IniCollectionKey}=")));
+ configOverrideSupplyCrateItems.FromIniValues(section.KeysToStringEnumerable().Where(s => s.StartsWith($"{configOverrideSupplyCrateItems.IniCollectionKey}=")));
Server.Profile.ConfigOverrideSupplyCrateItems.AddRange(configOverrideSupplyCrateItems);
Server.Profile.ConfigOverrideSupplyCrateItems.IsEnabled |= configOverrideSupplyCrateItems.IsEnabled;
}
@@ -3133,7 +3137,7 @@ namespace ServerManagerTool
RefreshBaseSupplyCrateList();
RefreshBasePrimalItemList();
- if (errors.Length > 0)
+ if (errors.Any())
{
var error = $"The following errors have been found:\r\n\r\n{string.Join("\r\n", errors)}";
@@ -3199,7 +3203,8 @@ namespace ServerManagerTool
{
Settings.ConfigOverrideSupplyCrateItems.RenderToModel();
- var iniValues = Settings.ConfigOverrideSupplyCrateItems.ToIniValues().ToList();
+ var iniValues = new List();
+ iniValues.AddRange(Settings.ConfigOverrideSupplyCrateItems.ToIniValues());
var iniValue = string.Join("\r\n", iniValues);
var window = new CommandLineWindow(iniValue);
@@ -3265,7 +3270,7 @@ namespace ServerManagerTool
foreach (var section in iniFile.Sections.Where(s => s.SectionName != null && !SystemIniFile.IniSectionNames.ContainsValue(s.SectionName)))
{
var configOverrideItemMaxQuantity = new AggregateIniValueList(nameof(Server.Profile.ConfigOverrideItemMaxQuantity), null);
- configOverrideItemMaxQuantity.FromIniValues(section.KeysToStringArray().Where(s => s.StartsWith($"{configOverrideItemMaxQuantity.IniCollectionKey}=")));
+ configOverrideItemMaxQuantity.FromIniValues(section.KeysToStringEnumerable().Where(s => s.StartsWith($"{configOverrideItemMaxQuantity.IniCollectionKey}=")));
Server.Profile.ConfigOverrideItemMaxQuantity.AddRange(configOverrideItemMaxQuantity);
Server.Profile.ConfigOverrideItemMaxQuantity.IsEnabled |= configOverrideItemMaxQuantity.IsEnabled;
}
@@ -3274,7 +3279,7 @@ namespace ServerManagerTool
RefreshBasePrimalItemList();
- if (errors.Length > 0)
+ if (errors.Any())
{
var error = $"The following errors have been found:\r\n\r\n{string.Join("\r\n", errors)}";
@@ -3301,7 +3306,8 @@ namespace ServerManagerTool
{
Settings.ConfigOverrideItemMaxQuantity.RenderToModel();
- var iniValues = Settings.ConfigOverrideItemMaxQuantity.ToIniValues().ToList();
+ var iniValues = new List();
+ iniValues.AddRange(Settings.ConfigOverrideItemMaxQuantity.ToIniValues());
var iniValue = string.Join("\r\n", iniValues);
var window = new CommandLineWindow(iniValue);
@@ -3365,7 +3371,7 @@ namespace ServerManagerTool
foreach (var section in iniFile.Sections.Where(s => s.SectionName != null && !SystemIniFile.IniSectionNames.ContainsValue(s.SectionName)))
{
var preventTransferForClassNames = new AggregateIniValueList(nameof(Server.Profile.PreventTransferForClassNames), null);
- preventTransferForClassNames.FromIniValues(section.KeysToStringArray().Where(s => s.StartsWith($"{preventTransferForClassNames.IniCollectionKey}=")));
+ preventTransferForClassNames.FromIniValues(section.KeysToStringEnumerable().Where(s => s.StartsWith($"{preventTransferForClassNames.IniCollectionKey}=")));
Server.Profile.PreventTransferForClassNames.AddRange(preventTransferForClassNames);
Server.Profile.PreventTransferForClassNames.IsEnabled |= preventTransferForClassNames.IsEnabled;
}
@@ -3374,7 +3380,7 @@ namespace ServerManagerTool
RefreshBaseDinoList();
- if (errors.Length > 0)
+ if (errors.Any())
{
var error = $"The following errors have been found:\r\n\r\n{string.Join("\r\n", errors)}";
@@ -3401,7 +3407,8 @@ namespace ServerManagerTool
{
Settings.PreventTransferForClassNames.RenderToModel();
- var iniValues = Settings.PreventTransferForClassNames.ToIniValues().ToList();
+ var iniValues = new List();
+ iniValues.AddRange(Settings.PreventTransferForClassNames.ToIniValues());
var iniValue = string.Join("\r\n", iniValues);
var window = new CommandLineWindow(iniValue);
@@ -3442,7 +3449,7 @@ namespace ServerManagerTool
var name = _globalizer.GetResourceString($"Mod_{value}");
newList.Add(new Common.Model.ComboBoxItem(value, name));
- var values = GameData.GetDinoSpawns().GroupBy(d => d.Mod).OrderBy(g => g.Key).Select(g => g.Key).ToList();
+ var values = GameData.GetDinoSpawns().GroupBy(d => d.Mod).OrderBy(g => g.Key).Select(g => g.Key);
foreach (var modValue in values)
{
if (string.IsNullOrWhiteSpace(modValue))
@@ -3472,7 +3479,7 @@ namespace ServerManagerTool
var name = _globalizer.GetResourceString($"Mod_{value}");
newList.Add(new Common.Model.ComboBoxItem(value, name));
- var values = GameData.GetEngrams().GroupBy(d => d.Mod).OrderBy(g => g.Key).Select(g => g.Key).ToList();
+ var values = GameData.GetEngrams().GroupBy(d => d.Mod).OrderBy(g => g.Key).Select(g => g.Key);
foreach (var modValue in values)
{
if (string.IsNullOrWhiteSpace(modValue))
@@ -3502,7 +3509,7 @@ namespace ServerManagerTool
var name = _globalizer.GetResourceString($"Mod_{value}");
newList.Add(new Common.Model.ComboBoxItem(value, name));
- var values = GameData.GetResourceMultipliers().GroupBy(d => d.Mod).OrderBy(g => g.Key).Select(g => g.Key).ToList();
+ var values = GameData.GetResourceMultipliers().GroupBy(d => d.Mod).OrderBy(g => g.Key).Select(g => g.Key);
foreach (var modValue in values)
{
if (string.IsNullOrWhiteSpace(modValue))
diff --git a/src/ARKServerManager/Utils/DiscordBotHelper.cs b/src/ARKServerManager/Utils/DiscordBotHelper.cs
index 97abbec7..025f9b81 100644
--- a/src/ARKServerManager/Utils/DiscordBotHelper.cs
+++ b/src/ARKServerManager/Utils/DiscordBotHelper.cs
@@ -1,11 +1,11 @@
using QueryMaster;
+using ServerManagerTool.Common.Extensions;
using ServerManagerTool.Common.Utils;
using ServerManagerTool.DiscordBot.Enums;
using ServerManagerTool.Enums;
using ServerManagerTool.Lib;
using System;
using System.Collections.Generic;
-using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Threading;
@@ -23,7 +23,7 @@ namespace ServerManagerTool.Utils
public static bool HasRunningCommands => _currentProfileCommands.Count > 0;
- public static IList HandleDiscordCommand(CommandType commandType, string serverId, string channelId, string profileId, CancellationToken token)
+ public static IList HandleDiscordCommand(CommandType commandType, string serverId, string channelId, string profileIdOrAlias, CancellationToken token)
{
// check if incoming values are valid
if (string.IsNullOrWhiteSpace(serverId) || string.IsNullOrWhiteSpace(channelId))
@@ -42,35 +42,35 @@ namespace ServerManagerTool.Utils
switch (commandType)
{
case CommandType.Info:
- return GetServerInfo(channelId, profileId);
+ return GetServerInfo(channelId, profileIdOrAlias);
case CommandType.List:
return GetServerList(channelId);
case CommandType.Status:
- return GetServerStatus(channelId, profileId);
+ return GetServerStatus(channelId, profileIdOrAlias);
case CommandType.Backup:
if (Config.Default.AllowDiscordBackup)
- return BackupServer(channelId, profileId, token);
+ return BackupServer(channelId, profileIdOrAlias, token);
return new List { string.Format(_globalizer.GetResourceString("DiscordBot_CommandNotEnabled"), commandType) };
case CommandType.Restart:
if (Config.Default.AllowDiscordRestart)
- return RestartServer(channelId, profileId, token);
+ return RestartServer(channelId, profileIdOrAlias, token);
return new List { string.Format(_globalizer.GetResourceString("DiscordBot_CommandNotEnabled"), commandType) };
case CommandType.Shutdown:
if (Config.Default.AllowDiscordShutdown)
- return ShutdownServer(channelId, profileId, token);
+ return ShutdownServer(channelId, profileIdOrAlias, token);
return new List { string.Format(_globalizer.GetResourceString("DiscordBot_CommandNotEnabled"), commandType) };
case CommandType.Stop:
if (Config.Default.AllowDiscordStop)
- return StopServer(channelId, profileId, token);
+ return StopServer(channelId, profileIdOrAlias, token);
return new List { string.Format(_globalizer.GetResourceString("DiscordBot_CommandNotEnabled"), commandType) };
case CommandType.Start:
if (Config.Default.AllowDiscordStart)
- return StartServer(channelId, profileId, token);
+ return StartServer(channelId, profileIdOrAlias, token);
return new List { string.Format(_globalizer.GetResourceString("DiscordBot_CommandNotEnabled"), commandType) };
case CommandType.Update:
if (Config.Default.AllowDiscordUpdate)
- return UpdateServer(channelId, profileId, token);
+ return UpdateServer(channelId, profileIdOrAlias, token);
return new List { string.Format(_globalizer.GetResourceString("DiscordBot_CommandNotEnabled"), commandType) };
default:
@@ -93,19 +93,14 @@ namespace ServerManagerTool.Utils
return string.IsNullOrWhiteSpace(translationKey) ? string.Empty : _globalizer.GetResourceString(translationKey) ?? translationKey;
}
- private static IList GetServerInfo(string channelId, string profileId)
+ private static IList GetServerInfo(string channelId, string profileIdOrAlias)
{
- if (string.IsNullOrWhiteSpace(profileId))
+ if (string.IsNullOrWhiteSpace(profileIdOrAlias))
{
return new List { string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMissing"), CommandType.Info) };
}
- // check if another command is being run against the profile
- if (_currentProfileCommands.ContainsKey(profileId))
- {
- return new List { string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[profileId], profileId) };
- }
- _currentProfileCommands.Add(profileId, CommandType.Info);
+ var key = string.Empty;
try
{
@@ -115,12 +110,29 @@ namespace ServerManagerTool.Utils
TaskUtils.RunOnUIThreadAsync(() =>
{
- var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
+ var serverList = ServerManager.Instance.Servers.Where(s => string.Equals(channelId, s.Profile.DiscordChannelId, StringComparison.OrdinalIgnoreCase)
+ && (string.Equals(profileIdOrAlias, s.Profile.ProfileID, StringComparison.OrdinalIgnoreCase)
+ || !string.IsNullOrWhiteSpace(s.Profile.DiscordAlias) && string.Equals(profileIdOrAlias, s.Profile.DiscordAlias, StringComparison.OrdinalIgnoreCase)));
- if (server is null)
+ if (serverList.IsEmpty())
{
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileIdOrAlias));
}
+ if (!serverList.HasOne())
+ {
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMultiples"), profileIdOrAlias));
+ }
+
+ var server = serverList.First();
+
+ // check if another command is being run against the profile
+ if (_currentProfileCommands.ContainsKey(server.Profile.ProfileID))
+ {
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[server.Profile.ProfileID], server.Profile.ProfileName));
+ }
+
+ key = server.Profile.ProfileID;
+ _currentProfileCommands.Add(key, CommandType.Info);
switch (server.Runtime.Status)
{
@@ -130,7 +142,7 @@ namespace ServerManagerTool.Utils
case ServerStatus.Uninstalled:
case ServerStatus.Unknown:
case ServerStatus.Updating:
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileBadStatus"), profileId, server.Runtime.StatusString));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileBadStatus"), server.Profile.ProfileName, server.Runtime.StatusString));
}
serverName = server.Profile.ServerName;
@@ -155,7 +167,9 @@ namespace ServerManagerTool.Utils
else
{
var mapName = _globalizer.GetResourceString($"Map_{info.Map}") ?? info.Map;
- response.Add($"```{info.Name}\n{_globalizer.GetResourceString("DiscordBot_MapLabel")} {mapName}\n{_globalizer.GetResourceString("ServerSettings_PlayersLabel")} {info.Players} / {info.MaxPlayers}```");
+ response.Add($"```{info.Name}\n" +
+ $"{_globalizer.GetResourceString("DiscordBot_MapLabel")} {mapName}\n" +
+ $"{_globalizer.GetResourceString("ServerSettings_PlayersLabel")} {info.Players} / {info.MaxPlayers}```");
}
}
}
@@ -168,7 +182,7 @@ namespace ServerManagerTool.Utils
}
finally
{
- _currentProfileCommands.Remove(profileId);
+ _currentProfileCommands.Remove(key);
}
}
@@ -178,49 +192,55 @@ namespace ServerManagerTool.Utils
TaskUtils.RunOnUIThreadAsync(() =>
{
- var serverList = ServerManager.Instance.Servers.Where(s => Equals(channelId, s.Profile.DiscordChannelId));
+ var serverList = ServerManager.Instance.Servers.Where(s => string.Equals(channelId, s.Profile.DiscordChannelId, StringComparison.OrdinalIgnoreCase));
response.Add($"**{_globalizer.GetResourceString("DiscordBot_CountLabel")}** {serverList.Count()}");
foreach (var server in serverList)
{
- response.Add($"```{_globalizer.GetResourceString("ServerSettings_ProfileIdLabel")} {server.Profile.ProfileID}\n{_globalizer.GetResourceString("ServerSettings_ProfileLabel")} {server.Profile.ProfileName}\n{_globalizer.GetResourceString("ServerSettings_ServerNameLabel")} {server.Profile.ServerName}```");
+ response.Add($"```{_globalizer.GetResourceString("ServerSettings_ProfileLabel")} {server.Profile.ProfileName}\n" +
+ $"{_globalizer.GetResourceString("ServerSettings_ProfileIdLabel")} {server.Profile.ProfileID}\n" +
+ (string.IsNullOrWhiteSpace(server.Profile.DiscordAlias) ? "" : $"{_globalizer.GetResourceString("ServerSettings_DiscordAliasLabel")} {server.Profile.DiscordAlias}\n") +
+ $"{_globalizer.GetResourceString("ServerSettings_ServerNameLabel")} {server.Profile.ServerName}```");
}
}).Wait();
return response;
}
- private static IList GetServerStatus(string channelId, string profileId)
+ private static IList GetServerStatus(string channelId, string profileIdOrAlias)
{
List response = new List();
TaskUtils.RunOnUIThreadAsync(() =>
{
- var serverList = ServerManager.Instance.Servers.Where(s => Equals(channelId, s.Profile.DiscordChannelId) && (string.IsNullOrWhiteSpace(profileId) || Equals(profileId, s.Profile.ProfileID)));
+ var serverList = ServerManager.Instance.Servers.Where(s => string.Equals(channelId, s.Profile.DiscordChannelId, StringComparison.OrdinalIgnoreCase)
+ && (string.IsNullOrWhiteSpace(profileIdOrAlias)
+ || string.Equals(profileIdOrAlias, s.Profile.ProfileID, StringComparison.OrdinalIgnoreCase)
+ || !string.IsNullOrWhiteSpace(s.Profile.DiscordAlias) && string.Equals(profileIdOrAlias, s.Profile.DiscordAlias, StringComparison.OrdinalIgnoreCase)));
response.Add($"**{_globalizer.GetResourceString("DiscordBot_CountLabel")}** {serverList.Count()}");
foreach (var server in serverList)
{
- response.Add($"```{_globalizer.GetResourceString("ServerSettings_ProfileLabel")} {server.Profile.ProfileName}\n{_globalizer.GetResourceString("ServerSettings_ServerNameLabel")} {server.Profile.ServerName}\n{_globalizer.GetResourceString("ServerSettings_StatusLabel")} {server.Runtime.StatusString}\n{_globalizer.GetResourceString("ServerSettings_AvailabilityLabel")} {_globalizer.GetResourceString($"ServerSettings_Availability_{server.Runtime.Availability}")}```");
+ response.Add($"```{_globalizer.GetResourceString("ServerSettings_ProfileLabel")} {server.Profile.ProfileName}\n" +
+ $"{_globalizer.GetResourceString("ServerSettings_ProfileIdLabel")} {server.Profile.ProfileID}\n" +
+ (string.IsNullOrWhiteSpace(server.Profile.DiscordAlias) ? "" : $"{_globalizer.GetResourceString("ServerSettings_DiscordAliasLabel")} {server.Profile.DiscordAlias}\n") +
+ $"{_globalizer.GetResourceString("ServerSettings_ServerNameLabel")} {server.Profile.ServerName}\n" +
+ $"{_globalizer.GetResourceString("ServerSettings_StatusLabel")} {server.Runtime.StatusString}\n" +
+ $"{_globalizer.GetResourceString("ServerSettings_AvailabilityLabel")} {_globalizer.GetResourceString($"ServerSettings_Availability_{server.Runtime.Availability}")}```");
}
}).Wait();
return response;
}
- private static IList BackupServer(string channelId, string profileId, CancellationToken token)
+ private static IList BackupServer(string channelId, string profileIdOrAlias, CancellationToken token)
{
- if (string.IsNullOrWhiteSpace(profileId))
+ if (string.IsNullOrWhiteSpace(profileIdOrAlias))
{
return new List { string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMissing"), CommandType.Backup) };
}
- // check if another command is being run against the profile
- if (_currentProfileCommands.ContainsKey(profileId))
- {
- return new List { string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[profileId], profileId) };
- }
- _currentProfileCommands.Add(profileId, CommandType.Backup);
+ var key = string.Empty;
ServerProfileSnapshot profile = null;
Task task = null;
@@ -229,18 +249,35 @@ namespace ServerManagerTool.Utils
{
TaskUtils.RunOnUIThreadAsync(() =>
{
- var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
+ var serverList = ServerManager.Instance.Servers.Where(s => string.Equals(channelId, s.Profile.DiscordChannelId, StringComparison.OrdinalIgnoreCase)
+ && (string.Equals(profileIdOrAlias, s.Profile.ProfileID, StringComparison.OrdinalIgnoreCase)
+ || !string.IsNullOrWhiteSpace(s.Profile.DiscordAlias) && string.Equals(profileIdOrAlias, s.Profile.DiscordAlias, StringComparison.OrdinalIgnoreCase)));
- if (server is null)
+ if (serverList.IsEmpty())
{
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileIdOrAlias));
}
+ if (!serverList.HasOne())
+ {
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMultiples"), profileIdOrAlias));
+ }
+
+ var server = serverList.First();
if (!server.Profile.AllowDiscordBackup)
{
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandDisabledProfile"), CommandType.Backup, profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandDisabledProfile"), CommandType.Backup, server.Profile.ProfileName));
}
+ // check if another command is being run against the profile
+ if (_currentProfileCommands.ContainsKey(server.Profile.ProfileID))
+ {
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[server.Profile.ProfileID], server.Profile.ProfileName));
+ }
+
+ key = server.Profile.ProfileID;
+ _currentProfileCommands.Add(key, CommandType.Backup);
+
switch (server.Runtime.Status)
{
case ServerStatus.Initializing:
@@ -248,7 +285,7 @@ namespace ServerManagerTool.Utils
case ServerStatus.Uninstalled:
case ServerStatus.Unknown:
case ServerStatus.Updating:
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileBadStatus"), profileId, server.Runtime.StatusString));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileBadStatus"), server.Profile.ProfileName, server.Runtime.StatusString));
}
profile = ServerProfileSnapshot.Create(server.Profile);
@@ -267,7 +304,9 @@ namespace ServerManagerTool.Utils
{
TaskUtils.RunOnUIThreadAsync(() =>
{
- var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
+ var server = ServerManager.Instance.Servers.First(s => string.Equals(channelId, s.Profile.DiscordChannelId, StringComparison.OrdinalIgnoreCase)
+ && (string.Equals(profileIdOrAlias, s.Profile.ProfileID, StringComparison.OrdinalIgnoreCase)
+ || !string.IsNullOrWhiteSpace(s.Profile.DiscordAlias) && string.Equals(profileIdOrAlias, s.Profile.DiscordAlias, StringComparison.OrdinalIgnoreCase)));
server.Runtime.UpdateServerStatus(serverStatus, true);
}).Wait();
}
@@ -276,7 +315,7 @@ namespace ServerManagerTool.Utils
task = Task.Run(() =>
{
app.PerformProfileBackup(profile, token);
- _currentProfileCommands.Remove(profileId);
+ _currentProfileCommands.Remove(key);
});
response.Add(string.Format(_globalizer.GetResourceString("DiscordBot_BackupRequested"), profile.ServerName));
@@ -287,24 +326,19 @@ namespace ServerManagerTool.Utils
{
if (task is null)
{
- _currentProfileCommands.Remove(profileId);
+ _currentProfileCommands.Remove(key);
}
}
}
- private static IList RestartServer(string channelId, string profileId, CancellationToken token)
+ private static IList RestartServer(string channelId, string profileIdOrAlias, CancellationToken token)
{
- if (string.IsNullOrWhiteSpace(profileId))
+ if (string.IsNullOrWhiteSpace(profileIdOrAlias))
{
return new List { string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMissing"), CommandType.Restart) };
}
- // check if another command is being run against the profile
- if (_currentProfileCommands.ContainsKey(profileId))
- {
- return new List { string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[profileId], profileId) };
- }
- _currentProfileCommands.Add(profileId, CommandType.Restart);
+ var key = string.Empty;
ServerProfileSnapshot profile = null;
Task task = null;
@@ -313,28 +347,45 @@ namespace ServerManagerTool.Utils
{
TaskUtils.RunOnUIThreadAsync(() =>
{
- var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
+ var serverList = ServerManager.Instance.Servers.Where(s => string.Equals(channelId, s.Profile.DiscordChannelId, StringComparison.OrdinalIgnoreCase)
+ && (string.Equals(profileIdOrAlias, s.Profile.ProfileID, StringComparison.OrdinalIgnoreCase)
+ || !string.IsNullOrWhiteSpace(s.Profile.DiscordAlias) && string.Equals(profileIdOrAlias, s.Profile.DiscordAlias, StringComparison.OrdinalIgnoreCase)));
- if (server is null)
+ if (serverList.IsEmpty())
{
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileIdOrAlias));
}
+ if (!serverList.HasOne())
+ {
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMultiples"), profileIdOrAlias));
+ }
+
+ var server = serverList.First();
if (!server.Profile.AllowDiscordRestart)
{
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandDisabledProfile"), CommandType.Restart, profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandDisabledProfile"), CommandType.Restart, server.Profile.ProfileName));
}
+ // check if another command is being run against the profile
+ if (_currentProfileCommands.ContainsKey(server.Profile.ProfileID))
+ {
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[server.Profile.ProfileID], server.Profile.ProfileName));
+ }
+
+ key = server.Profile.ProfileID;
+ _currentProfileCommands.Add(key, CommandType.Restart);
+
switch (server.Runtime.Status)
{
case ServerStatus.Initializing:
case ServerStatus.Stopping:
case ServerStatus.Uninstalled:
case ServerStatus.Unknown:
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileBadStatus"), profileId, server.Runtime.StatusString));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileBadStatus"), server.Profile.ProfileName, server.Runtime.StatusString));
case ServerStatus.Updating:
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileUpdating"), profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileUpdating"), server.Profile.ProfileName));
}
profile = ServerProfileSnapshot.Create(server.Profile);
@@ -354,7 +405,9 @@ namespace ServerManagerTool.Utils
{
TaskUtils.RunOnUIThreadAsync(() =>
{
- var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
+ var server = ServerManager.Instance.Servers.First(s => string.Equals(channelId, s.Profile.DiscordChannelId, StringComparison.OrdinalIgnoreCase)
+ && (string.Equals(profileIdOrAlias, s.Profile.ProfileID, StringComparison.OrdinalIgnoreCase)
+ || !string.IsNullOrWhiteSpace(s.Profile.DiscordAlias) && string.Equals(profileIdOrAlias, s.Profile.DiscordAlias, StringComparison.OrdinalIgnoreCase)));
server.Runtime.UpdateServerStatus(serverStatus, true);
}).Wait();
}
@@ -363,7 +416,7 @@ namespace ServerManagerTool.Utils
task = Task.Run(() =>
{
app.PerformProfileShutdown(profile, true, false, false, token);
- _currentProfileCommands.Remove(profileId);
+ _currentProfileCommands.Remove(key);
});
response.Add(string.Format(_globalizer.GetResourceString("DiscordBot_RestartRequested"), profile.ServerName));
@@ -374,24 +427,19 @@ namespace ServerManagerTool.Utils
{
if (task is null)
{
- _currentProfileCommands.Remove(profileId);
+ _currentProfileCommands.Remove(key);
}
}
}
- private static IList ShutdownServer(string channelId, string profileId, CancellationToken token)
+ private static IList ShutdownServer(string channelId, string profileIdOrAlias, CancellationToken token)
{
- if (string.IsNullOrWhiteSpace(profileId))
+ if (string.IsNullOrWhiteSpace(profileIdOrAlias))
{
return new List { string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMissing"), CommandType.Shutdown) };
}
- // check if another command is being run against the profile
- if (_currentProfileCommands.ContainsKey(profileId))
- {
- return new List { string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[profileId], profileId) };
- }
- _currentProfileCommands.Add(profileId, CommandType.Shutdown);
+ var key = string.Empty;
ServerProfileSnapshot profile = null;
Task task = null;
@@ -400,18 +448,35 @@ namespace ServerManagerTool.Utils
{
TaskUtils.RunOnUIThreadAsync(() =>
{
- var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
+ var serverList = ServerManager.Instance.Servers.Where(s => string.Equals(channelId, s.Profile.DiscordChannelId, StringComparison.OrdinalIgnoreCase)
+ && (string.Equals(profileIdOrAlias, s.Profile.ProfileID, StringComparison.OrdinalIgnoreCase)
+ || !string.IsNullOrWhiteSpace(s.Profile.DiscordAlias) && string.Equals(profileIdOrAlias, s.Profile.DiscordAlias, StringComparison.OrdinalIgnoreCase)));
- if (server is null)
+ if (serverList.IsEmpty())
{
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileIdOrAlias));
}
+ if (!serverList.HasOne())
+ {
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMultiples"), profileIdOrAlias));
+ }
+
+ var server = serverList.First();
if (!server.Profile.AllowDiscordShutdown)
{
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandDisabledProfile"), CommandType.Shutdown, profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandDisabledProfile"), CommandType.Shutdown, server.Profile.ProfileName));
}
+ // check if another command is being run against the profile
+ if (_currentProfileCommands.ContainsKey(server.Profile.ProfileID))
+ {
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[server.Profile.ProfileID], server.Profile.ProfileName));
+ }
+
+ key = server.Profile.ProfileID;
+ _currentProfileCommands.Add(key, CommandType.Shutdown);
+
switch (server.Runtime.Status)
{
case ServerStatus.Initializing:
@@ -419,10 +484,10 @@ namespace ServerManagerTool.Utils
case ServerStatus.Stopped:
case ServerStatus.Uninstalled:
case ServerStatus.Unknown:
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileBadStatus"), profileId, server.Runtime.StatusString));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileBadStatus"), server.Profile.ProfileName, server.Runtime.StatusString));
case ServerStatus.Updating:
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileUpdating"), profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileUpdating"), server.Profile.ProfileName));
}
profile = ServerProfileSnapshot.Create(server.Profile);
@@ -441,7 +506,9 @@ namespace ServerManagerTool.Utils
{
TaskUtils.RunOnUIThreadAsync(() =>
{
- var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
+ var server = ServerManager.Instance.Servers.First(s => string.Equals(channelId, s.Profile.DiscordChannelId, StringComparison.OrdinalIgnoreCase)
+ && (string.Equals(profileIdOrAlias, s.Profile.ProfileID, StringComparison.OrdinalIgnoreCase)
+ || !string.IsNullOrWhiteSpace(s.Profile.DiscordAlias) && string.Equals(profileIdOrAlias, s.Profile.DiscordAlias, StringComparison.OrdinalIgnoreCase)));
server.Runtime.UpdateServerStatus(serverStatus, true);
}).Wait();
}
@@ -450,7 +517,7 @@ namespace ServerManagerTool.Utils
task = Task.Run(() =>
{
app.PerformProfileShutdown(profile, false, false, false, token);
- _currentProfileCommands.Remove(profileId);
+ _currentProfileCommands.Remove(key);
});
response.Add(string.Format(_globalizer.GetResourceString("DiscordBot_ShutdownRequested"), profile.ServerName));
@@ -461,24 +528,19 @@ namespace ServerManagerTool.Utils
{
if (task is null)
{
- _currentProfileCommands.Remove(profileId);
+ _currentProfileCommands.Remove(key);
}
}
}
- private static IList StopServer(string channelId, string profileId, CancellationToken token)
+ private static IList StopServer(string channelId, string profileIdOrAlias, CancellationToken token)
{
- if (string.IsNullOrWhiteSpace(profileId))
+ if (string.IsNullOrWhiteSpace(profileIdOrAlias))
{
return new List { string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMissing"), CommandType.Stop) };
}
- // check if another command is being run against the profile
- if (_currentProfileCommands.ContainsKey(profileId))
- {
- return new List { string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[profileId], profileId) };
- }
- _currentProfileCommands.Add(profileId, CommandType.Stop);
+ var key = string.Empty;
ServerProfileSnapshot profile = null;
Task task = null;
@@ -487,18 +549,35 @@ namespace ServerManagerTool.Utils
{
TaskUtils.RunOnUIThreadAsync(() =>
{
- var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
+ var serverList = ServerManager.Instance.Servers.Where(s => string.Equals(channelId, s.Profile.DiscordChannelId, StringComparison.OrdinalIgnoreCase)
+ && (string.Equals(profileIdOrAlias, s.Profile.ProfileID, StringComparison.OrdinalIgnoreCase)
+ || !string.IsNullOrWhiteSpace(s.Profile.DiscordAlias) && string.Equals(profileIdOrAlias, s.Profile.DiscordAlias, StringComparison.OrdinalIgnoreCase)));
- if (server is null)
+ if (serverList.IsEmpty())
{
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileIdOrAlias));
}
+ if (!serverList.HasOne())
+ {
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMultiples"), profileIdOrAlias));
+ }
+
+ var server = serverList.First();
if (!server.Profile.AllowDiscordStop)
{
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandDisabledProfile"), CommandType.Stop, profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandDisabledProfile"), CommandType.Stop, server.Profile.ProfileName));
}
+ // check if another command is being run against the profile
+ if (_currentProfileCommands.ContainsKey(server.Profile.ProfileID))
+ {
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[server.Profile.ProfileID], server.Profile.ProfileName));
+ }
+
+ key = server.Profile.ProfileID;
+ _currentProfileCommands.Add(key, CommandType.Stop);
+
switch (server.Runtime.Status)
{
case ServerStatus.Initializing:
@@ -506,10 +585,10 @@ namespace ServerManagerTool.Utils
case ServerStatus.Stopped:
case ServerStatus.Uninstalled:
case ServerStatus.Unknown:
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileBadStatus"), profileId, server.Runtime.StatusString));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileBadStatus"), server.Profile.ProfileName, server.Runtime.StatusString));
case ServerStatus.Updating:
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileUpdating"), profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileUpdating"), server.Profile.ProfileName));
}
profile = ServerProfileSnapshot.Create(server.Profile);
@@ -523,13 +602,15 @@ namespace ServerManagerTool.Utils
OutputLogs = false,
SendAlerts = true,
SendEmails = false,
- ServerProcess = ServerProcessType.Shutdown,
+ ServerProcess = ServerProcessType.Stop,
ShutdownInterval = 0,
ServerStatusChangeCallback = (ServerStatus serverStatus) =>
{
TaskUtils.RunOnUIThreadAsync(() =>
{
- var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
+ var server = ServerManager.Instance.Servers.First(s => string.Equals(channelId, s.Profile.DiscordChannelId, StringComparison.OrdinalIgnoreCase)
+ && (string.Equals(profileIdOrAlias, s.Profile.ProfileID, StringComparison.OrdinalIgnoreCase)
+ || !string.IsNullOrWhiteSpace(s.Profile.DiscordAlias) && string.Equals(profileIdOrAlias, s.Profile.DiscordAlias, StringComparison.OrdinalIgnoreCase)));
server.Runtime.UpdateServerStatus(serverStatus, true);
}).Wait();
}
@@ -538,7 +619,7 @@ namespace ServerManagerTool.Utils
task = Task.Run(() =>
{
app.PerformProfileShutdown(profile, false, false, false, token);
- _currentProfileCommands.Remove(profileId);
+ _currentProfileCommands.Remove(key);
});
response.Add(string.Format(_globalizer.GetResourceString("DiscordBot_StopRequested"), profile.ServerName));
@@ -549,24 +630,19 @@ namespace ServerManagerTool.Utils
{
if (task is null)
{
- _currentProfileCommands.Remove(profileId);
+ _currentProfileCommands.Remove(key);
}
}
}
- private static IList StartServer(string channelId, string profileId, CancellationToken token)
+ private static IList StartServer(string channelId, string profileIdOrAlias, CancellationToken token)
{
- if (string.IsNullOrWhiteSpace(profileId))
+ if (string.IsNullOrWhiteSpace(profileIdOrAlias))
{
return new List { string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMissing"), CommandType.Start) };
}
- // check if another command is being run against the profile
- if (_currentProfileCommands.ContainsKey(profileId))
- {
- return new List { string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[profileId], profileId) };
- }
- _currentProfileCommands.Add(profileId, CommandType.Start);
+ var key = string.Empty;
ServerProfileSnapshot profile = null;
Task task = null;
@@ -575,18 +651,35 @@ namespace ServerManagerTool.Utils
{
TaskUtils.RunOnUIThreadAsync(() =>
{
- var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
+ var serverList = ServerManager.Instance.Servers.Where(s => string.Equals(channelId, s.Profile.DiscordChannelId, StringComparison.OrdinalIgnoreCase)
+ && (string.Equals(profileIdOrAlias, s.Profile.ProfileID, StringComparison.OrdinalIgnoreCase)
+ || !string.IsNullOrWhiteSpace(s.Profile.DiscordAlias) && string.Equals(profileIdOrAlias, s.Profile.DiscordAlias, StringComparison.OrdinalIgnoreCase)));
- if (server is null)
+ if (serverList.IsEmpty())
{
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileIdOrAlias));
}
+ if (!serverList.HasOne())
+ {
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMultiples"), profileIdOrAlias));
+ }
+
+ var server = serverList.First();
if (!server.Profile.AllowDiscordStart)
{
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandDisabledProfile"), CommandType.Start, profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandDisabledProfile"), CommandType.Start, server.Profile.ProfileName));
}
+ // check if another command is being run against the profile
+ if (_currentProfileCommands.ContainsKey(server.Profile.ProfileID))
+ {
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[server.Profile.ProfileID], server.Profile.ProfileName));
+ }
+
+ key = server.Profile.ProfileID;
+ _currentProfileCommands.Add(key, CommandType.Start);
+
switch (server.Runtime.Status)
{
case ServerStatus.Initializing:
@@ -594,10 +687,10 @@ namespace ServerManagerTool.Utils
case ServerStatus.Running:
case ServerStatus.Uninstalled:
case ServerStatus.Unknown:
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileBadStatus"), profileId, server.Runtime.StatusString));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileBadStatus"), server.Profile.ProfileName, server.Runtime.StatusString));
case ServerStatus.Updating:
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileUpdating"), profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileUpdating"), server.Profile.ProfileName));
}
profile = ServerProfileSnapshot.Create(server.Profile);
@@ -617,7 +710,9 @@ namespace ServerManagerTool.Utils
{
TaskUtils.RunOnUIThreadAsync(() =>
{
- var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
+ var server = ServerManager.Instance.Servers.First(s => string.Equals(channelId, s.Profile.DiscordChannelId, StringComparison.OrdinalIgnoreCase)
+ && (string.Equals(profileIdOrAlias, s.Profile.ProfileID, StringComparison.OrdinalIgnoreCase)
+ || !string.IsNullOrWhiteSpace(s.Profile.DiscordAlias) && string.Equals(profileIdOrAlias, s.Profile.DiscordAlias, StringComparison.OrdinalIgnoreCase)));
server.Runtime.UpdateServerStatus(serverStatus, true);
}).Wait();
}
@@ -626,7 +721,7 @@ namespace ServerManagerTool.Utils
task = Task.Run(() =>
{
app.PerformProfileShutdown(profile, true, false, false, token);
- _currentProfileCommands.Remove(profileId);
+ _currentProfileCommands.Remove(key);
});
response.Add(string.Format(_globalizer.GetResourceString("DiscordBot_StartRequested"), profile.ServerName));
@@ -637,24 +732,19 @@ namespace ServerManagerTool.Utils
{
if (task is null)
{
- _currentProfileCommands.Remove(profileId);
+ _currentProfileCommands.Remove(key);
}
}
}
- private static IList UpdateServer(string channelId, string profileId, CancellationToken token)
+ private static IList UpdateServer(string channelId, string profileIdOrAlias, CancellationToken token)
{
- if (string.IsNullOrWhiteSpace(profileId))
+ if (string.IsNullOrWhiteSpace(profileIdOrAlias))
{
return new List { string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMissing"), CommandType.Update) };
}
- // check if another command is being run against the profile
- if (_currentProfileCommands.ContainsKey(profileId))
- {
- return new List { string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[profileId], profileId) };
- }
- _currentProfileCommands.Add(profileId, CommandType.Update);
+ var key = string.Empty;
ServerProfileSnapshot profile = null;
bool performRestart = false;
@@ -664,31 +754,48 @@ namespace ServerManagerTool.Utils
{
TaskUtils.RunOnUIThreadAsync(() =>
{
- var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
+ var serverList = ServerManager.Instance.Servers.Where(s => string.Equals(channelId, s.Profile.DiscordChannelId, StringComparison.OrdinalIgnoreCase)
+ && (string.Equals(profileIdOrAlias, s.Profile.ProfileID, StringComparison.OrdinalIgnoreCase)
+ || !string.IsNullOrWhiteSpace(s.Profile.DiscordAlias) && string.Equals(profileIdOrAlias, s.Profile.DiscordAlias, StringComparison.OrdinalIgnoreCase)));
- if (server is null)
+ if (serverList.IsEmpty())
{
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileIdOrAlias));
}
+ if (!serverList.HasOne())
+ {
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMultiples"), profileIdOrAlias));
+ }
+
+ var server = serverList.First();
if (!server.Profile.AllowDiscordUpdate)
{
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandDisabledProfile"), CommandType.Update, profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandDisabledProfile"), CommandType.Update, server.Profile.ProfileName));
}
+ // check if another command is being run against the profile
+ if (_currentProfileCommands.ContainsKey(server.Profile.ProfileID))
+ {
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[server.Profile.ProfileID], server.Profile.ProfileName));
+ }
+
+ key = server.Profile.ProfileID;
+ _currentProfileCommands.Add(key, CommandType.Update);
+
switch (server.Runtime.Status)
{
case ServerStatus.Initializing:
case ServerStatus.Stopping:
case ServerStatus.Unknown:
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileBadStatus"), profileId, server.Runtime.StatusString));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileBadStatus"), server.Profile.ProfileName, server.Runtime.StatusString));
case ServerStatus.Running:
performRestart = true;
break;
case ServerStatus.Updating:
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileUpdating"), profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileUpdating"), server.Profile.ProfileName));
}
profile = ServerProfileSnapshot.Create(server.Profile);
@@ -707,7 +814,9 @@ namespace ServerManagerTool.Utils
{
TaskUtils.RunOnUIThreadAsync(() =>
{
- var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
+ var server = ServerManager.Instance.Servers.First(s => string.Equals(channelId, s.Profile.DiscordChannelId, StringComparison.OrdinalIgnoreCase)
+ && (string.Equals(profileIdOrAlias, s.Profile.ProfileID, StringComparison.OrdinalIgnoreCase)
+ || !string.IsNullOrWhiteSpace(s.Profile.DiscordAlias) && string.Equals(profileIdOrAlias, s.Profile.DiscordAlias, StringComparison.OrdinalIgnoreCase)));
server.Runtime.UpdateServerStatus(serverStatus, true);
}).Wait();
}
@@ -716,7 +825,7 @@ namespace ServerManagerTool.Utils
task = Task.Run(() =>
{
app.PerformProfileShutdown(profile, performRestart, true, false, token);
- _currentProfileCommands.Remove(profileId);
+ _currentProfileCommands.Remove(key);
});
response.Add(string.Format(_globalizer.GetResourceString("DiscordBot_UpdateRequested"), profile.ServerName));
@@ -727,7 +836,7 @@ namespace ServerManagerTool.Utils
{
if (task is null)
{
- _currentProfileCommands.Remove(profileId);
+ _currentProfileCommands.Remove(key);
}
}
}
diff --git a/src/ARKServerManager/Utils/ModUtils.cs b/src/ARKServerManager/Utils/ModUtils.cs
index 54e22ef3..9ab371fe 100644
--- a/src/ARKServerManager/Utils/ModUtils.cs
+++ b/src/ARKServerManager/Utils/ModUtils.cs
@@ -46,15 +46,15 @@ namespace ServerManagerTool.Utils
}
}
- public static void AddOfficialMods(IEnumerable modIds)
+ public static void AddOfficialMods(List modIds)
{
if (OfficialMods == null)
OfficialMods = new List();
if (modIds != null)
{
- var modIdsToAdd = modIds.Where(m => !string.IsNullOrWhiteSpace(m) && !OfficialMods.Contains(m)).Distinct().ToList();
- if (modIdsToAdd != null && modIdsToAdd.Count > 0)
+ var modIdsToAdd = modIds.Where(m => !string.IsNullOrWhiteSpace(m) && !OfficialMods.Contains(m)).Distinct();
+ if (modIdsToAdd.Any())
{
OfficialMods.AddRange(modIdsToAdd);
}
@@ -170,14 +170,14 @@ namespace ServerManagerTool.Utils
return string.Empty;
// split the map string into parts, using the '/' separator.
- var parts = serverMap.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries).ToList();
+ var parts = serverMap.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
long mapModId;
- if (parts.Count == 1 && long.TryParse(parts[0], out mapModId))
+ if (parts.Length == 1 && long.TryParse(parts[0], out mapModId))
return mapModId.ToString();
// check if any parts were returned.
- if (parts.Count != 4)
+ if (parts.Length != 4)
return string.Empty;
// check if the first two parts match what is expected.
@@ -194,12 +194,12 @@ namespace ServerManagerTool.Utils
return string.Empty;
// split the map string into parts, using the '/' separator.
- var parts = serverMap.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries).ToList();
+ var parts = serverMap.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
// check if any parts were returned.
- if (parts.Count == 1)
+ if (parts.Length == 1)
return serverMap;
- if (parts.Count != 4)
+ if (parts.Length != 4)
return string.Empty;
// check if the first two parts match what is expected.
@@ -496,9 +496,9 @@ namespace ServerManagerTool.Utils
return new List();
// remove all null, empty, duplicate and Official mod ids.
- var newModIdList = modIdList.Where(m => !string.IsNullOrWhiteSpace(m) && !IsOfficialMod(m)).Distinct().ToList();
+ var newModIdList = modIdList.Where(m => !string.IsNullOrWhiteSpace(m) && !IsOfficialMod(m)).Distinct();
- return newModIdList;
+ return newModIdList.ToList();
}
public static void WriteModFile(string fileName, string modId, Dictionary metaInformation, List mapNames)
diff --git a/src/ARKServerManager/VersionFeed.xml b/src/ARKServerManager/VersionFeed.xml
index 50b77e95..eb307a69 100644
--- a/src/ARKServerManager/VersionFeed.xml
+++ b/src/ARKServerManager/VersionFeed.xml
@@ -5,14 +5,85 @@
Ark Server Manager Version Feed
This is the Ark Server Manager release version feed.
- 2021-12-12T00:00:00Z
+ 2021-12-17T00:00:00Z
+
+
+ urn:uuid:3E33DCB2-ECFE-4489-B1A4-56F5D386F9DC
+ 1.1.413 (1.1.413.8)
+ 1.1.413.8
+
+ 2021-12-17T00:00:00Z
+
+
+
+ NEW
+
+
+ Main Window - Added Discord Bot Status and a button to Stop/Start the discord bot.
+ Global Settings - Discord Bot section - Added a log level droplist.
+ Global Settings - Discord Bot section - Added a checkbox to allow all bots.
+ Global Settings - Discord Bot section - Added a whitelist to allow bots to send commands to the server manager.
+ Server Settings - Discord Bot section - Added an alias that can be used with the discord command instead of the profile id.
+
+
CHANGE
+
+
+ Discord Bot - all commands are now case INsensitive, along with the profile id and the alias.
+ Discord Bot - removed the mandatory requirement to enter the '!' after the discord prefix. The '!' has been added to the existing prefix so no change to existing functionality, but you can now change it.
+ Made changes to the code to help improve performance.
+ pt-BR Translation file updated.
+ ru-RU Translation file updated.
+ zh-CN Translation file updated.
+
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
+
+
+ urn:uuid:18276A38-2C71-4BB8-9A83-96D5EBFE9C87
+ 1.1.412 (1.1.412.4)
+ 1.1.412.4
+
+ 2021-12-15T00:00:00Z
+
+
+
+ BUGFIX
+
+
+ Fixed a bug with the Server Shutdown when the CheckForOnlinePlayers option not selected.
+ Fixed a bug when the backup path was a root directory that caused a 'Invalid URI: A Dos path must be rooted' crash.
+ Added additional validation when setting directories in the global setting, to ensure they are rooted correctly.
+ Fixed a bug when starting the server manager and it tries to download steamcmd, but fails as steamcmd is unavailable for download.
+
+
CHANGE
+
+
+ fr-FR Translation file updated.
+ zh-CN Translation file updated.
+ Added LostIsland to official mods in the SurvivalEvolved gamedata file.
+ Added coloring to the setting grids for the Lost Island DLC engrams, creatures and resources.
+
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
urn:uuid:DBAFCE91-2235-4B6C-AE9B-5E4EF9FEC8F5
- 1.1.411 (1.1.411.6)
- 1.1.411.6
+ 1.1.411 (1.1.411.10)
+ 1.1.411.10
- 2021-12-12T00:00:00Z
+ 2021-12-14T00:00:00Z
@@ -35,6 +106,7 @@
Global Settings - Added reset button to the Data Directory Location.
Server Monitor window now stores it's location.
+ Removed MOTD and Alternate Save Directory from the Administration section of the Sync.
fr-FR Translation file updated.
pt-BR Translation file updated.
ru-RU Translation file updated.
diff --git a/src/ARKServerManager/VersionFeedBeta.xml b/src/ARKServerManager/VersionFeedBeta.xml
index 559b5624..0f5abe1b 100644
--- a/src/ARKServerManager/VersionFeedBeta.xml
+++ b/src/ARKServerManager/VersionFeedBeta.xml
@@ -5,22 +5,45 @@
Ark Server Manager Version Feed
This is the Ark Server Manager beta version feed.
- 2021-12-12T00:00:00Z
+ 2021-12-16T00:00:00Z
- urn:uuid:C02D44F9-E3AA-4CA0-BF2F-110F8C83CC21
- 1.1.411 (1.1.411.7)
- 1.1.411.7
+ urn:uuid:8EE5659C-18E6-47D3-941D-C32B129D2E06
+ 1.1.413 (1.1.413.8)
+ 1.1.413.8
- 2021-12-12T00:00:00Z
+ 2021-12-17T00:00:00Z
+
+
+
+ CHANGE
+
+
+ Discord Bot - all commands are now case INsensitive, along with the profile id and the alias.
+
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
+
+
+ urn:uuid:8EE5659C-18E6-47D3-941D-C32B129D2E06
+ 1.1.413 (1.1.413.7)
+ 1.1.413.7
+
+ 2021-12-17T00:00:00Z
NEW
- Added gamedata file for the Lost Island DLC - only contains the map name for the Map droplist - do not use until the DLC is officially released!
- Added Lost Island to the language files for translation.
+ Main Window - Added Discord Bot Status and a button to Stop/Start the discord bot.
+ Global Settings - Discord Bot section - Added a checkbox to allow all bots.
@@ -32,42 +55,18 @@
- urn:uuid:F75C6AFF-2A27-49BE-917A-7EAAACCCBF17
- 1.1.411 (1.1.411.6)
- 1.1.411.6
+ urn:uuid:65A7E6B1-98D1-422D-B42F-B0EBB1D20E41
+ 1.1.413 (1.1.413.6)
+ 1.1.413.6
- 2021-12-12T00:00:00Z
+ 2021-12-17T00:00:00Z
CHANGE
- fr-FR Translation file updated.
-
-
-
-
-
- bletch
- bletch1971@hotmail.com
-
-
-
-
- urn:uuid:0BCB8BBA-330F-4063-8B7E-5B144589999A
- 1.1.411 (1.1.411.5)
- 1.1.411.5
-
- 2021-12-10T00:00:00Z
-
-
-
- CHANGE
-
-
- Server Monitor window now stores it's location.
- Reference library updates.
+ Added additional message logging when log level set to debug.
pt-BR Translation file updated.
ru-RU Translation file updated.
@@ -81,29 +80,69 @@
- urn:uuid:7697EBD7-DEF6-422B-B9A6-D4B77F31D572
- 1.1.411 (1.1.411.4)
- 1.1.411.4
+ urn:uuid:65A7E6B1-98D1-422D-B42F-B0EBB1D20E41
+ 1.1.413 (1.1.413.5)
+ 1.1.413.5
- 2021-12-09T00:00:00Z
+ 2021-12-16T00:00:00Z
+
+
+
+ NEW
+
+
+ Global Settings - Discord Bot section - Added a log level droplist.
+
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
+
+
+ urn:uuid:98FFBFA1-4E99-4801-BF2B-CA68BE300C27
+ 1.1.413 (1.1.413.4)
+ 1.1.413.4
+
+ 2021-12-16T00:00:00Z
BUGFIX
- Fixed a minor issue when clicking the data directory reset button - fringe case that I found during testing.
+ Fixed a bug that would prevent a bot on the whitelist processing the message.
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
+
+
+ urn:uuid:8958A494-DE13-4F6F-ACA2-10026D5FB8A9
+ 1.1.413 (1.1.413.3)
+ 1.1.413.3
+
+ 2021-12-16T00:00:00Z
+
+
+
NEW
- Server Settings - Dino Section - Added MutagenLevelBoost and MutagenLevelBoostBred settings.
+ Server Settings - Discord Bot section - Added an alias that can be used with the discord command instead of the profile id.
CHANGE
- pt-BR Translation file updated.
- ru-RU Translation file updated.
+ Removed the mandatory requirement to enter the '!' after the discord prefix. The '!' has been added to the existing prefix so no change to existing functionality, but you can now change it.
zh-CN Translation file updated.
@@ -116,73 +155,41 @@
- urn:uuid:8290F43D-98F4-4F4D-8DD8-0A3EF5A45656
- 1.1.411 (1.1.411.3)
- 1.1.411.3
+ urn:uuid:8958A494-DE13-4F6F-ACA2-10026D5FB8A9
+ 1.1.413 (1.1.413.2)
+ 1.1.413.2
- 2021-12-08T00:00:00Z
-
-
-
- BUGFIX
-
-
- Fixed language translation of Data Directory window.
-
-
-
-
-
- bletch
- bletch1971@hotmail.com
-
-
-
-
- urn:uuid:ADBF3FE0-017C-4E23-8FE8-EFE75E7C8BA1
- 1.1.411 (1.1.411.2)
- 1.1.411.2
-
- 2021-12-08T00:00:00Z
-
-
-
- CHANGE
-
-
- Global Settings - Added reset button to the Data Directory Location.
- pt-BR Translation file updated.
- zh-CN Translation file updated.
-
-
-
-
-
- bletch
- bletch1971@hotmail.com
-
-
-
-
- urn:uuid:DBAFCE91-2235-4B6C-AE9B-5E4EF9FEC8F5
- 1.1.411 (1.1.411.1)
- 1.1.411.1
-
- 2021-12-06T00:00:00Z
+ 2021-12-16T00:00:00Z
NEW
-
- A new Discord Bot has been added to the server manager.
- This new discord bot will allow you to send Start, Stop, Shutdown, Restart, Backup and Update commands to the server manager from within your discord client.
- To setup the new discord bot, open the global settings and scroll down to the Discord section.
-
- NOTE: This is long process to get the discord bot working, and I have created a forum post with detailed instructions how to do it.
-
-
+ Global Settings - Discord Bot section - Added a whitelist to allow bots to send commands to the server manager.
+
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
+
+
+ urn:uuid:3E33DCB2-ECFE-4489-B1A4-56F5D386F9DC
+ 1.1.413 (1.1.413.1)
+ 1.1.413.1
+
+ 2021-12-16T00:00:00Z
+
+
+
+ CHANGE
+
+
+ Made changes to the code to help improve performance.
diff --git a/src/ARKServerManager/Windows/AutoUpdateWindow.xaml b/src/ARKServerManager/Windows/AutoUpdateWindow.xaml
index 0df8f2ca..011a4957 100644
--- a/src/ARKServerManager/Windows/AutoUpdateWindow.xaml
+++ b/src/ARKServerManager/Windows/AutoUpdateWindow.xaml
@@ -17,6 +17,7 @@
+
diff --git a/src/ARKServerManager/Windows/AutoUpdateWindow.xaml.cs b/src/ARKServerManager/Windows/AutoUpdateWindow.xaml.cs
index 4f998b70..6036ae8c 100644
--- a/src/ARKServerManager/Windows/AutoUpdateWindow.xaml.cs
+++ b/src/ARKServerManager/Windows/AutoUpdateWindow.xaml.cs
@@ -2,6 +2,7 @@
using ServerManagerTool.Common.Utils;
using System;
using System.Threading;
+using System.Threading.Tasks;
using System.Windows;
using WPFSharp.Globalizer;
@@ -12,15 +13,16 @@ namespace ServerManagerTool
///
public partial class AutoUpdateWindow : Window
{
- private GlobalizedApplication _globalizer = GlobalizedApplication.Instance;
-
- private SteamCmdUpdater updater = new SteamCmdUpdater();
+ private readonly GlobalizedApplication _globalizer = GlobalizedApplication.Instance;
+ private readonly SteamCmdUpdater updater = new SteamCmdUpdater();
private CancellationTokenSource cancelSource;
public AutoUpdateWindow()
{
InitializeComponent();
WindowUtils.RemoveDefaultResourceDictionary(this, Config.Default.DefaultGlobalizationFile);
+
+ this.ErrorLabel.Visibility = Visibility.Collapsed;
}
private void Window_Loaded(object sender, RoutedEventArgs e)
@@ -32,10 +34,13 @@ namespace ServerManagerTool
this.StatusLabel.Content = message;
this.CompletionProgress.Value = u.CompletionPercent;
- if(u.FailureText != null)
+ if (u.FailureText != null)
{
- // TODO: Report error through UI
- throw new Exception(u.FailureText);
+ this.ErrorLabel.Text = u.FailureText;
+ this.ErrorLabel.Visibility = Visibility.Visible;
+ await Task.Delay(10000);
+
+ Environment.Exit(1);
}
if (u.CompletionPercent >= 100 || u.Cancelled)
diff --git a/src/ARKServerManager/Windows/MainWindow.xaml b/src/ARKServerManager/Windows/MainWindow.xaml
index 2c7bd445..cbaf9329 100644
--- a/src/ARKServerManager/Windows/MainWindow.xaml
+++ b/src/ARKServerManager/Windows/MainWindow.xaml
@@ -9,6 +9,7 @@
xmlns:cvr="clr-namespace:ServerManagerTool.Common.ValidationRules;assembly=ServerManager.Common"
xmlns:com="clr-namespace:ServerManagerTool.Common;assembly=ServerManager.Common"
xmlns:enum="clr-namespace:ServerManagerTool.Enums"
+ xmlns:bot="clr-namespace:ServerManagerTool.DiscordBot;assembly=ServerManager.Discord"
MinWidth="900" MinHeight="600" Width="1100" Height="900" Left="50" Top="50" WindowState="Normal"
Loaded="MainWindow_Loaded" SizeChanged="MainWindow_SizeChanged" StateChanged="MainWindow_StateChanged" LocationChanged="MainWindow_LocationChanged"
Name="Main" Icon="../Art/favicon.ico" Title="{DynamicResource MainWindow_Title}">
@@ -33,7 +34,7 @@
+
+
+
+
+
+
+
+
@@ -277,7 +334,7 @@
-
+
@@ -310,7 +367,7 @@
-
+
@@ -318,7 +375,7 @@
-
+
@@ -329,7 +386,7 @@
-
+
@@ -337,7 +394,7 @@
-
+
diff --git a/src/ARKServerManager/Windows/MainWindow.xaml.cs b/src/ARKServerManager/Windows/MainWindow.xaml.cs
index 1b95b8ed..ad172d40 100644
--- a/src/ARKServerManager/Windows/MainWindow.xaml.cs
+++ b/src/ARKServerManager/Windows/MainWindow.xaml.cs
@@ -27,45 +27,80 @@ namespace ServerManagerTool
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
- public static MainWindow Instance
- {
- get;
- private set;
- }
-
private readonly GlobalizedApplication _globalizer = GlobalizedApplication.Instance;
private readonly ActionQueue versionChecker;
private readonly ActionQueue scheduledTaskChecker;
+ private readonly ActionQueue discordBotChecker;
- public static readonly DependencyProperty BetaVersionProperty = DependencyProperty.Register(nameof(BetaVersion), typeof(bool), typeof(MainWindow), new PropertyMetadata(false));
- public static readonly DependencyProperty IsIpValidProperty = DependencyProperty.Register(nameof(IsIpValid), typeof(bool), typeof(MainWindow));
- public static readonly DependencyProperty CurrentConfigProperty = DependencyProperty.Register(nameof(CurrentConfig), typeof(Config), typeof(MainWindow));
+ private bool discordBotStateClicked = false;
+
+ public static readonly DependencyProperty AppInstanceProperty = DependencyProperty.Register(nameof(AppInstance), typeof(App), typeof(MainWindow), new PropertyMetadata(null));
+ public static readonly DependencyProperty ConfigProperty = DependencyProperty.Register(nameof(Config), typeof(Config), typeof(MainWindow), new PropertyMetadata(null));
public static readonly DependencyProperty ServerManagerProperty = DependencyProperty.Register(nameof(ServerManager), typeof(ServerManager), typeof(MainWindow), new PropertyMetadata(null));
- public static readonly DependencyProperty LatestASMVersionProperty = DependencyProperty.Register(nameof(LatestASMVersion), typeof(Version), typeof(MainWindow), new PropertyMetadata(new Version()));
- public static readonly DependencyProperty NewASMAvailableProperty = DependencyProperty.Register(nameof(NewASMAvailable), typeof(bool), typeof(MainWindow), new PropertyMetadata(false));
public static readonly DependencyProperty AutoBackupStateProperty = DependencyProperty.Register(nameof(AutoBackupState), typeof(Microsoft.Win32.TaskScheduler.TaskState), typeof(MainWindow), new PropertyMetadata(Microsoft.Win32.TaskScheduler.TaskState.Unknown));
public static readonly DependencyProperty AutoBackupStateStringProperty = DependencyProperty.Register(nameof(AutoBackupStateString), typeof(string), typeof(MainWindow), new PropertyMetadata(string.Empty));
public static readonly DependencyProperty AutoBackupNextRunTimeProperty = DependencyProperty.Register(nameof(AutoBackupNextRunTime), typeof(string), typeof(MainWindow), new PropertyMetadata(string.Empty));
public static readonly DependencyProperty AutoUpdateStateProperty = DependencyProperty.Register(nameof(AutoUpdateState), typeof(Microsoft.Win32.TaskScheduler.TaskState), typeof(MainWindow), new PropertyMetadata(Microsoft.Win32.TaskScheduler.TaskState.Unknown));
public static readonly DependencyProperty AutoUpdateStateStringProperty = DependencyProperty.Register(nameof(AutoUpdateStateString), typeof(string), typeof(MainWindow), new PropertyMetadata(string.Empty));
public static readonly DependencyProperty AutoUpdateNextRunTimeProperty = DependencyProperty.Register(nameof(AutoUpdateNextRunTime), typeof(string), typeof(MainWindow), new PropertyMetadata(string.Empty));
+ public static readonly DependencyProperty DiscordBotStateProperty = DependencyProperty.Register(nameof(DiscordBotState), typeof(DiscordBot.Enums.BotState), typeof(MainWindow), new PropertyMetadata(DiscordBot.Enums.BotState.Unknown));
+ public static readonly DependencyProperty DiscordBotStateStringProperty = DependencyProperty.Register(nameof(DiscordBotStateString), typeof(string), typeof(MainWindow), new PropertyMetadata(string.Empty));
+ public static readonly DependencyProperty IsIpValidProperty = DependencyProperty.Register(nameof(IsIpValid), typeof(bool), typeof(MainWindow), new PropertyMetadata(false));
+ public static readonly DependencyProperty LatestServerManagerVersionProperty = DependencyProperty.Register(nameof(LatestServerManagerVersion), typeof(Version), typeof(MainWindow), new PropertyMetadata(new Version()));
+ public static readonly DependencyProperty NewServerManagerAvailableProperty = DependencyProperty.Register(nameof(NewServerManagerAvailable), typeof(bool), typeof(MainWindow), new PropertyMetadata(false));
- public bool BetaVersion
+ public MainWindow()
{
- get { return (bool)GetValue(BetaVersionProperty); }
- set { SetValue(BetaVersionProperty, value); }
+ this.AppInstance = App.Instance;
+ this.Config = Config.Default;
+
+ InitializeComponent();
+ WindowUtils.RemoveDefaultResourceDictionary(this, Config.Default.DefaultGlobalizationFile);
+
+ this.ServerManager = ServerManager.Instance;
+
+ this.DataContext = this;
+ this.versionChecker = new ActionQueue();
+ this.scheduledTaskChecker = new ActionQueue();
+ this.discordBotChecker = new ActionQueue();
+
+ IsAdministrator = SecurityUtils.IsAdministrator();
+ if (!string.IsNullOrWhiteSpace(App.Instance.Title))
+ {
+ this.Title = App.Instance.Title;
+ }
+ else
+ {
+ if (IsAdministrator)
+ {
+ this.Title = _globalizer.GetResourceString("MainWindow_TitleWithAdmin");
+ }
+ else
+ {
+ this.Title = _globalizer.GetResourceString("MainWindow_Title");
+ }
+ }
+
+ this.Left = Config.Default.MainWindow_Left;
+ this.Top = Config.Default.MainWindow_Top;
+ this.Height = Config.Default.MainWindow_Height;
+ this.Width = Config.Default.MainWindow_Width;
+ this.WindowState = Config.Default.MainWindow_WindowState;
+
+ // hook into the language change event
+ GlobalizedApplication.Instance.GlobalizationManager.ResourceDictionaryChangedEvent += ResourceDictionaryChangedEvent;
}
- public bool IsIpValid
+ public App AppInstance
{
- get { return (bool)GetValue(IsIpValidProperty); }
- set { SetValue(IsIpValidProperty, value); }
+ get { return GetValue(AppInstanceProperty) as App; }
+ set { SetValue(AppInstanceProperty, value); }
}
- public Config CurrentConfig
+ public Config Config
{
- get { return GetValue(CurrentConfigProperty) as Config; }
- set { SetValue(CurrentConfigProperty, value); }
+ get { return GetValue(ConfigProperty) as Config; }
+ set { SetValue(ConfigProperty, value); }
}
public ServerManager ServerManager
@@ -74,18 +109,6 @@ namespace ServerManagerTool
set { SetValue(ServerManagerProperty, value); }
}
- public Version LatestASMVersion
- {
- get { return (Version)GetValue(LatestASMVersionProperty); }
- set { SetValue(LatestASMVersionProperty, value); }
- }
-
- public bool NewASMAvailable
- {
- get { return (bool)GetValue(NewASMAvailableProperty); }
- set { SetValue(NewASMAvailableProperty, value); }
- }
-
public Microsoft.Win32.TaskScheduler.TaskState AutoBackupState
{
get { return (Microsoft.Win32.TaskScheduler.TaskState)GetValue(AutoBackupStateProperty); }
@@ -122,52 +145,40 @@ namespace ServerManagerTool
set { SetValue(AutoUpdateNextRunTimeProperty, value); }
}
+ public DiscordBot.Enums.BotState DiscordBotState
+ {
+ get { return (DiscordBot.Enums.BotState)GetValue(DiscordBotStateProperty); }
+ set { SetValue(DiscordBotStateProperty, value); }
+ }
+
+ public string DiscordBotStateString
+ {
+ get { return (string)GetValue(DiscordBotStateStringProperty); }
+ set { SetValue(DiscordBotStateStringProperty, value); }
+ }
+
public bool IsAdministrator
{
get;
set;
}
- public MainWindow()
+ public bool IsIpValid
{
- this.BetaVersion = App.Instance.BetaVersion;
- this.CurrentConfig = Config.Default;
+ get { return (bool)GetValue(IsIpValidProperty); }
+ set { SetValue(IsIpValidProperty, value); }
+ }
- InitializeComponent();
- WindowUtils.RemoveDefaultResourceDictionary(this, Config.Default.DefaultGlobalizationFile);
+ public Version LatestServerManagerVersion
+ {
+ get { return (Version)GetValue(LatestServerManagerVersionProperty); }
+ set { SetValue(LatestServerManagerVersionProperty, value); }
+ }
- MainWindow.Instance = this;
- this.ServerManager = ServerManager.Instance;
-
- this.DataContext = this;
- this.versionChecker = new ActionQueue();
- this.scheduledTaskChecker = new ActionQueue();
-
- IsAdministrator = SecurityUtils.IsAdministrator();
- if (!string.IsNullOrWhiteSpace(App.Instance.Title))
- {
- this.Title = $"{App.Instance.Title}";
- }
- else
- {
- if (IsAdministrator)
- {
- this.Title = _globalizer.GetResourceString("MainWindow_TitleWithAdmin");
- }
- else
- {
- this.Title = _globalizer.GetResourceString("MainWindow_Title");
- }
- }
-
- this.Left = Config.Default.MainWindow_Left;
- this.Top = Config.Default.MainWindow_Top;
- this.Height = Config.Default.MainWindow_Height;
- this.Width = Config.Default.MainWindow_Width;
- this.WindowState = Config.Default.MainWindow_WindowState;
-
- // hook into the language change event
- GlobalizedApplication.Instance.GlobalizationManager.ResourceDictionaryChangedEvent += ResourceDictionaryChangedEvent;
+ public bool NewServerManagerAvailable
+ {
+ get { return (bool)GetValue(NewServerManagerAvailableProperty); }
+ set { SetValue(NewServerManagerAvailableProperty, value); }
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
@@ -198,6 +209,7 @@ namespace ServerManagerTool
this.versionChecker.PostAction(CheckForUpdates).DoNotWait();
this.scheduledTaskChecker.PostAction(CheckForScheduledTasks).DoNotWait();
+ this.discordBotChecker.PostAction(CheckForDiscordBot).DoNotWait();
}
private void MainWindow_LocationChanged(object sender, EventArgs e)
@@ -261,12 +273,13 @@ namespace ServerManagerTool
this.Title = _globalizer.GetResourceString("MainWindow_Title");
this.scheduledTaskChecker.PostAction(CheckForScheduledTasks).DoNotWait();
+ this.discordBotChecker.PostAction(CheckForDiscordBot).DoNotWait();
}
- private void ASMPatchNotes_Click(object sender, RoutedEventArgs e)
+ private void PatchNotes_Click(object sender, RoutedEventArgs e)
{
var url = string.Empty;
- if (BetaVersion)
+ if (AppInstance.BetaVersion)
url = Config.Default.ServerManagerVersionBetaFeedUrl;
else
url = Config.Default.ServerManagerVersionFeedUrl;
@@ -280,7 +293,7 @@ namespace ServerManagerTool
}
else
{
- if (BetaVersion)
+ if (AppInstance.BetaVersion)
url = Config.Default.LatestASMBetaPatchNotesUrl;
else
url = Config.Default.LatestASMPatchNotesUrl;
@@ -424,7 +437,7 @@ namespace ServerManagerTool
private async void Upgrade_Click(object sender, RoutedEventArgs e)
{
- var result = MessageBox.Show(String.Format(_globalizer.GetResourceString("MainWindow_Upgrade_Label"), this.LatestASMVersion), _globalizer.GetResourceString("MainWindow_Upgrade_Title"), MessageBoxButton.YesNo, MessageBoxImage.Question);
+ var result = MessageBox.Show(String.Format(_globalizer.GetResourceString("MainWindow_Upgrade_Label"), this.LatestServerManagerVersion), _globalizer.GetResourceString("MainWindow_Upgrade_Title"), MessageBoxButton.YesNo, MessageBoxImage.Question);
if(result == MessageBoxResult.Yes)
{
try
@@ -578,6 +591,36 @@ namespace ServerManagerTool
}
}
+ private async void DiscordBotTaskState_Click(object sender, RoutedEventArgs e)
+ {
+ if (discordBotStateClicked)
+ return;
+ discordBotStateClicked = true;
+
+ try
+ {
+ switch (DiscordBotState)
+ {
+ case DiscordBot.Enums.BotState.Stopped:
+ AppInstance.StartDiscordBot();
+ break;
+ case DiscordBot.Enums.BotState.Running:
+ AppInstance.StopDiscordBot();
+ break;
+ }
+
+ await Task.Delay(5000);
+ }
+ catch (Exception)
+ {
+ // Ignore.
+ }
+ finally
+ {
+ discordBotStateClicked = false;
+ }
+ }
+
public ICommand ShowWindowCommand
{
get
@@ -640,8 +683,8 @@ namespace ServerManagerTool
var appVersion = new Version();
Version.TryParse(App.Instance.Version, out appVersion);
- this.LatestASMVersion = newVersion;
- this.NewASMAvailable = appVersion < newVersion;
+ this.LatestServerManagerVersion = newVersion;
+ this.NewServerManagerAvailable = appVersion < newVersion;
Logger.Info($"{nameof(CheckForUpdates)} performed");
}
@@ -669,8 +712,8 @@ namespace ServerManagerTool
this.AutoBackupState = backupState;
this.AutoUpdateState = updateState;
- this.AutoBackupStateString = GetTaskStateString(AutoBackupState);
- this.AutoUpdateStateString = GetTaskStateString(AutoUpdateState);
+ this.AutoBackupStateString = GetTaskSchedulerStateString(AutoBackupState);
+ this.AutoUpdateStateString = GetTaskSchedulerStateString(AutoUpdateState);
this.AutoBackupNextRunTime = backupnextRunTime == DateTime.MinValue ? string.Empty : $"{_globalizer.GetResourceString("MainWindow_TaskRunTimeLabel")} {backupnextRunTime:G}";
this.AutoUpdateNextRunTime = updatenextRunTime == DateTime.MinValue ? string.Empty : $"{_globalizer.GetResourceString("MainWindow_TaskRunTimeLabel")} {updatenextRunTime:G}";
@@ -687,7 +730,46 @@ namespace ServerManagerTool
this.scheduledTaskChecker.PostAction(CheckForScheduledTasks).DoNotWait();
}
- private string GetTaskStateString(Microsoft.Win32.TaskScheduler.TaskState taskState)
+ private async Task CheckForDiscordBot()
+ {
+ TaskUtils.RunOnUIThreadAsync(() =>
+ {
+ try
+ {
+ var botState = DiscordBot.Enums.BotState.Unknown;
+ if (AppInstance.DiscordBotStarted)
+ {
+ botState = DiscordBot.Enums.BotState.Running;
+ }
+ else
+ {
+ if (Config.DiscordBotEnabled)
+ {
+ botState = DiscordBot.Enums.BotState.Stopped;
+ }
+ else
+ {
+ botState = DiscordBot.Enums.BotState.Disabled;
+ }
+ }
+
+ this.DiscordBotState = botState;
+
+ this.DiscordBotStateString = GetDiscordBotStateString(botState);
+
+ Logger.Info($"{nameof(CheckForDiscordBot)} performed");
+ }
+ catch (Exception)
+ {
+ // Ignore.
+ }
+ }).DoNotWait();
+
+ await Task.Delay(Config.Default.DiscordBotStatusCheckTime * 1 * 1000);
+ this.discordBotChecker.PostAction(CheckForDiscordBot).DoNotWait();
+ }
+
+ private string GetTaskSchedulerStateString(Microsoft.Win32.TaskScheduler.TaskState taskState)
{
switch (taskState)
{
@@ -706,6 +788,21 @@ namespace ServerManagerTool
}
}
+ private string GetDiscordBotStateString(DiscordBot.Enums.BotState botState)
+ {
+ switch (botState)
+ {
+ case DiscordBot.Enums.BotState.Disabled:
+ return _globalizer.GetResourceString("MainWindow_TaskStateDisabledLabel");
+ case DiscordBot.Enums.BotState.Running:
+ return _globalizer.GetResourceString("MainWindow_TaskStateRunningLabel");
+ case DiscordBot.Enums.BotState.Stopped:
+ return _globalizer.GetResourceString("MainWindow_TaskStateStoppedLabel");
+ default:
+ return _globalizer.GetResourceString("MainWindow_TaskStateUnknownLabel");
+ }
+ }
+
private async Task StartServerAsync(Server server)
{
if (server == null || server.Profile == null || server.Runtime == null || server.Runtime.Status != ServerStatus.Stopped)
diff --git a/src/ARKServerManager/Windows/RCONWindow.xaml.cs b/src/ARKServerManager/Windows/RCONWindow.xaml.cs
index e2ec9fbf..fb75190a 100644
--- a/src/ARKServerManager/Windows/RCONWindow.xaml.cs
+++ b/src/ARKServerManager/Windows/RCONWindow.xaml.cs
@@ -1,4 +1,5 @@
-using ServerManagerTool.Common.Lib;
+using ServerManagerTool.Common.Extensions;
+using ServerManagerTool.Common.Lib;
using ServerManagerTool.Common.Utils;
using ServerManagerTool.Enums;
using ServerManagerTool.Lib;
@@ -927,7 +928,7 @@ namespace ServerManagerTool
yield return new RCONOutput_Command($"> {command.rawCommand}");
}
- if(!command.suppressOutput && command.lines.Count() > 0)
+ if(!command.suppressOutput && !command.lines.IsEmpty())
{
yield return new LineBreak();
}
diff --git a/src/ARKServerManager/Windows/SettingsWindow.xaml b/src/ARKServerManager/Windows/SettingsWindow.xaml
index 19e1b951..f2826aa5 100644
--- a/src/ARKServerManager/Windows/SettingsWindow.xaml
+++ b/src/ARKServerManager/Windows/SettingsWindow.xaml
@@ -16,6 +16,6 @@
-
+
diff --git a/src/ARKServerManager/Windows/SettingsWindow.xaml.cs b/src/ARKServerManager/Windows/SettingsWindow.xaml.cs
index 58c918b6..c1981589 100644
--- a/src/ARKServerManager/Windows/SettingsWindow.xaml.cs
+++ b/src/ARKServerManager/Windows/SettingsWindow.xaml.cs
@@ -22,6 +22,8 @@ namespace ServerManagerTool
protected override void OnClosed(EventArgs e)
{
+ globalSettingsControl.ApplyChangesToConfig();
+
if (SecurityUtils.IsAdministrator())
{
// check if the Auto Update has been enabled.
diff --git a/src/ArkData/DataContainerAsync.cs b/src/ArkData/DataContainerAsync.cs
index a6a044ac..6a5472e2 100644
--- a/src/ArkData/DataContainerAsync.cs
+++ b/src/ArkData/DataContainerAsync.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
@@ -18,29 +19,35 @@ namespace ArkData
/// The async task context containing the resulting container.
public static async Task CreateAsync(string playerFileFolder, string tribeFileFolder)
{
- var playerFiles = new string[0];
- var tribeFiles = new string[0];
+ IEnumerable playerFiles = null;
+ IEnumerable tribeFiles = null;
if (Directory.Exists(playerFileFolder))
{
playerFiles = Directory.GetFiles(playerFileFolder).Where(f => Path.GetFileNameWithoutExtension(f).StartsWith(DataFileDetails.PlayerFilePrefix)
&& Path.GetFileNameWithoutExtension(f).EndsWith(DataFileDetails.PlayerFileSuffix)
- && Path.GetExtension(f).Equals(DataFileDetails.PlayerFileExtension)).ToArray();
+ && Path.GetExtension(f).Equals(DataFileDetails.PlayerFileExtension));
}
if (Directory.Exists(tribeFileFolder))
{
tribeFiles = Directory.GetFiles(tribeFileFolder).Where(f => Path.GetFileNameWithoutExtension(f).StartsWith(DataFileDetails.TribeFilePrefix)
&& Path.GetFileNameWithoutExtension(f).EndsWith(DataFileDetails.TribeFileSuffix)
- && Path.GetExtension(f).Equals(DataFileDetails.TribeFileExtension)).ToArray();
+ && Path.GetExtension(f).Equals(DataFileDetails.TribeFileExtension));
}
var container = new DataContainer();
- foreach (var file in playerFiles)
- container.Players.Add(await Parser.ParsePlayerAsync(file));
+ if (playerFiles != null)
+ {
+ foreach (var file in playerFiles)
+ container.Players.Add(await Parser.ParsePlayerAsync(file));
+ }
- foreach (var file in tribeFiles)
- container.Tribes.Add(await Parser.ParseTribeAsync(file));
+ if (tribeFiles != null)
+ {
+ foreach (var file in tribeFiles)
+ container.Tribes.Add(await Parser.ParseTribeAsync(file));
+ }
container.LinkPlayerTribe();
@@ -58,14 +65,14 @@ namespace ArkData
// need to make multiple calls of 100 steam id's.
var lastSteamUpdateUtc = DateTime.UtcNow;
var startIndex = 0;
- var playerSteamIds = Players.Where(p => p.LastPlatformUpdateUtc.AddMinutes(steamUpdateInterval) < DateTime.UtcNow).Select(p => p.PlayerId).ToArray();
+ var playerSteamIds = Players.Where(p => p.LastPlatformUpdateUtc.AddMinutes(steamUpdateInterval) < DateTime.UtcNow).Select(p => p.PlayerId);
while (true)
{
// check if the start index has exceeded the Players list count.
- if (startIndex >= playerSteamIds.Length) break;
+ if (startIndex >= playerSteamIds.Count()) break;
// get the number of steam ids to read.
- int steamIdsCount = System.Math.Min(MAX_STEAM_IDS, playerSteamIds.Length - startIndex);
+ int steamIdsCount = Math.Min(MAX_STEAM_IDS, playerSteamIds.Count() - startIndex);
// get a comma delimited list of the steam ids to process
var builder = string.Join(",", playerSteamIds, startIndex, steamIdsCount);
diff --git a/src/ArkData/DataContainerBase.cs b/src/ArkData/DataContainerBase.cs
index 0588c13c..99525a09 100644
--- a/src/ArkData/DataContainerBase.cs
+++ b/src/ArkData/DataContainerBase.cs
@@ -45,7 +45,7 @@ namespace ArkData
{
try
{
- var online = Enumerable.OfType(new SSQL().Players(new IPEndPoint(IPAddress.Parse(ipString), port))).ToList();
+ var online = Enumerable.OfType(new SSQL().Players(new IPEndPoint(IPAddress.Parse(ipString), port)));
for (var i = 0; i < Players.Count; i++)
{
diff --git a/src/ArkData/DataContainerSync.cs b/src/ArkData/DataContainerSync.cs
index cd1dd34d..b1d36194 100644
--- a/src/ArkData/DataContainerSync.cs
+++ b/src/ArkData/DataContainerSync.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
@@ -16,29 +17,35 @@ namespace ArkData
///
public static DataContainer Create(string playerFileFolder, string tribeFileFolder)
{
- var playerFiles = new string[0];
- var tribeFiles = new string[0];
+ IEnumerable playerFiles = null;
+ IEnumerable tribeFiles = null;
if (Directory.Exists(playerFileFolder))
{
playerFiles = Directory.GetFiles(playerFileFolder).Where(f => Path.GetFileNameWithoutExtension(f).StartsWith(DataFileDetails.PlayerFilePrefix)
&& Path.GetFileNameWithoutExtension(f).EndsWith(DataFileDetails.PlayerFileSuffix)
- && Path.GetExtension(f).Equals(DataFileDetails.PlayerFileExtension)).ToArray();
+ && Path.GetExtension(f).Equals(DataFileDetails.PlayerFileExtension));
}
if (Directory.Exists(tribeFileFolder))
{
tribeFiles = Directory.GetFiles(tribeFileFolder).Where(f => Path.GetFileNameWithoutExtension(f).StartsWith(DataFileDetails.TribeFilePrefix)
&& Path.GetFileNameWithoutExtension(f).EndsWith(DataFileDetails.TribeFileSuffix)
- && Path.GetExtension(f).Equals(DataFileDetails.TribeFileExtension)).ToArray();
+ && Path.GetExtension(f).Equals(DataFileDetails.TribeFileExtension));
}
var container = new DataContainer();
- foreach (var file in playerFiles)
- container.Players.Add(Parser.ParsePlayer(file));
+ if (playerFiles != null)
+ {
+ foreach (var file in playerFiles)
+ container.Players.Add(Parser.ParsePlayer(file));
+ }
- foreach (var file in tribeFiles)
- container.Tribes.Add(Parser.ParseTribe(file));
+ if (tribeFiles != null)
+ {
+ foreach (var file in tribeFiles)
+ container.Tribes.Add(Parser.ParseTribe(file));
+ }
container.LinkPlayerTribe();
@@ -56,14 +63,14 @@ namespace ArkData
// need to make multiple calls of 100 steam id's.
var lastSteamUpdateUtc = DateTime.UtcNow;
var startIndex = 0;
- var playerSteamIds = Players.Where(p => p.LastPlatformUpdateUtc.AddMinutes(steamUpdateInterval) < DateTime.UtcNow).Select(p => p.PlayerId).ToArray();
+ var playerSteamIds = Players.Where(p => p.LastPlatformUpdateUtc.AddMinutes(steamUpdateInterval) < DateTime.UtcNow).Select(p => p.PlayerId);
while (true)
{
// check if the start index has exceeded the Players list count.
- if (startIndex >= playerSteamIds.Length) break;
+ if (startIndex >= playerSteamIds.Count()) break;
// get the number of steam ids to read.
- int steamIdsCount = System.Math.Min(MAX_STEAM_IDS, playerSteamIds.Length - startIndex);
+ int steamIdsCount = Math.Min(MAX_STEAM_IDS, playerSteamIds.Count() - startIndex);
// get a comma delimited list of the steam ids to process
var builder = string.Join(",", playerSteamIds, startIndex, steamIdsCount);
diff --git a/src/ArkData/Extensions.cs b/src/ArkData/Extensions.cs
index df2ff5d7..a03c8958 100644
--- a/src/ArkData/Extensions.cs
+++ b/src/ArkData/Extensions.cs
@@ -18,7 +18,7 @@ namespace ArkData
return -1;
}
- public static int[] Locate(this byte[] self, byte[] candidate)
+ public static IEnumerable Locate(this byte[] self, byte[] candidate)
{
if (IsEmptyLocate(self, candidate, 0))
return Empty;
@@ -29,7 +29,7 @@ namespace ArkData
list.Add(position);
if (list.Count != 0)
- return list.ToArray();
+ return list;
return Empty;
}
diff --git a/src/ConanServerManager/App.config b/src/ConanServerManager/App.config
index bd610257..b96df230 100644
--- a/src/ConanServerManager/App.config
+++ b/src/ConanServerManager/App.config
@@ -263,6 +263,9 @@
https://servermanagers.freeforums.net/thread/99/get-own-discord-bot
+
+ 10
+
@@ -580,7 +583,7 @@
False
- csm
+ csm!
@@ -615,6 +618,20 @@
50
+
+
+
+
+
+
+ False
+
+
+ Info
+
+
+ False
+
\ No newline at end of file
diff --git a/src/ConanServerManager/App.xaml.cs b/src/ConanServerManager/App.xaml.cs
index f5ab9594..55b63548 100644
--- a/src/ConanServerManager/App.xaml.cs
+++ b/src/ConanServerManager/App.xaml.cs
@@ -10,6 +10,7 @@ using ServerManagerTool.Plugin.Common;
using ServerManagerTool.Utils;
using ServerManagerTool.Windows;
using System;
+using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
@@ -37,7 +38,7 @@ namespace ServerManagerTool
public event PropertyChangedEventHandler PropertyChanged;
- private CancellationTokenSource _tokenSource;
+ private CancellationTokenSource _tokenSourceDiscordBot;
private GlobalizedApplication _globalizer;
private bool _applicationStarted;
private string _args;
@@ -48,7 +49,45 @@ namespace ServerManagerTool
public App()
{
if (string.IsNullOrWhiteSpace(Config.Default.ServerManagerUniqueKey))
+ {
Config.Default.ServerManagerUniqueKey = Guid.NewGuid().ToString();
+ }
+
+ if (!string.IsNullOrWhiteSpace(Config.Default.DataPath))
+ {
+ var root = Path.GetPathRoot(Config.Default.DataPath);
+ if (!root.EndsWith("\\"))
+ {
+ Config.Default.DataPath = Config.Default.DataPath.Replace(root, root + "\\");
+ }
+ }
+
+ if (!string.IsNullOrWhiteSpace(Config.Default.ConfigPath))
+ {
+ var root = Path.GetPathRoot(Config.Default.ConfigPath);
+ if (!root.EndsWith("\\"))
+ {
+ Config.Default.ConfigPath = Config.Default.ConfigPath.Replace(root, root + "\\");
+ }
+ }
+
+ if (!string.IsNullOrWhiteSpace(Config.Default.BackupPath))
+ {
+ var root = Path.GetPathRoot(Config.Default.BackupPath);
+ if (!root.EndsWith("\\"))
+ {
+ Config.Default.BackupPath = Config.Default.BackupPath.Replace(root, root + "\\");
+ }
+ }
+
+ if (!string.IsNullOrWhiteSpace(Config.Default.AutoUpdate_CacheDir))
+ {
+ var root = Path.GetPathRoot(Config.Default.AutoUpdate_CacheDir);
+ if (!root.EndsWith("\\"))
+ {
+ Config.Default.AutoUpdate_CacheDir = Config.Default.AutoUpdate_CacheDir.Replace(root, root + "\\");
+ }
+ }
App.Instance = this;
ApplicationStarted = false;
@@ -111,6 +150,18 @@ namespace ServerManagerTool
}
}
+ public bool DiscordBotStarted
+ {
+ get
+ {
+ return _tokenSourceDiscordBot != null;
+ }
+ set
+ {
+ OnPropertyChanged();
+ }
+ }
+
public string Title
{
get
@@ -239,6 +290,14 @@ namespace ServerManagerTool
Config.Default.UpgradeConfig = false;
Config.Default.Save();
}
+ if (!Config.Default.DiscordBotPrefixFixed)
+ {
+ if (!Config.Default.DiscordBotPrefix.EndsWith("!"))
+ Config.Default.DiscordBotPrefix += "!";
+ Config.Default.DiscordBotPrefixFixed = true;
+ Config.Default.Save();
+ Config.Default.Reload();
+ }
Config.Default.SteamCmdRedirectOutput = false;
}
@@ -432,21 +491,7 @@ namespace ServerManagerTool
if (Config.Default.DiscordBotEnabled)
{
- _tokenSource = new CancellationTokenSource();
-
- Task discordTask = Task.Run(async () =>
- {
- await ServerManagerBotFactory.GetServerManagerBot()?.StartAsync(Config.Default.DiscordBotToken,Config.Default.DiscordBotPrefix, Config.Default.DataPath, DiscordBotHelper.HandleDiscordCommand, DiscordBotHelper.HandleTranslation, _tokenSource.Token);
- }, _tokenSource.Token)
- .ContinueWith(t => {
- var message = t.Exception.InnerException is null ? t.Exception.Message : t.Exception.InnerException.Message;
- if (message.StartsWith("#"))
- {
- message = _globalizer.GetResourceString(message.Substring(1)) ?? message.Substring(1);
- }
-
- MessageBox.Show(message, _globalizer.GetResourceString("DiscordBot_ErrorTitle"), MessageBoxButton.OK, MessageBoxImage.Error);
- }, TaskContinuationOptions.OnlyOnFaulted);
+ StartDiscordBot();
}
}
@@ -488,11 +533,7 @@ namespace ServerManagerTool
private void ShutDownApplication()
{
- if (!(_tokenSource is null))
- {
- _tokenSource.Cancel();
- _tokenSource.Dispose();
- }
+ StopDiscordBot();
if (this.ApplicationStarted)
{
@@ -525,13 +566,68 @@ namespace ServerManagerTool
var installFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var backupFolder = includeBackup
- ? IOUtils.NormalizePath(string.IsNullOrWhiteSpace(Config.Default.BackupPath)
+ ? string.IsNullOrWhiteSpace(Config.Default.BackupPath)
? Path.Combine(Config.Default.DataPath, Config.Default.BackupRelativePath)
- : Path.Combine(Config.Default.BackupPath))
+ : Path.Combine(Config.Default.BackupPath)
: null;
SettingsUtils.BackupUserConfigSettings(Config.Default, "userconfig.json", installFolder, backupFolder);
SettingsUtils.BackupUserConfigSettings(CommonConfig.Default, "commonconfig.json", installFolder, backupFolder);
}
+
+ public void StartDiscordBot()
+ {
+ if (_tokenSourceDiscordBot != null)
+ {
+ return;
+ }
+
+ _tokenSourceDiscordBot = new CancellationTokenSource();
+ DiscordBotStarted = true;
+
+ Task discordTask = Task.Run(async () =>
+ {
+ var discordWhiteList = new List();
+ if (Config.Default.DiscordBotWhitelist != null)
+ {
+ discordWhiteList.AddRange(Config.Default.DiscordBotWhitelist.Cast());
+ }
+
+ await ServerManagerBotFactory.GetServerManagerBot()?.StartAsync(Config.Default.DiscordBotLogLevel, Config.Default.DiscordBotToken, Config.Default.DiscordBotPrefix, Config.Default.DataPath, Config.Default.DiscordBotAllowAllBots, discordWhiteList, DiscordBotHelper.HandleDiscordCommand, DiscordBotHelper.HandleTranslation, _tokenSourceDiscordBot.Token);
+
+ if (_tokenSourceDiscordBot != null)
+ {
+ // cleanup the token
+ _tokenSourceDiscordBot.Dispose();
+ _tokenSourceDiscordBot = null;
+ }
+ DiscordBotStarted = false;
+ }, _tokenSourceDiscordBot.Token)
+ .ContinueWith(t => {
+ var message = t.Exception.InnerException is null ? t.Exception.Message : t.Exception.InnerException.Message;
+ if (message.StartsWith("#"))
+ {
+ message = _globalizer.GetResourceString(message.Substring(1)) ?? message.Substring(1);
+ }
+
+ MessageBox.Show(message, _globalizer.GetResourceString("DiscordBot_ErrorTitle"), MessageBoxButton.OK, MessageBoxImage.Error);
+
+ if (_tokenSourceDiscordBot != null)
+ {
+ // cleanup the token
+ _tokenSourceDiscordBot.Dispose();
+ _tokenSourceDiscordBot = null;
+ }
+ DiscordBotStarted = false;
+ }, TaskContinuationOptions.OnlyOnFaulted);
+ }
+
+ public void StopDiscordBot()
+ {
+ if (!(_tokenSourceDiscordBot is null))
+ {
+ _tokenSourceDiscordBot.Cancel();
+ }
+ }
}
}
diff --git a/src/ConanServerManager/ConanServerManager.csproj b/src/ConanServerManager/ConanServerManager.csproj
index f9e040b3..9bfc02b9 100644
--- a/src/ConanServerManager/ConanServerManager.csproj
+++ b/src/ConanServerManager/ConanServerManager.csproj
@@ -147,7 +147,6 @@
-
4.0
diff --git a/src/ConanServerManager/Config.Designer.cs b/src/ConanServerManager/Config.Designer.cs
index 994ba21a..b8f4d5e1 100644
--- a/src/ConanServerManager/Config.Designer.cs
+++ b/src/ConanServerManager/Config.Designer.cs
@@ -1980,7 +1980,7 @@ namespace ServerManagerTool {
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("csm")]
+ [global::System.Configuration.DefaultSettingValueAttribute("csm!")]
public string DiscordBotPrefix {
get {
return ((string)(this["DiscordBotPrefix"]));
@@ -2139,5 +2139,63 @@ namespace ServerManagerTool {
this["ServerMonitorWindow_Top"] = value;
}
}
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("\r\n ")]
+ public global::System.Collections.Specialized.StringCollection DiscordBotWhitelist {
+ get {
+ return ((global::System.Collections.Specialized.StringCollection)(this["DiscordBotWhitelist"]));
+ }
+ set {
+ this["DiscordBotWhitelist"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("False")]
+ public bool DiscordBotPrefixFixed {
+ get {
+ return ((bool)(this["DiscordBotPrefixFixed"]));
+ }
+ set {
+ this["DiscordBotPrefixFixed"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("Info")]
+ public global::ServerManagerTool.DiscordBot.Enums.LogLevel DiscordBotLogLevel {
+ get {
+ return ((global::ServerManagerTool.DiscordBot.Enums.LogLevel)(this["DiscordBotLogLevel"]));
+ }
+ set {
+ this["DiscordBotLogLevel"] = value;
+ }
+ }
+
+ [global::System.Configuration.ApplicationScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("10")]
+ public int DiscordBotStatusCheckTime {
+ get {
+ return ((int)(this["DiscordBotStatusCheckTime"]));
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("False")]
+ public bool DiscordBotAllowAllBots {
+ get {
+ return ((bool)(this["DiscordBotAllowAllBots"]));
+ }
+ set {
+ this["DiscordBotAllowAllBots"] = value;
+ }
+ }
}
}
diff --git a/src/ConanServerManager/Config.settings b/src/ConanServerManager/Config.settings
index 90cf58e4..a9c38c97 100644
--- a/src/ConanServerManager/Config.settings
+++ b/src/ConanServerManager/Config.settings
@@ -549,7 +549,7 @@
False
- csm
+ csm!
@@ -590,5 +590,21 @@
50
+
+ <?xml version="1.0" encoding="utf-16"?>
+<ArrayOfString xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
+
+
+ False
+
+
+ Info
+
+
+ 10
+
+
+ False
+
\ No newline at end of file
diff --git a/src/ConanServerManager/Enums/ServerProcessType.cs b/src/ConanServerManager/Enums/ServerProcessType.cs
index 7298dfd9..cced8642 100644
--- a/src/ConanServerManager/Enums/ServerProcessType.cs
+++ b/src/ConanServerManager/Enums/ServerProcessType.cs
@@ -8,8 +8,9 @@
AutoShutdown1,
AutoShutdown2,
Backup,
- Shutdown,
Restart,
+ Shutdown,
+ Stop,
Update,
}
}
diff --git a/src/ConanServerManager/Globalization/en-US/en-US.xaml b/src/ConanServerManager/Globalization/en-US/en-US.xaml
index 1a4dddf1..ddb3222f 100644
--- a/src/ConanServerManager/Globalization/en-US/en-US.xaml
+++ b/src/ConanServerManager/Globalization/en-US/en-US.xaml
@@ -57,12 +57,21 @@
All
-
+
Normal
Minimized
Maximized
+
+ Critical
+ Error
+ Warning
+ Info
+ Verbose
+ Debug
+
+
x
%
@@ -120,6 +129,7 @@
Server download complete
Complete
Cancelled
+ Failed
Cancel
@@ -605,12 +615,18 @@
Enable
Enable the auto-update scheduled task
Next Run Time:
+ Discord Bot:
+ Start
+ Start the discord bot
+ Stop
+ Stop the discord bot
Unknown
Disabled
Queued
Ready
Running
+ Stopped
Profile failed to load
The profile at {0} failed to load. The error was: {1}\r\n{2}
@@ -779,8 +795,17 @@
The id of the discord server the bot will listen to.
Prefix:
The prefix that must be used when sending a command via discord.
+ Log Level:
Get Token...
Help...
+ Allow All Bots
+ If enabled, the server manager bot will respond to all other bots, otherwise they will be ignored unless they are in the whitelist.
+ Bot Whitelist
+ Bot ID
+ The id of the bot to whitelist.
+ Add Whitelist
+ Clear Whitelists
+ Delete Whitelist
If enabled, the backup command can be sent from discord.
If enabled, the restart command can be sent from discord.
If enabled, the shutdown command can be sent from discord.
@@ -1147,6 +1172,8 @@
Discord Bot Details
Channel Id:
The id of the discord server channel this profile will listen to.
+ Alias:
+ A unique name to identify your server when using the discord commands, can be used instead of the profile id.
Allow Backup
If enabled, the profile will listen for backup commands from discord.
Allow Restart
@@ -1244,8 +1271,9 @@
Another command '{0}' is currently running against profile '{1}'.
Command '{0}' has been disabled for profile '{1}'.
- The '{0}' command requires a profile id.
+ The '{0}' command requires a profile id or alias.
Profile '{0}' was not found or is not associated with the channel.
+ Multiple profiles with '{0}' were found in the channel, command aborted.
Profile '{0}' is in a state '{1}' that cannot run this command.
Profile '{0}' is currently being updated.
diff --git a/src/ConanServerManager/Lib/ServerApp.cs b/src/ConanServerManager/Lib/ServerApp.cs
index 7b5be7cb..acfdd0e3 100644
--- a/src/ConanServerManager/Lib/ServerApp.cs
+++ b/src/ConanServerManager/Lib/ServerApp.cs
@@ -423,6 +423,16 @@ namespace ServerManagerTool.Lib
LogProfileMessage("Starting shutdown timer...");
var minutesLeft = ShutdownInterval;
+ if (ServerProcess == ServerProcessType.Stop)
+ {
+ LogProfileMessage($"Server shutdown type is {ServerProcess}, shutdown timer cancelled.");
+ minutesLeft = 0;
+ }
+ else if (!CheckForOnlinePlayers)
+ {
+ LogProfileMessage("CheckForOnlinePlayers disabled, shutdown timer will not perform online player check.");
+ }
+
while (minutesLeft > 0)
{
if (cancellationToken.IsCancellationRequested)
@@ -446,8 +456,8 @@ namespace ServerManagerTool.Lib
// BH - commented out until Funcom fix the Online player status column in the world save database
//var gameFile = GetServerWorldFile();
//var playerCount = DataContainer.GetOnlinePlayerCount(gameFile);
- var playerInfo = gameServer?.GetPlayers()?.Where(p => !string.IsNullOrWhiteSpace(p.Name?.Trim())).ToList();
- var playerCount = playerInfo?.Count ?? -1;
+ var playerInfo = gameServer?.GetPlayers()?.Where(p => !string.IsNullOrWhiteSpace(p.Name?.Trim()));
+ var playerCount = playerInfo?.Count() ?? -1;
// check if anyone is logged into the server
if (playerCount <= 0)
@@ -466,7 +476,6 @@ namespace ServerManagerTool.Lib
else
{
Debug.WriteLine($"CheckForOnlinePlayers disabled, shutdown timer cancelled.");
- break;
}
var message = string.Empty;
@@ -1781,7 +1790,7 @@ namespace ServerManagerTool.Lib
comment.AppendLine($"Profile Name: {_profile.ProfileName}");
comment.AppendLine($"Process: {ServerProcess}");
- ZipUtils.ZipFiles(backupFile, files.ToArray(), comment.ToString(), false);
+ ZipUtils.ZipFiles(backupFile, files, comment.ToString(), false);
LogProfileMessage($"Backup file created - {backupFile}");
}
@@ -1901,7 +1910,7 @@ namespace ServerManagerTool.Lib
ZipUtils.ZipAFile(backupFile, worldFileName, worldBackupFile, comment.ToString());
if (files.Count > 0)
- ZipUtils.UpdateFiles(backupFile, files.ToArray(), null, false, "");
+ ZipUtils.UpdateFiles(backupFile, files, null, false, "");
LogProfileMessage($"Backed up world files - {saveFolder}");
LogProfileMessage($"Backup file created - {backupFile}");
@@ -2842,7 +2851,7 @@ namespace ServerManagerTool.Lib
if (ExitCode == EXITCODE_NORMALEXIT)
{
// get the profile associated with the branch
- var profiles = _profiles.Keys.Where(p => p.EnableAutoUpdate && p.BranchName.Equals(branch.BranchName, StringComparison.OrdinalIgnoreCase)).ToArray();
+ var profiles = _profiles.Keys.Where(p => p.EnableAutoUpdate && p.BranchName.Equals(branch.BranchName, StringComparison.OrdinalIgnoreCase));
var profileExitCodes = new ConcurrentDictionary();
if (Config.Default.AutoUpdate_ParallelUpdate)
@@ -3093,7 +3102,7 @@ namespace ServerManagerTool.Lib
if (exitCode == EXITCODE_NORMALEXIT)
{
- var branches = _profiles.Keys.Where(p => p.EnableAutoUpdate).Select(p => BranchSnapshot.Create(p)).Distinct(new BranchSnapshotComparer()).ToArray();
+ var branches = _profiles.Keys.Where(p => p.EnableAutoUpdate).Select(p => BranchSnapshot.Create(p)).Distinct(new BranchSnapshotComparer());
var exitCodes = new ConcurrentDictionary();
// update the server cache for each branch
diff --git a/src/ConanServerManager/Lib/ServerPlayers.cs b/src/ConanServerManager/Lib/ServerPlayers.cs
index 8205979e..4ba60503 100644
--- a/src/ConanServerManager/Lib/ServerPlayers.cs
+++ b/src/ConanServerManager/Lib/ServerPlayers.cs
@@ -212,7 +212,7 @@ namespace ServerManagerTool.Lib
return;
// remove any players that do not have a player record.
- var droppedPlayers = this._players.Values.Where(p => dataContainer.Players.FirstOrDefault(pd => pd.PlayerId.Equals(p.PlayerId, StringComparison.OrdinalIgnoreCase)) == null).ToArray();
+ var droppedPlayers = this._players.Values.Where(p => dataContainer.Players.FirstOrDefault(pd => pd.PlayerId.Equals(p.PlayerId, StringComparison.OrdinalIgnoreCase)) == null);
foreach (var droppedPlayer in droppedPlayers)
{
_players.TryRemove(droppedPlayer.PlayerId, out PlayerInfo player);
diff --git a/src/ConanServerManager/Lib/ServerProfile.cs b/src/ConanServerManager/Lib/ServerProfile.cs
index 9e6531e3..cc62450c 100644
--- a/src/ConanServerManager/Lib/ServerProfile.cs
+++ b/src/ConanServerManager/Lib/ServerProfile.cs
@@ -576,6 +576,14 @@ namespace ServerManagerTool.Lib
set { SetValue(DiscordChannelIdProperty, value); }
}
+ public static readonly DependencyProperty DiscordAliasProperty = DependencyProperty.Register(nameof(DiscordAlias), typeof(string), typeof(ServerProfile), new PropertyMetadata(String.Empty));
+ [DataMember]
+ public string DiscordAlias
+ {
+ get { return (string)GetValue(DiscordAliasProperty); }
+ set { SetValue(DiscordAliasProperty, value); }
+ }
+
public static readonly DependencyProperty AllowDiscordBackupProperty = DependencyProperty.Register(nameof(AllowDiscordBackup), typeof(bool), typeof(ServerProfile), new PropertyMetadata(true));
[DataMember]
public bool AllowDiscordBackup
@@ -688,8 +696,7 @@ namespace ServerManagerTool.Lib
{
InstallDirectory = folder;
- LoadServerFileBlacklisted();
- LoadServerFileWhitelisted();
+ LoadServerFiles(true, true);
SetupServerFilesWatcher();
}
@@ -759,8 +766,7 @@ namespace ServerManagerTool.Lib
internal static ServerProfile FromDefaults()
{
var settings = new ServerProfile();
- settings.LoadServerFileBlacklisted();
- settings.LoadServerFileWhitelisted();
+ settings.LoadServerFiles(true, true);
settings.SetupServerFilesWatcher();
return settings;
}
@@ -794,11 +800,9 @@ namespace ServerManagerTool.Lib
}
}
- private static Enum[] GetExclusions()
+ private static IEnumerable GetExclusions()
{
- var exclusions = new List();
-
- return exclusions.ToArray();
+ return new List();
}
public string GetLauncherFile() => Path.Combine(GetProfileServerConfigDir(), Config.Default.LauncherFile);
@@ -887,7 +891,7 @@ namespace ServerManagerTool.Lib
return profile;
}
- public static ServerProfile LoadFromConfigFiles(string file, ServerProfile profile, Enum[] exclusions = null)
+ public static ServerProfile LoadFromConfigFiles(string file, ServerProfile profile, IEnumerable exclusions = null)
{
if (string.IsNullOrWhiteSpace(file) || !File.Exists(file))
return null;
@@ -949,8 +953,7 @@ namespace ServerManagerTool.Lib
profile = LoadFromConfigFiles(serverConfigFile, profile);
}
- profile.LoadServerFileBlacklisted();
- profile.LoadServerFileWhitelisted();
+ profile.LoadServerFiles(true, true);
profile.SetupServerFilesWatcher();
profile._lastSaveLocation = file;
@@ -1111,7 +1114,7 @@ namespace ServerManagerTool.Lib
SaveConfigFile(serverConfigDir);
}
- public void SaveConfigFile(string configDir, Enum[] exclusions = null)
+ public void SaveConfigFile(string configDir, IEnumerable exclusions = null)
{
if (exclusions == null)
exclusions = GetExclusions();
@@ -1536,14 +1539,19 @@ namespace ServerManagerTool.Lib
#region Server Files
private void ServerFilesWatcher_Changed(object sender, FileSystemEventArgs e)
{
+ var blacklistFile = false;
+ var whitelistFile = false;
+
if (e.Name.Equals(Config.Default.ServerBlacklistFile, StringComparison.OrdinalIgnoreCase))
{
- TaskUtils.RunOnUIThreadAsync(() => LoadServerFileBlacklisted()).DoNotWait();
+ blacklistFile = true;
}
if (e.Name.Equals(Config.Default.ServerWhitelistFile, StringComparison.OrdinalIgnoreCase))
{
- TaskUtils.RunOnUIThreadAsync(() => LoadServerFileWhitelisted()).DoNotWait();
+ whitelistFile = true;
}
+
+ TaskUtils.RunOnUIThreadAsync(() => LoadServerFiles(blacklistFile, whitelistFile)).DoNotWait();
}
private void ServerFilesWatcher_Error(object sender, ErrorEventArgs e)
@@ -1589,58 +1597,58 @@ namespace ServerManagerTool.Lib
_serverFilesWatcher.EnableRaisingEvents = true;
}
- public void LoadServerFileBlacklisted()
+ public void LoadServerFiles(bool blacklistFile, bool whitelistFile)
{
try
{
- var list = this.ServerFilesBlacklisted ?? new PlayerUserList();
+ var list1 = this.ServerFilesBlacklisted ?? new PlayerUserList();
+ var list2 = this.ServerFilesWhitelisted ?? new PlayerUserList();
- var file = Path.Combine(InstallDirectory, Config.Default.SavedFilesRelativePath, Config.Default.ServerBlacklistFile);
- if (File.Exists(file))
+ var allSteamIds = new List();
+ string[] blacklistSteamIds = null;
+ string[] whitelistSteamIds = null;
+
+ if (blacklistFile)
{
- var steamIds = File.ReadAllLines(file);
- var steamUsers = SteamUtils.GetSteamUserDetails(steamIds.ToList());
-
- list = PlayerUserList.GetList(steamUsers, steamIds);
+ var file = Path.Combine(InstallDirectory, Config.Default.ServerBinaryRelativePath, Config.Default.ServerBlacklistFile);
+ if (File.Exists(file))
+ {
+ blacklistSteamIds = File.ReadAllLines(file);
+ allSteamIds.AddRange(blacklistSteamIds);
+ }
}
- this.ServerFilesBlacklisted = list;
- }
- catch (IOException)
- {
- // do nothing
+ if (whitelistFile)
+ {
+ var file = Path.Combine(InstallDirectory, Config.Default.ServerBinaryRelativePath, Config.Default.ServerWhitelistFile);
+ if (File.Exists(file))
+ {
+ whitelistSteamIds = File.ReadAllLines(file);
+ allSteamIds.AddRange(whitelistSteamIds);
+ }
+ }
+
+ // remove all duplicates
+ allSteamIds = allSteamIds.Distinct().ToList();
+
+ // fetch the details of all steam users in the list
+ var steamUsers = SteamUtils.GetSteamUserDetails(allSteamIds);
+
+ if (blacklistFile && blacklistSteamIds != null)
+ {
+ list1 = PlayerUserList.GetList(steamUsers, blacklistSteamIds);
+ }
+
+ if (whitelistFile && whitelistSteamIds != null)
+ {
+ list2 = PlayerUserList.GetList(steamUsers, whitelistSteamIds);
+ }
+
+ this.ServerFilesBlacklisted = list1;
+ this.ServerFilesWhitelisted = list2;
}
catch (Exception ex)
{
- this.ServerFilesBlacklisted = new PlayerUserList();
- MessageBox.Show(ex.Message, _globalizer.GetResourceString("ServerSettings_ServerFilesLoadErrorTitle"), MessageBoxButton.OK, MessageBoxImage.Error);
- }
- }
-
- public void LoadServerFileWhitelisted()
- {
- try
- {
- var list = this.ServerFilesWhitelisted ?? new PlayerUserList();
-
- var file = Path.Combine(InstallDirectory, Config.Default.SavedFilesRelativePath, Config.Default.ServerWhitelistFile);
- if (File.Exists(file))
- {
- var steamIds = File.ReadAllLines(file);
- var steamUsers = SteamUtils.GetSteamUserDetails(steamIds.ToList());
-
- list = PlayerUserList.GetList(steamUsers, steamIds);
- }
-
- this.ServerFilesWhitelisted = list;
- }
- catch (IOException)
- {
- // do nothing
- }
- catch (Exception ex)
- {
- this.ServerFilesWhitelisted = new PlayerUserList();
MessageBox.Show(ex.Message, _globalizer.GetResourceString("ServerSettings_ServerFilesLoadErrorTitle"), MessageBoxButton.OK, MessageBoxImage.Error);
}
}
@@ -1654,7 +1662,7 @@ namespace ServerManagerTool.Lib
Directory.CreateDirectory(folder);
var file = Path.Combine(folder, Config.Default.ServerBlacklistFile);
- File.WriteAllLines(file, this.ServerFilesBlacklisted.ToArray());
+ File.WriteAllLines(file, this.ServerFilesBlacklisted.ToEnumerable());
}
catch (Exception ex)
{
@@ -1671,7 +1679,7 @@ namespace ServerManagerTool.Lib
Directory.CreateDirectory(folder);
var file = Path.Combine(folder, Config.Default.ServerWhitelistFile);
- File.WriteAllLines(file, this.ServerFilesWhitelisted.ToArray());
+ File.WriteAllLines(file, this.ServerFilesWhitelisted.ToEnumerable());
}
catch (Exception ex)
{
diff --git a/src/ConanServerManager/Lib/ServerRcon.cs b/src/ConanServerManager/Lib/ServerRcon.cs
index a7ceba57..979fe124 100644
--- a/src/ConanServerManager/Lib/ServerRcon.cs
+++ b/src/ConanServerManager/Lib/ServerRcon.cs
@@ -450,7 +450,7 @@ namespace ServerManagerTool.Lib
return new List();
// remove any players that do not have a player record.
- var droppedPlayers = this._players.Values.Where(p => dataContainer.Players.FirstOrDefault(pd => pd.PlayerId.Equals(p.PlayerId, StringComparison.OrdinalIgnoreCase)) == null).ToArray();
+ var droppedPlayers = this._players.Values.Where(p => dataContainer.Players.FirstOrDefault(pd => pd.PlayerId.Equals(p.PlayerId, StringComparison.OrdinalIgnoreCase)) == null);
foreach (var droppedPlayer in droppedPlayers)
{
_players.TryRemove(droppedPlayer.PlayerId, out PlayerInfo player);
diff --git a/src/ConanServerManager/UserControls/GlobalSettingsControl.xaml b/src/ConanServerManager/UserControls/GlobalSettingsControl.xaml
index 1a6f3909..430ccbd6 100644
--- a/src/ConanServerManager/UserControls/GlobalSettingsControl.xaml
+++ b/src/ConanServerManager/UserControls/GlobalSettingsControl.xaml
@@ -534,11 +534,14 @@
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -565,6 +568,8 @@
+
+
@@ -573,6 +578,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/ConanServerManager/UserControls/GlobalSettingsControl.xaml.cs b/src/ConanServerManager/UserControls/GlobalSettingsControl.xaml.cs
index dd9587f4..a89cbfb1 100644
--- a/src/ConanServerManager/UserControls/GlobalSettingsControl.xaml.cs
+++ b/src/ConanServerManager/UserControls/GlobalSettingsControl.xaml.cs
@@ -5,13 +5,16 @@ using ServerManagerTool.Common.Lib;
using ServerManagerTool.Common.Model;
using ServerManagerTool.Common.Utils;
using System;
+using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
+using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
+using System.Windows.Data;
using System.Windows.Input;
using System.Xml;
using WPFSharp.Globalizer;
@@ -24,11 +27,13 @@ namespace ServerManagerTool
public partial class GlobalSettingsControl : UserControl
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
- private GlobalizedApplication _globalizer = GlobalizedApplication.Instance;
+ private readonly GlobalizedApplication _globalizer = GlobalizedApplication.Instance;
public static readonly DependencyProperty AppInstanceProperty = DependencyProperty.Register(nameof(AppInstance), typeof(App), typeof(GlobalSettingsControl), new PropertyMetadata(null));
public static readonly DependencyProperty IsAdministratorProperty = DependencyProperty.Register(nameof(IsAdministrator), typeof(bool), typeof(GlobalSettingsControl), new PropertyMetadata(false));
public static readonly DependencyProperty WindowStatesProperty = DependencyProperty.Register(nameof(WindowStates), typeof(ComboBoxItemList), typeof(GlobalSettingsControl), new PropertyMetadata(null));
+ public static readonly DependencyProperty DiscordBotLogLevelsProperty = DependencyProperty.Register(nameof(DiscordBotLogLevels), typeof(ComboBoxItemList), typeof(GlobalSettingsControl), new PropertyMetadata(null));
+ public static readonly DependencyProperty DiscordBotWhitelistProperty = DependencyProperty.Register(nameof(DiscordBotWhitelist), typeof(List), typeof(GlobalSettingsControl), new PropertyMetadata(null));
public GlobalSettingsControl()
{
@@ -38,11 +43,21 @@ namespace ServerManagerTool
this.IsAdministrator = SecurityUtils.IsAdministrator();
this.Version = GetDeployedVersion();
- PopulateWindowsStatesComboBox();
-
InitializeComponent();
WindowUtils.RemoveDefaultResourceDictionary(this, Config.Default.DefaultGlobalizationFile);
+ PopulateWindowsStatesComboBox();
+ PopulateDiscordBotLogLevelsComboBox();
+
+ DiscordBotWhitelist = new List();
+ if (Config.DiscordBotWhitelist != null)
+ {
+ foreach (var item in Config.DiscordBotWhitelist)
+ {
+ DiscordBotWhitelist.Add(new DiscordBotWhitelist() { BotId = item });
+ }
+ }
+
this.DataContext = this;
}
@@ -82,6 +97,27 @@ namespace ServerManagerTool
set;
}
+ public ComboBoxItemList DiscordBotLogLevels
+ {
+ get { return (ComboBoxItemList)GetValue(DiscordBotLogLevelsProperty); }
+ set { SetValue(DiscordBotLogLevelsProperty, value); }
+ }
+
+ public List DiscordBotWhitelist
+ {
+ get { return (List)GetValue(DiscordBotWhitelistProperty); }
+ set { SetValue(DiscordBotWhitelistProperty, value); }
+ }
+
+ public void ApplyChangesToConfig()
+ {
+ if (Config.DiscordBotWhitelist is null)
+ Config.DiscordBotWhitelist = new System.Collections.Specialized.StringCollection();
+
+ Config.DiscordBotWhitelist.Clear();
+ Config.DiscordBotWhitelist.AddRange(DiscordBotWhitelist.Select(i => i.BotId).ToArray());
+ }
+
private string GetDeployedVersion()
{
XmlDocument xmlDoc = new XmlDocument();
@@ -158,14 +194,24 @@ namespace ServerManagerTool
if (result == CommonFileDialogResult.Ok)
{
- if (!String.Equals(dialog.FileName, Config.Default.DataPath))
+ if (!string.Equals(dialog.FileName, Config.Default.DataPath))
{
try
{
+ var newDataDirectory = dialog.FileName;
+ if (!string.IsNullOrWhiteSpace(newDataDirectory))
+ {
+ var root = Path.GetPathRoot(newDataDirectory);
+ if (!root.EndsWith("\\"))
+ {
+ newDataDirectory = newDataDirectory.Replace(root, root + "\\");
+ }
+ }
+
// Set up the destination directories
- string newConfigDirectory = Path.Combine(dialog.FileName, Config.Default.ProfilesRelativePath);
+ string newConfigDirectory = Path.Combine(newDataDirectory, Config.Default.ProfilesRelativePath);
string oldSteamDirectory = Path.Combine(Config.Default.DataPath, CommonConfig.Default.SteamCmdRelativePath);
- string newSteamDirectory = Path.Combine(dialog.FileName, CommonConfig.Default.SteamCmdRelativePath);
+ string newSteamDirectory = Path.Combine(newDataDirectory, CommonConfig.Default.SteamCmdRelativePath);
Directory.CreateDirectory(newConfigDirectory);
Directory.CreateDirectory(newSteamDirectory);
@@ -199,7 +245,7 @@ namespace ServerManagerTool
Directory.Delete(oldSteamDirectory, true);
// Update the config
- Config.Default.DataPath = dialog.FileName;
+ Config.Default.DataPath = newDataDirectory;
Config.Default.ConfigPath = newConfigDirectory;
App.ReconfigureLogging();
}
@@ -238,9 +284,18 @@ namespace ServerManagerTool
if (result == CommonFileDialogResult.Ok)
{
- if (!String.Equals(dialog.FileName, Config.Default.BackupPath))
+ if (!string.Equals(dialog.FileName, Config.Default.BackupPath))
{
Config.Default.BackupPath = dialog.FileName;
+
+ if (!string.IsNullOrWhiteSpace(Config.Default.BackupPath))
+ {
+ var root = Path.GetPathRoot(Config.Default.BackupPath);
+ if (!root.EndsWith("\\"))
+ {
+ Config.Default.BackupPath = Config.Default.BackupPath.Replace(root, root + "\\");
+ }
+ }
}
}
}
@@ -260,9 +315,18 @@ namespace ServerManagerTool
if (result == CommonFileDialogResult.Ok)
{
- if (!String.Equals(dialog.FileName, Config.Default.AutoUpdate_CacheDir))
+ if (!string.Equals(dialog.FileName, Config.Default.AutoUpdate_CacheDir))
{
Config.Default.AutoUpdate_CacheDir = dialog.FileName;
+
+ if (!string.IsNullOrWhiteSpace(Config.Default.AutoUpdate_CacheDir))
+ {
+ var root = Path.GetPathRoot(Config.Default.AutoUpdate_CacheDir);
+ if (!root.EndsWith("\\"))
+ {
+ Config.Default.AutoUpdate_CacheDir = Config.Default.AutoUpdate_CacheDir.Replace(root, root + "\\");
+ }
+ }
}
}
}
@@ -443,5 +507,53 @@ namespace ServerManagerTool
this.WindowStateComboBox.SelectedValue = selectedValue;
}
}
+
+ private void PopulateDiscordBotLogLevelsComboBox()
+ {
+ var selectedValue = this.DiscordBotLogLevelComboBox?.SelectedValue ?? Config.DiscordBotLogLevel;
+ var comboBoxList = new ComboBoxItemList();
+
+ foreach (DiscordBot.Enums.LogLevel logLevel in Enum.GetValues(typeof(DiscordBot.Enums.LogLevel)))
+ {
+ var displayMember = _globalizer.GetResourceString($"DiscordBotLogLevel_{logLevel}") ?? logLevel.ToString();
+ comboBoxList.Add(new Common.Model.ComboBoxItem(logLevel.ToString(), displayMember));
+ }
+
+ this.DiscordBotLogLevels = comboBoxList;
+ if (this.DiscordBotLogLevelComboBox != null)
+ {
+ this.DiscordBotLogLevelComboBox.SelectedValue = selectedValue;
+ }
+ }
+
+ #region Discord Bot Whitelist
+ private void AddDiscordBotWhitelist_Click(object sender, RoutedEventArgs e)
+ {
+ DiscordBotWhitelist.Add(new DiscordBotWhitelist());
+
+ CollectionViewSource.GetDefaultView(DiscordBotWhitelistGrid.ItemsSource).Refresh();
+ }
+
+ private void ClearDiscordBotWhitelists_Click(object sender, RoutedEventArgs e)
+ {
+ if (MessageBox.Show(_globalizer.GetResourceString("ServerSettings_ClearLabel"), _globalizer.GetResourceString("ServerSettings_ClearTitle"), MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes)
+ return;
+
+ DiscordBotWhitelist.Clear();
+
+ CollectionViewSource.GetDefaultView(DiscordBotWhitelistGrid.ItemsSource).Refresh();
+ }
+
+ private void RemoveDiscordBotWhitelist_Click(object sender, RoutedEventArgs e)
+ {
+ if (MessageBox.Show(_globalizer.GetResourceString("ServerSettings_DeleteLabel"), _globalizer.GetResourceString("ServerSettings_DeleteTitle"), MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes)
+ return;
+
+ var item = ((DiscordBotWhitelist)((Button)e.Source).DataContext);
+ DiscordBotWhitelist.Remove(item);
+
+ CollectionViewSource.GetDefaultView(DiscordBotWhitelistGrid.ItemsSource).Refresh();
+ }
+ #endregion
}
}
diff --git a/src/ConanServerManager/UserControls/ServerSettingsControl.xaml b/src/ConanServerManager/UserControls/ServerSettingsControl.xaml
index bfa7cb8f..1538ee97 100644
--- a/src/ConanServerManager/UserControls/ServerSettingsControl.xaml
+++ b/src/ConanServerManager/UserControls/ServerSettingsControl.xaml
@@ -1093,6 +1093,9 @@
+
+
+
diff --git a/src/ConanServerManager/UserControls/ServerSettingsControl.xaml.cs b/src/ConanServerManager/UserControls/ServerSettingsControl.xaml.cs
index 0ca8ddce..60e21a10 100644
--- a/src/ConanServerManager/UserControls/ServerSettingsControl.xaml.cs
+++ b/src/ConanServerManager/UserControls/ServerSettingsControl.xaml.cs
@@ -696,7 +696,7 @@ namespace ServerManagerTool
comment.AppendLine($"ServerUpdate_OnServerStart: {Config.Default.ServerUpdate_OnServerStart}");
comment.AppendLine($"DiscordBotEnabled: {Config.Default.DiscordBotEnabled}");
- comment.AppendLine($"HasDiscordBotToken: {string.IsNullOrWhiteSpace(Config.Default.DiscordBotToken)}");
+ comment.AppendLine($"HasDiscordBotToken: {!string.IsNullOrWhiteSpace(Config.Default.DiscordBotToken)}");
comment.AppendLine($"DiscordBotServerId: {Config.Default.DiscordBotServerId}");
comment.AppendLine($"DiscordBotPrefix: {Config.Default.DiscordBotPrefix}");
comment.AppendLine($"AllowDiscordBackup: {Config.Default.AllowDiscordBackup}");
@@ -720,7 +720,7 @@ namespace ServerManagerTool
var zipFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), this.Settings.ProfileID + ".zip");
if (File.Exists(zipFile)) File.Delete(zipFile);
- ZipUtils.ZipFiles(zipFile, files.ToArray(), comment.ToString());
+ ZipUtils.ZipFiles(zipFile, files, comment.ToString());
foreach (var kvp in obfuscateFiles)
{
ZipUtils.ZipAFile(zipFile, kvp.Key, kvp.Value);
@@ -1130,7 +1130,7 @@ namespace ServerManagerTool
Application.Current.Dispatcher.Invoke(() => this.Cursor = Cursors.Wait);
await Task.Delay(500);
- Settings.LoadServerFileBlacklisted();
+ Settings.LoadServerFiles(true, false);
}
catch (Exception ex)
{
@@ -1151,7 +1151,7 @@ namespace ServerManagerTool
Application.Current.Dispatcher.Invoke(() => this.Cursor = Cursors.Wait);
await Task.Delay(500);
- Settings.LoadServerFileWhitelisted();
+ Settings.LoadServerFiles(false, true);
}
catch (Exception ex)
{
diff --git a/src/ConanServerManager/Utils/DiscordBotHelper.cs b/src/ConanServerManager/Utils/DiscordBotHelper.cs
index 727ac5f0..44abc15e 100644
--- a/src/ConanServerManager/Utils/DiscordBotHelper.cs
+++ b/src/ConanServerManager/Utils/DiscordBotHelper.cs
@@ -1,11 +1,11 @@
using QueryMaster;
+using ServerManagerTool.Common.Extensions;
using ServerManagerTool.Common.Utils;
using ServerManagerTool.DiscordBot.Enums;
using ServerManagerTool.Enums;
using ServerManagerTool.Lib;
using System;
using System.Collections.Generic;
-using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Threading;
@@ -23,7 +23,7 @@ namespace ServerManagerTool.Utils
public static bool HasRunningCommands => _currentProfileCommands.Count > 0;
- public static IList HandleDiscordCommand(CommandType commandType, string serverId, string channelId, string profileId, CancellationToken token)
+ public static IList HandleDiscordCommand(CommandType commandType, string serverId, string channelId, string profileIdOrAlias, CancellationToken token)
{
// check if incoming values are valid
if (string.IsNullOrWhiteSpace(serverId) || string.IsNullOrWhiteSpace(channelId))
@@ -42,35 +42,35 @@ namespace ServerManagerTool.Utils
switch (commandType)
{
case CommandType.Info:
- return GetServerInfo(channelId, profileId);
+ return GetServerInfo(channelId, profileIdOrAlias);
case CommandType.List:
return GetServerList(channelId);
case CommandType.Status:
- return GetServerStatus(channelId, profileId);
+ return GetServerStatus(channelId, profileIdOrAlias);
case CommandType.Backup:
if (Config.Default.AllowDiscordBackup)
- return BackupServer(channelId, profileId, token);
+ return BackupServer(channelId, profileIdOrAlias, token);
return new List { string.Format(_globalizer.GetResourceString("DiscordBot_CommandNotEnabled"), commandType) };
case CommandType.Restart:
if (Config.Default.AllowDiscordRestart)
- return RestartServer(channelId, profileId, token);
+ return RestartServer(channelId, profileIdOrAlias, token);
return new List { string.Format(_globalizer.GetResourceString("DiscordBot_CommandNotEnabled"), commandType) };
case CommandType.Shutdown:
if (Config.Default.AllowDiscordShutdown)
- return ShutdownServer(channelId, profileId, token);
+ return ShutdownServer(channelId, profileIdOrAlias, token);
return new List { string.Format(_globalizer.GetResourceString("DiscordBot_CommandNotEnabled"), commandType) };
case CommandType.Stop:
if (Config.Default.AllowDiscordStop)
- return StopServer(channelId, profileId, token);
+ return StopServer(channelId, profileIdOrAlias, token);
return new List { string.Format(_globalizer.GetResourceString("DiscordBot_CommandNotEnabled"), commandType) };
case CommandType.Start:
if (Config.Default.AllowDiscordStart)
- return StartServer(channelId, profileId, token);
+ return StartServer(channelId, profileIdOrAlias, token);
return new List { string.Format(_globalizer.GetResourceString("DiscordBot_CommandNotEnabled"), commandType) };
case CommandType.Update:
if (Config.Default.AllowDiscordUpdate)
- return UpdateServer(channelId, profileId, token);
+ return UpdateServer(channelId, profileIdOrAlias, token);
return new List { string.Format(_globalizer.GetResourceString("DiscordBot_CommandNotEnabled"), commandType) };
default:
@@ -93,19 +93,14 @@ namespace ServerManagerTool.Utils
return string.IsNullOrWhiteSpace(translationKey) ? string.Empty : _globalizer.GetResourceString(translationKey) ?? translationKey;
}
- private static IList GetServerInfo(string channelId, string profileId)
+ private static IList GetServerInfo(string channelId, string profileIdOrAlias)
{
- if (string.IsNullOrWhiteSpace(profileId))
+ if (string.IsNullOrWhiteSpace(profileIdOrAlias))
{
return new List { string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMissing"), CommandType.Info) };
}
- // check if another command is being run against the profile
- if (_currentProfileCommands.ContainsKey(profileId))
- {
- return new List { string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[profileId], profileId) };
- }
- _currentProfileCommands.Add(profileId, CommandType.Info);
+ var key = string.Empty;
try
{
@@ -115,12 +110,29 @@ namespace ServerManagerTool.Utils
TaskUtils.RunOnUIThreadAsync(() =>
{
- var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
+ var serverList = ServerManager.Instance.Servers.Where(s => string.Equals(channelId, s.Profile.DiscordChannelId, StringComparison.OrdinalIgnoreCase)
+ && (string.Equals(profileIdOrAlias, s.Profile.ProfileID, StringComparison.OrdinalIgnoreCase)
+ || !string.IsNullOrWhiteSpace(s.Profile.DiscordAlias) && string.Equals(profileIdOrAlias, s.Profile.DiscordAlias, StringComparison.OrdinalIgnoreCase)));
- if (server is null)
+ if (serverList.IsEmpty())
{
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileIdOrAlias));
}
+ if (!serverList.HasOne())
+ {
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMultiples"), profileIdOrAlias));
+ }
+
+ var server = serverList.First();
+
+ // check if another command is being run against the profile
+ if (_currentProfileCommands.ContainsKey(server.Profile.ProfileID))
+ {
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[server.Profile.ProfileID], server.Profile.ProfileName));
+ }
+
+ key = server.Profile.ProfileID;
+ _currentProfileCommands.Add(key, CommandType.Info);
switch (server.Runtime.Status)
{
@@ -130,7 +142,7 @@ namespace ServerManagerTool.Utils
case ServerStatus.Uninstalled:
case ServerStatus.Unknown:
case ServerStatus.Updating:
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileBadStatus"), profileId, server.Runtime.StatusString));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileBadStatus"), server.Profile.ProfileName, server.Runtime.StatusString));
}
serverName = server.Profile.ServerName;
@@ -155,7 +167,9 @@ namespace ServerManagerTool.Utils
else
{
var mapName = _globalizer.GetResourceString($"Map_{info.Map}") ?? info.Map;
- response.Add($"```{info.Name}\n{_globalizer.GetResourceString("DiscordBot_MapLabel")} {mapName}\n{_globalizer.GetResourceString("ServerSettings_PlayersLabel")} {info.Players} / {info.MaxPlayers}```");
+ response.Add($"```{info.Name}\n" +
+ $"{_globalizer.GetResourceString("DiscordBot_MapLabel")} {mapName}\n" +
+ $"{_globalizer.GetResourceString("ServerSettings_PlayersLabel")} {info.Players} / {info.MaxPlayers}```");
}
}
}
@@ -168,7 +182,7 @@ namespace ServerManagerTool.Utils
}
finally
{
- _currentProfileCommands.Remove(profileId);
+ _currentProfileCommands.Remove(key);
}
}
@@ -178,49 +192,55 @@ namespace ServerManagerTool.Utils
TaskUtils.RunOnUIThreadAsync(() =>
{
- var serverList = ServerManager.Instance.Servers.Where(s => Equals(channelId, s.Profile.DiscordChannelId));
+ var serverList = ServerManager.Instance.Servers.Where(s => string.Equals(channelId, s.Profile.DiscordChannelId, StringComparison.OrdinalIgnoreCase));
response.Add($"**{_globalizer.GetResourceString("DiscordBot_CountLabel")}** {serverList.Count()}");
foreach (var server in serverList)
{
- response.Add($"```{_globalizer.GetResourceString("ServerSettings_ProfileIdLabel")} {server.Profile.ProfileID}\n{_globalizer.GetResourceString("ServerSettings_ProfileLabel")} {server.Profile.ProfileName}\n{_globalizer.GetResourceString("ServerSettings_ServerNameLabel")} {server.Profile.ServerName}```");
+ response.Add($"```{_globalizer.GetResourceString("ServerSettings_ProfileLabel")} {server.Profile.ProfileName}\n" +
+ $"{_globalizer.GetResourceString("ServerSettings_ProfileIdLabel")} {server.Profile.ProfileID}\n" +
+ (string.IsNullOrWhiteSpace(server.Profile.DiscordAlias) ? "" : $"{_globalizer.GetResourceString("ServerSettings_DiscordAliasLabel")} {server.Profile.DiscordAlias}\n") +
+ $"{_globalizer.GetResourceString("ServerSettings_ServerNameLabel")} {server.Profile.ServerName}```");
}
}).Wait();
return response;
}
- private static IList GetServerStatus(string channelId, string profileId)
+ private static IList GetServerStatus(string channelId, string profileIdOrAlias)
{
List response = new List();
TaskUtils.RunOnUIThreadAsync(() =>
{
- var serverList = ServerManager.Instance.Servers.Where(s => Equals(channelId, s.Profile.DiscordChannelId) && (string.IsNullOrWhiteSpace(profileId) || Equals(profileId, s.Profile.ProfileID)));
+ var serverList = ServerManager.Instance.Servers.Where(s => string.Equals(channelId, s.Profile.DiscordChannelId, StringComparison.OrdinalIgnoreCase)
+ && (string.IsNullOrWhiteSpace(profileIdOrAlias)
+ || string.Equals(profileIdOrAlias, s.Profile.ProfileID, StringComparison.OrdinalIgnoreCase)
+ || !string.IsNullOrWhiteSpace(s.Profile.DiscordAlias) && string.Equals(profileIdOrAlias, s.Profile.DiscordAlias, StringComparison.OrdinalIgnoreCase)));
response.Add($"**{_globalizer.GetResourceString("DiscordBot_CountLabel")}** {serverList.Count()}");
foreach (var server in serverList)
{
- response.Add($"```{_globalizer.GetResourceString("ServerSettings_ProfileLabel")} {server.Profile.ProfileName}\n{_globalizer.GetResourceString("ServerSettings_ServerNameLabel")} {server.Profile.ServerName}\n{_globalizer.GetResourceString("ServerSettings_StatusLabel")} {server.Runtime.StatusString}\n{_globalizer.GetResourceString("ServerSettings_AvailabilityLabel")} {_globalizer.GetResourceString($"ServerSettings_Availability_{server.Runtime.Availability}")}```");
+ response.Add($"```{_globalizer.GetResourceString("ServerSettings_ProfileLabel")} {server.Profile.ProfileName}\n" +
+ $"{_globalizer.GetResourceString("ServerSettings_ProfileIdLabel")} {server.Profile.ProfileID}\n" +
+ (string.IsNullOrWhiteSpace(server.Profile.DiscordAlias) ? "" : $"{_globalizer.GetResourceString("ServerSettings_DiscordAliasLabel")} {server.Profile.DiscordAlias}\n") +
+ $"{_globalizer.GetResourceString("ServerSettings_ServerNameLabel")} {server.Profile.ServerName}\n" +
+ $"{_globalizer.GetResourceString("ServerSettings_StatusLabel")} {server.Runtime.StatusString}\n" +
+ $"{_globalizer.GetResourceString("ServerSettings_AvailabilityLabel")} {_globalizer.GetResourceString($"ServerSettings_Availability_{server.Runtime.Availability}")}```");
}
}).Wait();
return response;
}
- private static IList BackupServer(string channelId, string profileId, CancellationToken token)
+ private static IList BackupServer(string channelId, string profileIdOrAlias, CancellationToken token)
{
- if (string.IsNullOrWhiteSpace(profileId))
+ if (string.IsNullOrWhiteSpace(profileIdOrAlias))
{
return new List { string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMissing"), CommandType.Backup) };
}
- // check if another command is being run against the profile
- if (_currentProfileCommands.ContainsKey(profileId))
- {
- return new List { string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[profileId], profileId) };
- }
- _currentProfileCommands.Add(profileId, CommandType.Backup);
+ var key = string.Empty;
ServerProfileSnapshot profile = null;
Task task = null;
@@ -229,18 +249,35 @@ namespace ServerManagerTool.Utils
{
TaskUtils.RunOnUIThreadAsync(() =>
{
- var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
+ var serverList = ServerManager.Instance.Servers.Where(s => string.Equals(channelId, s.Profile.DiscordChannelId, StringComparison.OrdinalIgnoreCase)
+ && (string.Equals(profileIdOrAlias, s.Profile.ProfileID, StringComparison.OrdinalIgnoreCase)
+ || !string.IsNullOrWhiteSpace(s.Profile.DiscordAlias) && string.Equals(profileIdOrAlias, s.Profile.DiscordAlias, StringComparison.OrdinalIgnoreCase)));
- if (server is null)
+ if (serverList.IsEmpty())
{
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileIdOrAlias));
}
+ if (!serverList.HasOne())
+ {
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMultiples"), profileIdOrAlias));
+ }
+
+ var server = serverList.First();
if (!server.Profile.AllowDiscordBackup)
{
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandDisabledProfile"), CommandType.Backup, profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandDisabledProfile"), CommandType.Backup, server.Profile.ProfileName));
}
+ // check if another command is being run against the profile
+ if (_currentProfileCommands.ContainsKey(server.Profile.ProfileID))
+ {
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[server.Profile.ProfileID], server.Profile.ProfileName));
+ }
+
+ key = server.Profile.ProfileID;
+ _currentProfileCommands.Add(key, CommandType.Backup);
+
switch (server.Runtime.Status)
{
case ServerStatus.Initializing:
@@ -248,7 +285,7 @@ namespace ServerManagerTool.Utils
case ServerStatus.Uninstalled:
case ServerStatus.Unknown:
case ServerStatus.Updating:
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileBadStatus"), profileId, server.Runtime.StatusString));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileBadStatus"), server.Profile.ProfileName, server.Runtime.StatusString));
}
profile = ServerProfileSnapshot.Create(server.Profile);
@@ -267,7 +304,9 @@ namespace ServerManagerTool.Utils
{
TaskUtils.RunOnUIThreadAsync(() =>
{
- var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
+ var server = ServerManager.Instance.Servers.First(s => string.Equals(channelId, s.Profile.DiscordChannelId, StringComparison.OrdinalIgnoreCase)
+ && (string.Equals(profileIdOrAlias, s.Profile.ProfileID, StringComparison.OrdinalIgnoreCase)
+ || !string.IsNullOrWhiteSpace(s.Profile.DiscordAlias) && string.Equals(profileIdOrAlias, s.Profile.DiscordAlias, StringComparison.OrdinalIgnoreCase)));
server.Runtime.UpdateServerStatus(serverStatus, true);
}).Wait();
}
@@ -276,7 +315,7 @@ namespace ServerManagerTool.Utils
task = Task.Run(() =>
{
app.PerformProfileBackup(profile, token);
- _currentProfileCommands.Remove(profileId);
+ _currentProfileCommands.Remove(key);
});
response.Add(string.Format(_globalizer.GetResourceString("DiscordBot_BackupRequested"), profile.ServerName));
@@ -287,24 +326,19 @@ namespace ServerManagerTool.Utils
{
if (task is null)
{
- _currentProfileCommands.Remove(profileId);
+ _currentProfileCommands.Remove(key);
}
}
}
- private static IList RestartServer(string channelId, string profileId, CancellationToken token)
+ private static IList RestartServer(string channelId, string profileIdOrAlias, CancellationToken token)
{
- if (string.IsNullOrWhiteSpace(profileId))
+ if (string.IsNullOrWhiteSpace(profileIdOrAlias))
{
return new List { string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMissing"), CommandType.Restart) };
}
- // check if another command is being run against the profile
- if (_currentProfileCommands.ContainsKey(profileId))
- {
- return new List { string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[profileId], profileId) };
- }
- _currentProfileCommands.Add(profileId, CommandType.Restart);
+ var key = string.Empty;
ServerProfileSnapshot profile = null;
Task task = null;
@@ -313,28 +347,45 @@ namespace ServerManagerTool.Utils
{
TaskUtils.RunOnUIThreadAsync(() =>
{
- var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
+ var serverList = ServerManager.Instance.Servers.Where(s => string.Equals(channelId, s.Profile.DiscordChannelId, StringComparison.OrdinalIgnoreCase)
+ && (string.Equals(profileIdOrAlias, s.Profile.ProfileID, StringComparison.OrdinalIgnoreCase)
+ || !string.IsNullOrWhiteSpace(s.Profile.DiscordAlias) && string.Equals(profileIdOrAlias, s.Profile.DiscordAlias, StringComparison.OrdinalIgnoreCase)));
- if (server is null)
+ if (serverList.IsEmpty())
{
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileIdOrAlias));
}
+ if (!serverList.HasOne())
+ {
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMultiples"), profileIdOrAlias));
+ }
+
+ var server = serverList.First();
if (!server.Profile.AllowDiscordRestart)
{
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandDisabledProfile"), CommandType.Restart, profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandDisabledProfile"), CommandType.Restart, server.Profile.ProfileName));
}
+ // check if another command is being run against the profile
+ if (_currentProfileCommands.ContainsKey(server.Profile.ProfileID))
+ {
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[server.Profile.ProfileID], server.Profile.ProfileName));
+ }
+
+ key = server.Profile.ProfileID;
+ _currentProfileCommands.Add(key, CommandType.Restart);
+
switch (server.Runtime.Status)
{
case ServerStatus.Initializing:
case ServerStatus.Stopping:
case ServerStatus.Uninstalled:
case ServerStatus.Unknown:
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileBadStatus"), profileId, server.Runtime.StatusString));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileBadStatus"), server.Profile.ProfileName, server.Runtime.StatusString));
case ServerStatus.Updating:
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileUpdating"), profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileUpdating"), server.Profile.ProfileName));
}
profile = ServerProfileSnapshot.Create(server.Profile);
@@ -354,7 +405,9 @@ namespace ServerManagerTool.Utils
{
TaskUtils.RunOnUIThreadAsync(() =>
{
- var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
+ var server = ServerManager.Instance.Servers.First(s => string.Equals(channelId, s.Profile.DiscordChannelId, StringComparison.OrdinalIgnoreCase)
+ && (string.Equals(profileIdOrAlias, s.Profile.ProfileID, StringComparison.OrdinalIgnoreCase)
+ || !string.IsNullOrWhiteSpace(s.Profile.DiscordAlias) && string.Equals(profileIdOrAlias, s.Profile.DiscordAlias, StringComparison.OrdinalIgnoreCase)));
server.Runtime.UpdateServerStatus(serverStatus, true);
}).Wait();
}
@@ -363,7 +416,7 @@ namespace ServerManagerTool.Utils
task = Task.Run(() =>
{
app.PerformProfileShutdown(profile, true, false, false, false, token);
- _currentProfileCommands.Remove(profileId);
+ _currentProfileCommands.Remove(key);
});
response.Add(string.Format(_globalizer.GetResourceString("DiscordBot_RestartRequested"), profile.ServerName));
@@ -374,24 +427,19 @@ namespace ServerManagerTool.Utils
{
if (task is null)
{
- _currentProfileCommands.Remove(profileId);
+ _currentProfileCommands.Remove(key);
}
}
}
- private static IList ShutdownServer(string channelId, string profileId, CancellationToken token)
+ private static IList ShutdownServer(string channelId, string profileIdOrAlias, CancellationToken token)
{
- if (string.IsNullOrWhiteSpace(profileId))
+ if (string.IsNullOrWhiteSpace(profileIdOrAlias))
{
return new List { string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMissing"), CommandType.Shutdown) };
}
- // check if another command is being run against the profile
- if (_currentProfileCommands.ContainsKey(profileId))
- {
- return new List { string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[profileId], profileId) };
- }
- _currentProfileCommands.Add(profileId, CommandType.Shutdown);
+ var key = string.Empty;
ServerProfileSnapshot profile = null;
Task task = null;
@@ -400,18 +448,35 @@ namespace ServerManagerTool.Utils
{
TaskUtils.RunOnUIThreadAsync(() =>
{
- var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
+ var serverList = ServerManager.Instance.Servers.Where(s => string.Equals(channelId, s.Profile.DiscordChannelId, StringComparison.OrdinalIgnoreCase)
+ && (string.Equals(profileIdOrAlias, s.Profile.ProfileID, StringComparison.OrdinalIgnoreCase)
+ || !string.IsNullOrWhiteSpace(s.Profile.DiscordAlias) && string.Equals(profileIdOrAlias, s.Profile.DiscordAlias, StringComparison.OrdinalIgnoreCase)));
- if (server is null)
+ if (serverList.IsEmpty())
{
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileIdOrAlias));
}
+ if (!serverList.HasOne())
+ {
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMultiples"), profileIdOrAlias));
+ }
+
+ var server = serverList.First();
if (!server.Profile.AllowDiscordShutdown)
{
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandDisabledProfile"), CommandType.Shutdown, profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandDisabledProfile"), CommandType.Shutdown, server.Profile.ProfileName));
}
+ // check if another command is being run against the profile
+ if (_currentProfileCommands.ContainsKey(server.Profile.ProfileID))
+ {
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[server.Profile.ProfileID], server.Profile.ProfileName));
+ }
+
+ key = server.Profile.ProfileID;
+ _currentProfileCommands.Add(key, CommandType.Shutdown);
+
switch (server.Runtime.Status)
{
case ServerStatus.Initializing:
@@ -419,10 +484,10 @@ namespace ServerManagerTool.Utils
case ServerStatus.Stopped:
case ServerStatus.Uninstalled:
case ServerStatus.Unknown:
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileBadStatus"), profileId, server.Runtime.StatusString));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileBadStatus"), server.Profile.ProfileName, server.Runtime.StatusString));
case ServerStatus.Updating:
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileUpdating"), profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileUpdating"), server.Profile.ProfileName));
}
profile = ServerProfileSnapshot.Create(server.Profile);
@@ -441,7 +506,9 @@ namespace ServerManagerTool.Utils
{
TaskUtils.RunOnUIThreadAsync(() =>
{
- var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
+ var server = ServerManager.Instance.Servers.First(s => string.Equals(channelId, s.Profile.DiscordChannelId, StringComparison.OrdinalIgnoreCase)
+ && (string.Equals(profileIdOrAlias, s.Profile.ProfileID, StringComparison.OrdinalIgnoreCase)
+ || !string.IsNullOrWhiteSpace(s.Profile.DiscordAlias) && string.Equals(profileIdOrAlias, s.Profile.DiscordAlias, StringComparison.OrdinalIgnoreCase)));
server.Runtime.UpdateServerStatus(serverStatus, true);
}).Wait();
}
@@ -450,7 +517,7 @@ namespace ServerManagerTool.Utils
task = Task.Run(() =>
{
app.PerformProfileShutdown(profile, false, false, false, false, token);
- _currentProfileCommands.Remove(profileId);
+ _currentProfileCommands.Remove(key);
});
response.Add(string.Format(_globalizer.GetResourceString("DiscordBot_ShutdownRequested"), profile.ServerName));
@@ -461,24 +528,19 @@ namespace ServerManagerTool.Utils
{
if (task is null)
{
- _currentProfileCommands.Remove(profileId);
+ _currentProfileCommands.Remove(key);
}
}
}
- private static IList StopServer(string channelId, string profileId, CancellationToken token)
+ private static IList StopServer(string channelId, string profileIdOrAlias, CancellationToken token)
{
- if (string.IsNullOrWhiteSpace(profileId))
+ if (string.IsNullOrWhiteSpace(profileIdOrAlias))
{
return new List { string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMissing"), CommandType.Stop) };
}
- // check if another command is being run against the profile
- if (_currentProfileCommands.ContainsKey(profileId))
- {
- return new List { string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[profileId], profileId) };
- }
- _currentProfileCommands.Add(profileId, CommandType.Stop);
+ var key = string.Empty;
ServerProfileSnapshot profile = null;
Task task = null;
@@ -487,18 +549,35 @@ namespace ServerManagerTool.Utils
{
TaskUtils.RunOnUIThreadAsync(() =>
{
- var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
+ var serverList = ServerManager.Instance.Servers.Where(s => string.Equals(channelId, s.Profile.DiscordChannelId, StringComparison.OrdinalIgnoreCase)
+ && (string.Equals(profileIdOrAlias, s.Profile.ProfileID, StringComparison.OrdinalIgnoreCase)
+ || !string.IsNullOrWhiteSpace(s.Profile.DiscordAlias) && string.Equals(profileIdOrAlias, s.Profile.DiscordAlias, StringComparison.OrdinalIgnoreCase)));
- if (server is null)
+ if (serverList.IsEmpty())
{
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileIdOrAlias));
}
+ if (!serverList.HasOne())
+ {
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMultiples"), profileIdOrAlias));
+ }
+
+ var server = serverList.First();
if (!server.Profile.AllowDiscordStop)
{
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandDisabledProfile"), CommandType.Stop, profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandDisabledProfile"), CommandType.Stop, server.Profile.ProfileName));
}
+ // check if another command is being run against the profile
+ if (_currentProfileCommands.ContainsKey(server.Profile.ProfileID))
+ {
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[server.Profile.ProfileID], server.Profile.ProfileName));
+ }
+
+ key = server.Profile.ProfileID;
+ _currentProfileCommands.Add(key, CommandType.Stop);
+
switch (server.Runtime.Status)
{
case ServerStatus.Initializing:
@@ -506,10 +585,10 @@ namespace ServerManagerTool.Utils
case ServerStatus.Stopped:
case ServerStatus.Uninstalled:
case ServerStatus.Unknown:
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileBadStatus"), profileId, server.Runtime.StatusString));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileBadStatus"), server.Profile.ProfileName, server.Runtime.StatusString));
case ServerStatus.Updating:
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileUpdating"), profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileUpdating"), server.Profile.ProfileName));
}
profile = ServerProfileSnapshot.Create(server.Profile);
@@ -523,13 +602,15 @@ namespace ServerManagerTool.Utils
OutputLogs = false,
SendAlerts = true,
SendEmails = false,
- ServerProcess = ServerProcessType.Shutdown,
+ ServerProcess = ServerProcessType.Stop,
ShutdownInterval = 0,
ServerStatusChangeCallback = (ServerStatus serverStatus) =>
{
TaskUtils.RunOnUIThreadAsync(() =>
{
- var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
+ var server = ServerManager.Instance.Servers.First(s => string.Equals(channelId, s.Profile.DiscordChannelId, StringComparison.OrdinalIgnoreCase)
+ && (string.Equals(profileIdOrAlias, s.Profile.ProfileID, StringComparison.OrdinalIgnoreCase)
+ || !string.IsNullOrWhiteSpace(s.Profile.DiscordAlias) && string.Equals(profileIdOrAlias, s.Profile.DiscordAlias, StringComparison.OrdinalIgnoreCase)));
server.Runtime.UpdateServerStatus(serverStatus, true);
}).Wait();
}
@@ -538,7 +619,7 @@ namespace ServerManagerTool.Utils
task = Task.Run(() =>
{
app.PerformProfileShutdown(profile, false, false, false, false, token);
- _currentProfileCommands.Remove(profileId);
+ _currentProfileCommands.Remove(key);
});
response.Add(string.Format(_globalizer.GetResourceString("DiscordBot_StopRequested"), profile.ServerName));
@@ -549,24 +630,19 @@ namespace ServerManagerTool.Utils
{
if (task is null)
{
- _currentProfileCommands.Remove(profileId);
+ _currentProfileCommands.Remove(key);
}
}
}
- private static IList StartServer(string channelId, string profileId, CancellationToken token)
+ private static IList StartServer(string channelId, string profileIdOrAlias, CancellationToken token)
{
- if (string.IsNullOrWhiteSpace(profileId))
+ if (string.IsNullOrWhiteSpace(profileIdOrAlias))
{
return new List { string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMissing"), CommandType.Start) };
}
- // check if another command is being run against the profile
- if (_currentProfileCommands.ContainsKey(profileId))
- {
- return new List { string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[profileId], profileId) };
- }
- _currentProfileCommands.Add(profileId, CommandType.Start);
+ var key = string.Empty;
ServerProfileSnapshot profile = null;
Task task = null;
@@ -575,18 +651,35 @@ namespace ServerManagerTool.Utils
{
TaskUtils.RunOnUIThreadAsync(() =>
{
- var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
+ var serverList = ServerManager.Instance.Servers.Where(s => string.Equals(channelId, s.Profile.DiscordChannelId, StringComparison.OrdinalIgnoreCase)
+ && (string.Equals(profileIdOrAlias, s.Profile.ProfileID, StringComparison.OrdinalIgnoreCase)
+ || !string.IsNullOrWhiteSpace(s.Profile.DiscordAlias) && string.Equals(profileIdOrAlias, s.Profile.DiscordAlias, StringComparison.OrdinalIgnoreCase)));
- if (server is null)
+ if (serverList.IsEmpty())
{
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileIdOrAlias));
}
+ if (!serverList.HasOne())
+ {
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMultiples"), profileIdOrAlias));
+ }
+
+ var server = serverList.First();
if (!server.Profile.AllowDiscordStart)
{
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandDisabledProfile"), CommandType.Start, profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandDisabledProfile"), CommandType.Start, server.Profile.ProfileName));
}
+ // check if another command is being run against the profile
+ if (_currentProfileCommands.ContainsKey(server.Profile.ProfileID))
+ {
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[server.Profile.ProfileID], server.Profile.ProfileName));
+ }
+
+ key = server.Profile.ProfileID;
+ _currentProfileCommands.Add(key, CommandType.Start);
+
switch (server.Runtime.Status)
{
case ServerStatus.Initializing:
@@ -594,10 +687,10 @@ namespace ServerManagerTool.Utils
case ServerStatus.Running:
case ServerStatus.Uninstalled:
case ServerStatus.Unknown:
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileBadStatus"), profileId, server.Runtime.StatusString));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileBadStatus"), server.Profile.ProfileName, server.Runtime.StatusString));
case ServerStatus.Updating:
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileUpdating"), profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileUpdating"), server.Profile.ProfileName));
}
profile = ServerProfileSnapshot.Create(server.Profile);
@@ -617,7 +710,9 @@ namespace ServerManagerTool.Utils
{
TaskUtils.RunOnUIThreadAsync(() =>
{
- var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
+ var server = ServerManager.Instance.Servers.First(s => string.Equals(channelId, s.Profile.DiscordChannelId, StringComparison.OrdinalIgnoreCase)
+ && (string.Equals(profileIdOrAlias, s.Profile.ProfileID, StringComparison.OrdinalIgnoreCase)
+ || !string.IsNullOrWhiteSpace(s.Profile.DiscordAlias) && string.Equals(profileIdOrAlias, s.Profile.DiscordAlias, StringComparison.OrdinalIgnoreCase)));
server.Runtime.UpdateServerStatus(serverStatus, true);
}).Wait();
}
@@ -626,7 +721,7 @@ namespace ServerManagerTool.Utils
task = Task.Run(() =>
{
app.PerformProfileShutdown(profile, true, false, false, false, token);
- _currentProfileCommands.Remove(profileId);
+ _currentProfileCommands.Remove(key);
});
response.Add(string.Format(_globalizer.GetResourceString("DiscordBot_StartRequested"), profile.ServerName));
@@ -637,24 +732,19 @@ namespace ServerManagerTool.Utils
{
if (task is null)
{
- _currentProfileCommands.Remove(profileId);
+ _currentProfileCommands.Remove(key);
}
}
}
- private static IList UpdateServer(string channelId, string profileId, CancellationToken token)
+ private static IList UpdateServer(string channelId, string profileIdOrAlias, CancellationToken token)
{
- if (string.IsNullOrWhiteSpace(profileId))
+ if (string.IsNullOrWhiteSpace(profileIdOrAlias))
{
return new List { string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMissing"), CommandType.Update) };
}
- // check if another command is being run against the profile
- if (_currentProfileCommands.ContainsKey(profileId))
- {
- return new List { string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[profileId], profileId) };
- }
- _currentProfileCommands.Add(profileId, CommandType.Update);
+ var key = string.Empty;
ServerProfileSnapshot profile = null;
bool performRestart = false;
@@ -664,31 +754,48 @@ namespace ServerManagerTool.Utils
{
TaskUtils.RunOnUIThreadAsync(() =>
{
- var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
+ var serverList = ServerManager.Instance.Servers.Where(s => string.Equals(channelId, s.Profile.DiscordChannelId, StringComparison.OrdinalIgnoreCase)
+ && (string.Equals(profileIdOrAlias, s.Profile.ProfileID, StringComparison.OrdinalIgnoreCase)
+ || !string.IsNullOrWhiteSpace(s.Profile.DiscordAlias) && string.Equals(profileIdOrAlias, s.Profile.DiscordAlias, StringComparison.OrdinalIgnoreCase)));
- if (server is null)
+ if (serverList.IsEmpty())
{
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileNotFound"), profileIdOrAlias));
}
+ if (!serverList.HasOne())
+ {
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileMultiples"), profileIdOrAlias));
+ }
+
+ var server = serverList.First();
if (!server.Profile.AllowDiscordUpdate)
{
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandDisabledProfile"), CommandType.Update, profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandDisabledProfile"), CommandType.Update, server.Profile.ProfileName));
}
+ // check if another command is being run against the profile
+ if (_currentProfileCommands.ContainsKey(server.Profile.ProfileID))
+ {
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_CommandRunningProfile"), _currentProfileCommands[server.Profile.ProfileID], server.Profile.ProfileName));
+ }
+
+ key = server.Profile.ProfileID;
+ _currentProfileCommands.Add(key, CommandType.Update);
+
switch (server.Runtime.Status)
{
case ServerStatus.Initializing:
case ServerStatus.Stopping:
case ServerStatus.Unknown:
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileBadStatus"), profileId, server.Runtime.StatusString));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileBadStatus"), server.Profile.ProfileName, server.Runtime.StatusString));
case ServerStatus.Running:
performRestart = true;
break;
case ServerStatus.Updating:
- throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileUpdating"), profileId));
+ throw new Exception(string.Format(_globalizer.GetResourceString("DiscordBot_ProfileUpdating"), server.Profile.ProfileName));
}
profile = ServerProfileSnapshot.Create(server.Profile);
@@ -707,7 +814,9 @@ namespace ServerManagerTool.Utils
{
TaskUtils.RunOnUIThreadAsync(() =>
{
- var server = ServerManager.Instance.Servers.FirstOrDefault(s => Equals(channelId, s.Profile.DiscordChannelId) && Equals(profileId, s.Profile.ProfileID));
+ var server = ServerManager.Instance.Servers.First(s => string.Equals(channelId, s.Profile.DiscordChannelId, StringComparison.OrdinalIgnoreCase)
+ && (string.Equals(profileIdOrAlias, s.Profile.ProfileID, StringComparison.OrdinalIgnoreCase)
+ || !string.IsNullOrWhiteSpace(s.Profile.DiscordAlias) && string.Equals(profileIdOrAlias, s.Profile.DiscordAlias, StringComparison.OrdinalIgnoreCase)));
server.Runtime.UpdateServerStatus(serverStatus, true);
}).Wait();
}
@@ -716,7 +825,7 @@ namespace ServerManagerTool.Utils
task = Task.Run(() =>
{
app.PerformProfileShutdown(profile, performRestart, true, false, false, token);
- _currentProfileCommands.Remove(profileId);
+ _currentProfileCommands.Remove(key);
});
response.Add(string.Format(_globalizer.GetResourceString("DiscordBot_UpdateRequested"), profile.ServerName));
@@ -727,7 +836,7 @@ namespace ServerManagerTool.Utils
{
if (task is null)
{
- _currentProfileCommands.Remove(profileId);
+ _currentProfileCommands.Remove(key);
}
}
}
diff --git a/src/ConanServerManager/Utils/ModUtils.cs b/src/ConanServerManager/Utils/ModUtils.cs
index 0cb51fcd..6435e68e 100644
--- a/src/ConanServerManager/Utils/ModUtils.cs
+++ b/src/ConanServerManager/Utils/ModUtils.cs
@@ -86,7 +86,7 @@ namespace ServerManagerTool.Utils
Directory.CreateDirectory(modRootFolder);
// get the a list of the mod file into include in the mod file
- var modFileItems = modIdList.Select(m => $"{m}.pak").ToArray();
+ var modFileItems = modIdList.Select(m => $"{m}.pak");
// create the mod file.
File.WriteAllLines(modListFile, modFileItems);
}
diff --git a/src/ConanServerManager/VersionFeed.xml b/src/ConanServerManager/VersionFeed.xml
index ea8301b2..64d9c4ab 100644
--- a/src/ConanServerManager/VersionFeed.xml
+++ b/src/ConanServerManager/VersionFeed.xml
@@ -5,7 +5,67 @@
Conan Server Manager Version Feed
This is the Conan Server Manager release version feed.
- 2021-12-12T00:00:00Z
+ 2021-12-16T00:00:00Z
+
+
+ urn:uuid:19B09A66-43F2-4D5F-AF33-5C77D7EA9A6B
+ 1.1.58 (1.1.58.8)
+ 1.1.58.8
+
+ 2021-12-16T00:00:00Z
+
+
+
+ NEW
+
+
+ Main Window - Added Discord Bot Status and a button to Stop/Start the discord bot.
+ Global Settings - Discord Bot section - Added a log level droplist.
+ Global Settings - Discord Bot section - Added a checkbox to allow all bots.
+ Global Settings - Discord Bot section - Added a whitelist to allow bots to send commands to the server manager.
+ Server Settings - Discord Bot section - Added an alias that can be used with the discord command instead of the profile id.
+
+
CHANGE
+
+
+ Discord Bot - all commands are now case INsensitive, along with the profile id and the alias.
+ Discord Bot - removed the mandatory requirement to enter the '!' after the discord prefix. The '!' has been added to the existing prefix so no change to existing functionality, but you can now change it.
+ Made changes to the code to help improve performance.
+
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
+
+
+ urn:uuid:6383E79A-C31F-462B-9730-B26B28DC5EFF
+ 1.1.57 (1.1.57.3)
+ 1.1.57.3
+
+ 2021-12-15T00:00:00Z
+
+
+
+ BUGFIX
+
+
+ Fixed a bug with the Server Shutdown when the CheckForOnlinePlayers option not selected.
+ Fixed a bug when the backup path was a root directory that caused a 'Invalid URI: A Dos path must be rooted' crash.
+ Added additional validation when setting directories in the global setting, to ensure they are rooted correctly.
+ Fixed a bug when starting the server manager and it tries to download steamcmd, but fails as steamcmd is unavailable for download.
+
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
urn:uuid:F8A08616-749B-48E7-87D5-D97E86AB3926
diff --git a/src/ConanServerManager/VersionFeedBeta.xml b/src/ConanServerManager/VersionFeedBeta.xml
index 102fa702..9483dadb 100644
--- a/src/ConanServerManager/VersionFeedBeta.xml
+++ b/src/ConanServerManager/VersionFeedBeta.xml
@@ -5,114 +5,21 @@
Conan Server Manager Version Feed
This is the Conan Server Manager beta version feed.
- 2021-12-12T00:00:00Z
+ 2021-12-17T00:00:00Z
- urn:uuid:4C15C7A9-317C-4A9B-B426-6E885B918D3B
- 1.1.56 (1.1.56.6)
- 1.1.56.6
+ urn:uuid:9A427D82-9904-44F5-8C1E-7C943049869A
+ 1.1.58 (1.1.58.8)
+ 1.1.58.8
- 2021-12-12T00:00:00Z
-
-
-
- BUGFIX
-
-
- Reference library updates.
-
-
-
-
-
- bletch
- bletch1971@hotmail.com
-
-
-
-
- urn:uuid:126E8E9F-7FF2-4239-88D6-5FFC89925463
- 1.1.56 (1.1.56.5)
- 1.1.56.5
-
- 2021-12-10T00:00:00Z
-
-
-
- BUGFIX
-
-
- Server Monitor window now stores it's location.
- Reference library updates.
-
-
-
-
-
- bletch
- bletch1971@hotmail.com
-
-
-
-
- urn:uuid:BECA74AB-1107-40B0-932A-A851E978EABF
- 1.1.56 (1.1.56.4)
- 1.1.56.4
-
- 2021-12-09T00:00:00Z
-
-
-
- BUGFIX
-
-
- Fixed a minor issue when clicking the data directory reset button - fringe case that I found during testing.
-
-
-
-
-
- bletch
- bletch1971@hotmail.com
-
-
-
-
- urn:uuid:8C834060-F20F-4ACE-8F49-0B459531BA3C
- 1.1.56 (1.1.56.3)
- 1.1.56.3
-
- 2021-12-08T00:00:00Z
-
-
-
- BUGFIX
-
-
- Fixed language translation of Data Directory window.
-
-
-
-
-
- bletch
- bletch1971@hotmail.com
-
-
-
-
- urn:uuid:339F72FC-920A-4425-AF86-AF9B34611A21
- 1.1.56 (1.1.56.2)
- 1.1.56.2
-
- 2021-12-08T00:00:00Z
+ 2021-12-17T00:00:00Z
CHANGE
- Global Settings - Added reset button to the Data Directory Location.
+ Discord Bot - all commands are now case INsensitive, along with the profile id and the alias.
@@ -124,25 +31,162 @@
- urn:uuid:F8A08616-749B-48E7-87D5-D97E86AB3926
- 1.1.56 (1.1.56.1)
- 1.1.56.1
+ urn:uuid:9A427D82-9904-44F5-8C1E-7C943049869A
+ 1.1.58 (1.1.58.7)
+ 1.1.58.7
- 2021-12-06T00:00:00Z
+ 2021-12-17T00:00:00Z
NEW
-
- A new Discord Bot has been added to the server manager.
- This new discord bot will allow you to send Start, Stop, Shutdown, Restart, Backup and Update commands to the server manager from within your discord client.
- To setup the new discord bot, open the global settings and scroll down to the Discord section.
-
- NOTE: This is long process to get the discord bot working, and I have created a forum post with detailed instructions how to do it.
-
-
+ Main Window - Added Discord Bot Status and a button to Stop/Start the discord bot.
+ Global Settings - Discord Bot section - Added a checkbox to allow all bots.
+
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
+
+
+ urn:uuid:A189668E-DA03-471A-9C5A-7FF2A7264F9C
+ 1.1.58 (1.1.58.6)
+ 1.1.58.6
+
+ 2021-12-17T00:00:00Z
+
+
+
+ CHANGE
+
+
+ Added additional message logging when log level set to debug.
+
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
+
+
+ urn:uuid:A189668E-DA03-471A-9C5A-7FF2A7264F9C
+ 1.1.58 (1.1.58.5)
+ 1.1.58.5
+
+ 2021-12-16T00:00:00Z
+
+
+
+ NEW
+
+
+ Global Settings - Discord Bot section - Added a log level droplist.
+
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
+
+
+ urn:uuid:F3C22842-A089-46F7-AB1A-5D3DED105412
+ 1.1.58 (1.1.58.4)
+ 1.1.58.4
+
+ 2021-12-16T00:00:00Z
+
+
+
+ BUGFIX
+
+
+ Fixed a bug that would prevent a bot on the whitelist processing the message.
+
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
+
+
+ urn:uuid:F3C22842-A089-46F7-AB1A-5D3DED105412
+ 1.1.58 (1.1.58.3)
+ 1.1.58.3
+
+ 2021-12-16T00:00:00Z
+
+
+
+ NEW
+
+
+ Server Settings - Discord Bot section - Added an alias that can be used with the discord command instead of the profile id.
+
+
CHANGE
+
+
+ Removed the mandatory requirement to enter the '!' after the discord prefix. The '!' has been added to the existing prefix so no change to existing functionality, but you can now change it.
+
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
+
+
+ urn:uuid:C566D9D2-3566-46DF-8AD4-39F5FC0FFEF2
+ 1.1.58 (1.1.58.2)
+ 1.1.58.2
+
+ 2021-12-16T00:00:00Z
+
+
+
+ NEW
+
+
+ Global Settings - Discord Bot section - Added a whitelist to allow bots to send commands to the server manager.
+
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
+
+
+ urn:uuid:19B09A66-43F2-4D5F-AF33-5C77D7EA9A6B
+ 1.1.58 (1.1.58.1)
+ 1.1.58.1
+
+ 2021-12-16T00:00:00Z
+
+
+
+ CHANGE
+
+
+ Made changes to the code to help improve performance.
diff --git a/src/ConanServerManager/Windows/AutoUpdateWindow.xaml b/src/ConanServerManager/Windows/AutoUpdateWindow.xaml
index 61072172..f6347054 100644
--- a/src/ConanServerManager/Windows/AutoUpdateWindow.xaml
+++ b/src/ConanServerManager/Windows/AutoUpdateWindow.xaml
@@ -18,6 +18,7 @@
+
diff --git a/src/ConanServerManager/Windows/AutoUpdateWindow.xaml.cs b/src/ConanServerManager/Windows/AutoUpdateWindow.xaml.cs
index fa852ba1..4b729f62 100644
--- a/src/ConanServerManager/Windows/AutoUpdateWindow.xaml.cs
+++ b/src/ConanServerManager/Windows/AutoUpdateWindow.xaml.cs
@@ -2,6 +2,7 @@
using ServerManagerTool.Common.Utils;
using System;
using System.Threading;
+using System.Threading.Tasks;
using System.Windows;
using WPFSharp.Globalizer;
@@ -12,15 +13,16 @@ namespace ServerManagerTool
///
public partial class AutoUpdateWindow : Window
{
- private GlobalizedApplication _globalizer = GlobalizedApplication.Instance;
-
- private SteamCmdUpdater updater = new SteamCmdUpdater();
+ private readonly GlobalizedApplication _globalizer = GlobalizedApplication.Instance;
+ private readonly SteamCmdUpdater updater = new SteamCmdUpdater();
private CancellationTokenSource cancelSource;
public AutoUpdateWindow()
{
InitializeComponent();
WindowUtils.RemoveDefaultResourceDictionary(this, Config.Default.DefaultGlobalizationFile);
+
+ this.ErrorLabel.Visibility = Visibility.Collapsed;
}
private void Window_Loaded(object sender, RoutedEventArgs e)
@@ -32,10 +34,13 @@ namespace ServerManagerTool
this.StatusLabel.Content = message;
this.CompletionProgress.Value = u.CompletionPercent;
- if(u.FailureText != null)
+ if (u.FailureText != null)
{
- // TODO: Report error through UI
- throw new Exception(u.FailureText);
+ this.ErrorLabel.Text = u.FailureText;
+ this.ErrorLabel.Visibility = Visibility.Visible;
+ await Task.Delay(10000);
+
+ Environment.Exit(1);
}
if (u.CompletionPercent >= 100 || u.Cancelled)
diff --git a/src/ConanServerManager/Windows/MainWindow.xaml b/src/ConanServerManager/Windows/MainWindow.xaml
index 8a4cd1d7..c80333e3 100644
--- a/src/ConanServerManager/Windows/MainWindow.xaml
+++ b/src/ConanServerManager/Windows/MainWindow.xaml
@@ -9,6 +9,7 @@
xmlns:cvr="clr-namespace:ServerManagerTool.Common.ValidationRules;assembly=ServerManager.Common"
xmlns:com="clr-namespace:ServerManagerTool.Common;assembly=ServerManager.Common"
xmlns:enum="clr-namespace:ServerManagerTool.Enums"
+ xmlns:bot="clr-namespace:ServerManagerTool.DiscordBot;assembly=ServerManager.Discord"
MinWidth="900" MinHeight="600" Width="1100" Height="900" Left="50" Top="50" WindowState="Normal"
Loaded="MainWindow_Loaded" SizeChanged="MainWindow_SizeChanged" StateChanged="MainWindow_StateChanged" LocationChanged="MainWindow_LocationChanged"
Name="Main" Icon="../Art/favicon.ico" Title="{DynamicResource MainWindow_Title}">
@@ -128,6 +129,7 @@
+
@@ -253,6 +255,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/ConanServerManager/Windows/MainWindow.xaml.cs b/src/ConanServerManager/Windows/MainWindow.xaml.cs
index d901db40..67cda009 100644
--- a/src/ConanServerManager/Windows/MainWindow.xaml.cs
+++ b/src/ConanServerManager/Windows/MainWindow.xaml.cs
@@ -30,6 +30,9 @@ namespace ServerManagerTool
private readonly GlobalizedApplication _globalizer = GlobalizedApplication.Instance;
private readonly ActionQueue versionChecker;
private readonly ActionQueue scheduledTaskChecker;
+ private readonly ActionQueue discordBotChecker;
+
+ private bool discordBotStateClicked = false;
public static readonly DependencyProperty AppInstanceProperty = DependencyProperty.Register(nameof(AppInstance), typeof(App), typeof(MainWindow), new PropertyMetadata(null));
public static readonly DependencyProperty ConfigProperty = DependencyProperty.Register(nameof(Config), typeof(Config), typeof(MainWindow), new PropertyMetadata(null));
@@ -40,10 +43,54 @@ namespace ServerManagerTool
public static readonly DependencyProperty AutoUpdateStateProperty = DependencyProperty.Register(nameof(AutoUpdateState), typeof(Microsoft.Win32.TaskScheduler.TaskState), typeof(MainWindow), new PropertyMetadata(Microsoft.Win32.TaskScheduler.TaskState.Unknown));
public static readonly DependencyProperty AutoUpdateStateStringProperty = DependencyProperty.Register(nameof(AutoUpdateStateString), typeof(string), typeof(MainWindow), new PropertyMetadata(string.Empty));
public static readonly DependencyProperty AutoUpdateNextRunTimeProperty = DependencyProperty.Register(nameof(AutoUpdateNextRunTime), typeof(string), typeof(MainWindow), new PropertyMetadata(string.Empty));
+ public static readonly DependencyProperty DiscordBotStateProperty = DependencyProperty.Register(nameof(DiscordBotState), typeof(DiscordBot.Enums.BotState), typeof(MainWindow), new PropertyMetadata(DiscordBot.Enums.BotState.Unknown));
+ public static readonly DependencyProperty DiscordBotStateStringProperty = DependencyProperty.Register(nameof(DiscordBotStateString), typeof(string), typeof(MainWindow), new PropertyMetadata(string.Empty));
public static readonly DependencyProperty IsIpValidProperty = DependencyProperty.Register(nameof(IsIpValid), typeof(bool), typeof(MainWindow), new PropertyMetadata(false));
public static readonly DependencyProperty LatestServerManagerVersionProperty = DependencyProperty.Register(nameof(LatestServerManagerVersion), typeof(Version), typeof(MainWindow), new PropertyMetadata(new Version()));
public static readonly DependencyProperty NewServerManagerAvailableProperty = DependencyProperty.Register(nameof(NewServerManagerAvailable), typeof(bool), typeof(MainWindow), new PropertyMetadata(false));
+ public MainWindow()
+ {
+ this.AppInstance = App.Instance;
+ this.Config = Config.Default;
+
+ InitializeComponent();
+ WindowUtils.RemoveDefaultResourceDictionary(this, Config.Default.DefaultGlobalizationFile);
+
+ this.ServerManager = ServerManager.Instance;
+
+ this.DataContext = this;
+ this.versionChecker = new ActionQueue();
+ this.scheduledTaskChecker = new ActionQueue();
+ this.discordBotChecker = new ActionQueue();
+
+ IsAdministrator = SecurityUtils.IsAdministrator();
+ if (!string.IsNullOrWhiteSpace(App.Instance.Title))
+ {
+ this.Title = App.Instance.Title;
+ }
+ else
+ {
+ if (IsAdministrator)
+ {
+ this.Title = _globalizer.GetResourceString("MainWindow_TitleWithAdmin");
+ }
+ else
+ {
+ this.Title = _globalizer.GetResourceString("MainWindow_Title");
+ }
+ }
+
+ this.Left = Config.Default.MainWindow_Left;
+ this.Top = Config.Default.MainWindow_Top;
+ this.Height = Config.Default.MainWindow_Height;
+ this.Width = Config.Default.MainWindow_Width;
+ this.WindowState = Config.Default.MainWindow_WindowState;
+
+ // hook into the language change event
+ GlobalizedApplication.Instance.GlobalizationManager.ResourceDictionaryChangedEvent += ResourceDictionaryChangedEvent;
+ }
+
public App AppInstance
{
get { return GetValue(AppInstanceProperty) as App; }
@@ -98,6 +145,18 @@ namespace ServerManagerTool
set { SetValue(AutoUpdateNextRunTimeProperty, value); }
}
+ public DiscordBot.Enums.BotState DiscordBotState
+ {
+ get { return (DiscordBot.Enums.BotState)GetValue(DiscordBotStateProperty); }
+ set { SetValue(DiscordBotStateProperty, value); }
+ }
+
+ public string DiscordBotStateString
+ {
+ get { return (string)GetValue(DiscordBotStateStringProperty); }
+ set { SetValue(DiscordBotStateStringProperty, value); }
+ }
+
public bool IsAdministrator
{
get;
@@ -122,47 +181,6 @@ namespace ServerManagerTool
set { SetValue(NewServerManagerAvailableProperty, value); }
}
- public MainWindow()
- {
- this.AppInstance = App.Instance;
- this.Config = Config.Default;
-
- InitializeComponent();
- WindowUtils.RemoveDefaultResourceDictionary(this, Config.Default.DefaultGlobalizationFile);
-
- this.ServerManager = ServerManager.Instance;
-
- this.DataContext = this;
- this.versionChecker = new ActionQueue();
- this.scheduledTaskChecker = new ActionQueue();
-
- IsAdministrator = SecurityUtils.IsAdministrator();
- if (!string.IsNullOrWhiteSpace(App.Instance.Title))
- {
- this.Title = App.Instance.Title;
- }
- else
- {
- if (IsAdministrator)
- {
- this.Title = _globalizer.GetResourceString("MainWindow_TitleWithAdmin");
- }
- else
- {
- this.Title = _globalizer.GetResourceString("MainWindow_Title");
- }
- }
-
- this.Left = Config.Default.MainWindow_Left;
- this.Top = Config.Default.MainWindow_Top;
- this.Height = Config.Default.MainWindow_Height;
- this.Width = Config.Default.MainWindow_Width;
- this.WindowState = Config.Default.MainWindow_WindowState;
-
- // hook into the language change event
- GlobalizedApplication.Instance.GlobalizationManager.ResourceDictionaryChangedEvent += ResourceDictionaryChangedEvent;
- }
-
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
//
@@ -191,6 +209,7 @@ namespace ServerManagerTool
this.versionChecker.PostAction(CheckForUpdates).DoNotWait();
this.scheduledTaskChecker.PostAction(CheckForScheduledTasks).DoNotWait();
+ this.discordBotChecker.PostAction(CheckForDiscordBot).DoNotWait();
}
private void MainWindow_LocationChanged(object sender, EventArgs e)
@@ -254,6 +273,7 @@ namespace ServerManagerTool
this.Title = _globalizer.GetResourceString("MainWindow_Title");
this.scheduledTaskChecker.PostAction(CheckForScheduledTasks).DoNotWait();
+ this.discordBotChecker.PostAction(CheckForDiscordBot).DoNotWait();
}
private void PatchNotes_Click(object sender, RoutedEventArgs e)
@@ -563,6 +583,36 @@ namespace ServerManagerTool
}
}
+ private async void DiscordBotTaskState_Click(object sender, RoutedEventArgs e)
+ {
+ if (discordBotStateClicked)
+ return;
+ discordBotStateClicked = true;
+
+ try
+ {
+ switch (DiscordBotState)
+ {
+ case DiscordBot.Enums.BotState.Stopped:
+ AppInstance.StartDiscordBot();
+ break;
+ case DiscordBot.Enums.BotState.Running:
+ AppInstance.StopDiscordBot();
+ break;
+ }
+
+ await Task.Delay(5000);
+ }
+ catch (Exception)
+ {
+ // Ignore.
+ }
+ finally
+ {
+ discordBotStateClicked = false;
+ }
+ }
+
public ICommand ShowWindowCommand
{
get
@@ -654,8 +704,8 @@ namespace ServerManagerTool
this.AutoBackupState = backupState;
this.AutoUpdateState = updateState;
- this.AutoBackupStateString = GetTaskStateString(AutoBackupState);
- this.AutoUpdateStateString = GetTaskStateString(AutoUpdateState);
+ this.AutoBackupStateString = GetTaskSchedulerStateString(AutoBackupState);
+ this.AutoUpdateStateString = GetTaskSchedulerStateString(AutoUpdateState);
this.AutoBackupNextRunTime = backupnextRunTime == DateTime.MinValue ? string.Empty : $"{_globalizer.GetResourceString("MainWindow_TaskRunTimeLabel")} {backupnextRunTime:G}";
this.AutoUpdateNextRunTime = updatenextRunTime == DateTime.MinValue ? string.Empty : $"{_globalizer.GetResourceString("MainWindow_TaskRunTimeLabel")} {updatenextRunTime:G}";
@@ -672,7 +722,46 @@ namespace ServerManagerTool
this.scheduledTaskChecker.PostAction(CheckForScheduledTasks).DoNotWait();
}
- private string GetTaskStateString(Microsoft.Win32.TaskScheduler.TaskState taskState)
+ private async Task CheckForDiscordBot()
+ {
+ TaskUtils.RunOnUIThreadAsync(() =>
+ {
+ try
+ {
+ var botState = DiscordBot.Enums.BotState.Unknown;
+ if (AppInstance.DiscordBotStarted)
+ {
+ botState = DiscordBot.Enums.BotState.Running;
+ }
+ else
+ {
+ if (Config.DiscordBotEnabled)
+ {
+ botState = DiscordBot.Enums.BotState.Stopped;
+ }
+ else
+ {
+ botState = DiscordBot.Enums.BotState.Disabled;
+ }
+ }
+
+ this.DiscordBotState = botState;
+
+ this.DiscordBotStateString = GetDiscordBotStateString(botState);
+
+ Logger.Info($"{nameof(CheckForDiscordBot)} performed");
+ }
+ catch (Exception)
+ {
+ // Ignore.
+ }
+ }).DoNotWait();
+
+ await Task.Delay(Config.Default.DiscordBotStatusCheckTime * 1 * 1000);
+ this.discordBotChecker.PostAction(CheckForDiscordBot).DoNotWait();
+ }
+
+ private string GetTaskSchedulerStateString(Microsoft.Win32.TaskScheduler.TaskState taskState)
{
switch (taskState)
{
@@ -691,6 +780,21 @@ namespace ServerManagerTool
}
}
+ private string GetDiscordBotStateString(DiscordBot.Enums.BotState botState)
+ {
+ switch (botState)
+ {
+ case DiscordBot.Enums.BotState.Disabled:
+ return _globalizer.GetResourceString("MainWindow_TaskStateDisabledLabel");
+ case DiscordBot.Enums.BotState.Running:
+ return _globalizer.GetResourceString("MainWindow_TaskStateRunningLabel");
+ case DiscordBot.Enums.BotState.Stopped:
+ return _globalizer.GetResourceString("MainWindow_TaskStateStoppedLabel");
+ default:
+ return _globalizer.GetResourceString("MainWindow_TaskStateUnknownLabel");
+ }
+ }
+
private async Task StartServerAsync(Server server)
{
if (server == null || server.Profile == null || server.Runtime == null || server.Runtime.Status != ServerStatus.Stopped)
diff --git a/src/ConanServerManager/Windows/RconWindow.xaml.cs b/src/ConanServerManager/Windows/RconWindow.xaml.cs
index 50690dde..94831f88 100644
--- a/src/ConanServerManager/Windows/RconWindow.xaml.cs
+++ b/src/ConanServerManager/Windows/RconWindow.xaml.cs
@@ -1,4 +1,5 @@
using ServerManagerTool.Common.Enums;
+using ServerManagerTool.Common.Extensions;
using ServerManagerTool.Common.Lib;
using ServerManagerTool.Common.Utils;
using ServerManagerTool.Enums;
@@ -741,7 +742,7 @@ namespace ServerManagerTool
yield return new RconOutput_Command($"> {command.rawCommand}");
}
- if (!command.suppressOutput && command.lines.Count() > 0)
+ if (!command.suppressOutput && !command.lines.IsEmpty())
{
yield return new LineBreak();
}
diff --git a/src/ConanServerManager/Windows/SettingsWindow.xaml.cs b/src/ConanServerManager/Windows/SettingsWindow.xaml.cs
index d989298b..99005204 100644
--- a/src/ConanServerManager/Windows/SettingsWindow.xaml.cs
+++ b/src/ConanServerManager/Windows/SettingsWindow.xaml.cs
@@ -39,6 +39,8 @@ namespace ServerManagerTool
protected override void OnClosed(EventArgs e)
{
+ globalSettingsControl.ApplyChangesToConfig();
+
if (SecurityUtils.IsAdministrator())
{
// check if the Auto Update has been enabled.
diff --git a/src/Plugin.Common/Extensions/IEnumerableExtensions.cs b/src/Plugin.Common/Extensions/IEnumerableExtensions.cs
new file mode 100644
index 00000000..7fc11629
--- /dev/null
+++ b/src/Plugin.Common/Extensions/IEnumerableExtensions.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+
+namespace ServerManagerTool.Plugin.Common
+{
+ internal static class IEnumerableExtensions
+ {
+ public static bool IsEmpty(this IEnumerable source)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException(nameof(source));
+ }
+
+ using (IEnumerator enumerator = source.GetEnumerator())
+ {
+ if (enumerator.MoveNext())
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static bool HasOne(this IEnumerable source)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException(nameof(source));
+ }
+
+ var count = 0;
+
+ using (IEnumerator enumerator = source.GetEnumerator())
+ {
+ while (enumerator.MoveNext())
+ {
+ if (++count > 1)
+ return false;
+ }
+ }
+
+ return count == 1;
+ }
+ }
+}
diff --git a/src/Plugin.Common/PluginHelper.cs b/src/Plugin.Common/PluginHelper.cs
index 8f66f984..94728e63 100644
--- a/src/Plugin.Common/PluginHelper.cs
+++ b/src/Plugin.Common/PluginHelper.cs
@@ -272,7 +272,7 @@ namespace ServerManagerTool.Plugin.Common
return false;
var plugins = Plugins.Where(p => (p.PluginType is nameof(IAlertPlugin)) && (p.Plugin?.Enabled ?? false));
- if (plugins.Count() == 0)
+ if (plugins.IsEmpty())
return false;
lock (_syncLockProcessAlert)
diff --git a/src/Plugin.Discord/Config.Designer.cs b/src/Plugin.Discord/Config.Designer.cs
index fc944820..c7915f06 100644
--- a/src/Plugin.Discord/Config.Designer.cs
+++ b/src/Plugin.Discord/Config.Designer.cs
@@ -12,7 +12,7 @@ namespace ServerManagerTool.Plugin.Discord {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.8.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.0.3.0")]
internal sealed partial class Config : global::System.Configuration.ApplicationSettingsBase {
private static Config defaultInstance = ((Config)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Config())));
@@ -32,15 +32,6 @@ namespace ServerManagerTool.Plugin.Discord {
}
}
- [global::System.Configuration.ApplicationScopedSettingAttribute()]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("http://whatismyip.akamai.com/")]
- public string PublicIPCheckUrl {
- get {
- return ((string)(this["PublicIPCheckUrl"]));
- }
- }
-
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("12")]
@@ -154,5 +145,23 @@ namespace ServerManagerTool.Plugin.Discord {
return ((string)(this["VersionBetaFeedUrl"]));
}
}
+
+ [global::System.Configuration.ApplicationScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("https://api.ipify.org")]
+ public string PublicIPCheckUrl1 {
+ get {
+ return ((string)(this["PublicIPCheckUrl1"]));
+ }
+ }
+
+ [global::System.Configuration.ApplicationScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("http://whatismyip.akamai.com/")]
+ public string PublicIPCheckUrl2 {
+ get {
+ return ((string)(this["PublicIPCheckUrl2"]));
+ }
+ }
}
}
diff --git a/src/Plugin.Discord/Config.settings b/src/Plugin.Discord/Config.settings
index e95f2570..3548315e 100644
--- a/src/Plugin.Discord/Config.settings
+++ b/src/Plugin.Discord/Config.settings
@@ -5,9 +5,6 @@
http://servermanager.azurewebsites.net/api/plugin/call/{0}/{1}/
-
- http://whatismyip.akamai.com/
-
12
@@ -44,5 +41,11 @@
https://raw.githubusercontent.com/Bletch1971/ServerManagers/master/Plugins/Discord/beta/VersionFeed.xml
+
+ https://api.ipify.org
+
+
+ http://whatismyip.akamai.com/
+
\ No newline at end of file
diff --git a/src/Plugin.Discord/DiscordPlugin.cs b/src/Plugin.Discord/DiscordPlugin.cs
index 26f59402..b11ea349 100644
--- a/src/Plugin.Discord/DiscordPlugin.cs
+++ b/src/Plugin.Discord/DiscordPlugin.cs
@@ -115,7 +115,7 @@ namespace ServerManagerTool.Plugin.Discord
&& cp.AlertTypes.Any(pn => pn.Value.Equals(alertType))
&& cp.ProfileNames.Any(pn => pn.Value.Equals(profileName, StringComparison.OrdinalIgnoreCase))
&& !string.IsNullOrWhiteSpace(cp.DiscordWebhookUrl));
- if (configProfiles == null || configProfiles.Count() == 0)
+ if (configProfiles == null || configProfiles.IsEmpty())
{
#if DEBUG
var logFile = Path.Combine(PluginHelper.PluginFolder, "DiscordErrors.log");
diff --git a/src/Plugin.Discord/Extensions/IEnumerableExtensions.cs b/src/Plugin.Discord/Extensions/IEnumerableExtensions.cs
new file mode 100644
index 00000000..d99b13b7
--- /dev/null
+++ b/src/Plugin.Discord/Extensions/IEnumerableExtensions.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+
+namespace ServerManagerTool.Plugin.Discord
+{
+ internal static class IEnumerableExtensions
+ {
+ public static bool IsEmpty(this IEnumerable source)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException(nameof(source));
+ }
+
+ using (IEnumerator enumerator = source.GetEnumerator())
+ {
+ if (enumerator.MoveNext())
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static bool HasOne(this IEnumerable source)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException(nameof(source));
+ }
+
+ var count = 0;
+
+ using (IEnumerator enumerator = source.GetEnumerator())
+ {
+ while (enumerator.MoveNext())
+ {
+ if (++count > 1)
+ return false;
+ }
+ }
+
+ return count == 1;
+ }
+ }
+}
diff --git a/src/Plugin.Discord/Globalization/ru-RU/ru-RU.xaml b/src/Plugin.Discord/Globalization/ru-RU/ru-RU.xaml
new file mode 100644
index 00000000..d2f141ef
--- /dev/null
+++ b/src/Plugin.Discord/Globalization/ru-RU/ru-RU.xaml
@@ -0,0 +1,133 @@
+
+
+
+ Бекап
+ Ошибка
+ Обнаружено обновление Модов
+ Выключение
+ Сообщение о завершении работы
+ Причина отключения
+ Изменение статуса Сервера
+ Запуск
+ Результаты обновления
+
+
+
+ Отменить
+ Закрывать
+ OK
+ Сохранить
+
+ (Бета-режим)
+ Доступна новая версия плагина.
+ Загрузите последнюю версию.
+
+
+
+ Конфигурация плагина Discord
+
+ Просмотрите описание обновления
+ Добавить Профиль
+ Удалить Все Профили
+ Удалить Профиль
+ Редактировать профиль
+
+ Имя
+
+ Ошибка добавления действия
+ Произошла ошибка при попытке добавить профиль.
+ Подтвердить удаление всех действий
+ Нажмите «Да», чтобы подтвердить, что вы хотите удалить все.
+ Удалить все действия Ошибка
+ Произошла ошибка при попытке удалить все профили.
+ Подтвердить действие закрытия
+ Нажмите «Да», чтобы подтвердить, что вы хотите закрыть форму. Если у вас есть несохраненные изменения, они будут потеряны.
+ Подтвердить действие удаления
+ Нажмите «Да», чтобы подтвердить, что вы хотите выполнить удаление.
+ Удалить ошибку действия
+ Произошла ошибка при попытке удалить профиль.
+ Ошибка действия загрузки
+ Произошла ошибка при попытке выполнить загрузку.
+ Загрузка завершена
+ Последняя версия сохранена на вашем рабочем столе.
+ Ошибка редактирования действия
+ Произошла ошибка при попытке изменить профиль.
+ Ошибка сохранения
+ Произошла ошибка при попытке сохранить.
+
+
+
+ Конфигурация профиля
+
+ Имя:
+ Имя вашего профиля конфигурации.
+ Включено
+ Включить профиль конфигурации.
+ Webhook Url:
+ Это ваш URL Webhook, предоставленный Discord.
+ Имя бота:
+ Это переопределит имя, которое вы установили в своем Webhook. Оставьте поле пустым, чтобы использовать значение по умолчанию.
+ Use Text to Speech (TTS)
+ Если этот параметр включен, бот будет объявлять текст в речь, в противном случае отключит преобразование текста в речь.
+ Prefix Message with Profile Name
+ Если этот параметр включен, предупреждающее сообщение будет отправлено с префиксом имени профиля ASM.
+ Параметры сообщения
+ Bold
+ Если включено, сообщение будет выделено жирным шрифтом.
+ Underline
+ Если включено, отобразит сообщение с подчеркиванием.
+ Italic
+ Если включено, сообщение будет отображаться курсивом.
+ Embedded Code Block
+ Если включено, сообщение будет отображаться во встроенном блоке кода.
+ Имена профилей
+ Типы предупреждений
+
+ Добавить имя профиля ASM
+ Удалить все имена профиля ASM
+ Удалить имя профиля ASM
+
+ Добавить тип оповещения
+ Удалить все типы предупреждений
+ Удалить тип оповещения
+
+ Имя профиля ASM
+ Тип оповещения
+
+ Тест
+
+ Ошибка добавления действия
+ Произошла ошибка при попытке добавить тип предупреждения.
+ Произошла ошибка при попытке добавить имя профиля.
+ Подтвердить удаление всех действий
+ Нажмите «Да», чтобы подтвердить, что вы хотите удалить все.
+ Удалить все действия Ошибка
+ Произошла ошибка при попытке удалить все типы предупреждений.
+ Произошла ошибка при попытке удалить все имена профилей.
+ Подтвердить действие закрытия
+ Нажмите «Да», чтобы подтвердить, что вы хотите закрыть форму. Если у вас есть несохраненные изменения, они будут потеряны.
+ Подтвердите Действие Удаления
+ Нажмите "Да", чтобы подтвердить, что вы хотите выполнить удаление.
+ Ошибка Удаления Действия
+ При попытке удалить тип предупреждения произошла ошибка.
+ При попытке удалить имя профиля произошла ошибка.
+ Ошибка Тестового действия
+ При попытке проверить профиль конфигурации произошла ошибка.
+ Профиль не включен и не может быть протестирован.
+
+ Тест '{0}' тип предупреждения сообщение для имени профиля '{1}'
+
+
+
+ Сведения о версии плагина Discord
+ Ошибка загрузки Подачи
+
+ Версия:
+ Выберите версию для просмотра подробных сведений.
+
+
+
\ No newline at end of file
diff --git a/src/Plugin.Discord/Plugin.Discord.csproj b/src/Plugin.Discord/Plugin.Discord.csproj
index 59b5f303..8bfb7b03 100644
--- a/src/Plugin.Discord/Plugin.Discord.csproj
+++ b/src/Plugin.Discord/Plugin.Discord.csproj
@@ -32,6 +32,7 @@
+
@@ -66,6 +67,7 @@
+
diff --git a/src/Plugin.Discord/Utils/NetworkUtils.cs b/src/Plugin.Discord/Utils/NetworkUtils.cs
index 0590e7d4..05acefcd 100644
--- a/src/Plugin.Discord/Utils/NetworkUtils.cs
+++ b/src/Plugin.Discord/Utils/NetworkUtils.cs
@@ -13,10 +13,17 @@ namespace ServerManagerTool.Plugin.Discord
{
try
{
- var publicIP = await webClient.DownloadStringTaskAsync(Config.Default.PublicIPCheckUrl);
+ var publicIP = await webClient.DownloadStringTaskAsync(Config.Default.PublicIPCheckUrl1);
+ if (IPAddress.TryParse(publicIP, out IPAddress address1))
+ {
+ return address1;
+ }
- if (IPAddress.TryParse(publicIP, out IPAddress address))
- return address;
+ publicIP = await webClient.DownloadStringTaskAsync(Config.Default.PublicIPCheckUrl2);
+ if (IPAddress.TryParse(publicIP, out IPAddress address2))
+ {
+ return address2;
+ }
return IPAddress.None;
}
diff --git a/src/Plugin.Discord/VersionFeed.xml b/src/Plugin.Discord/VersionFeed.xml
index fae47834..b41b1f32 100644
--- a/src/Plugin.Discord/VersionFeed.xml
+++ b/src/Plugin.Discord/VersionFeed.xml
@@ -9,8 +9,8 @@
urn:uuid:A9EC2F32-E026-485F-BD7B-C657DBA95B54
- 1.0.19 (1.0.19.3)
- 1.0.19.3
+ 1.0.19 (1.0.19.5)
+ 1.0.19.5
2021-12-12T00:00:00Z
@@ -28,6 +28,7 @@
de-DE Translation file updated.
fr-FR Translation file added.
pt-BR Translation file updated.
+ ru-RU Translation file added.
diff --git a/src/Plugin.Discord/VersionFeedBeta.xml b/src/Plugin.Discord/VersionFeedBeta.xml
index 731453ee..0ffd8b43 100644
--- a/src/Plugin.Discord/VersionFeedBeta.xml
+++ b/src/Plugin.Discord/VersionFeedBeta.xml
@@ -7,6 +7,52 @@
2021-12-12T00:00:00Z
+
+ urn:uuid:A0D7BFD2-F2F0-481A-A22D-3C193BFB4C99
+ 1.0.19 (1.0.19.5)
+ 1.0.19.5
+
+ 2021-12-12T00:00:00Z
+
+
+
+ CHANGE
+
+
+ ru-RU Translation file updated.
+
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
+
+
+ urn:uuid:38A61493-CA4E-479E-A3FD-266565E83D90
+ 1.0.19 (1.0.19.4)
+ 1.0.19.4
+
+ 2021-12-12T00:00:00Z
+
+
+
+ CHANGE
+
+
+ ru-RU Translation file added.
+
+
+
+
+
+ bletch
+ bletch1971@hotmail.com
+
+
+
urn:uuid:DDB25735-1D20-4580-B5FE-1AD4BD107376
1.0.19 (1.0.19.3)
diff --git a/src/Plugin.Discord/app.config b/src/Plugin.Discord/app.config
index a2c1109e..76682998 100644
--- a/src/Plugin.Discord/app.config
+++ b/src/Plugin.Discord/app.config
@@ -10,9 +10,6 @@
http://servermanager.azurewebsites.net/api/plugin/call/{0}/{1}/
-
- http://whatismyip.akamai.com/
-
12
@@ -49,6 +46,12 @@
https://raw.githubusercontent.com/Bletch1971/ServerManagers/master/Plugins/Discord/beta/VersionFeed.xml
+
+ https://api.ipify.org
+
+
+ http://whatismyip.akamai.com/
+
diff --git a/src/QueryMaster/RconSource.cs b/src/QueryMaster/RconSource.cs
index 8980a872..bcfb974f 100644
--- a/src/QueryMaster/RconSource.cs
+++ b/src/QueryMaster/RconSource.cs
@@ -50,14 +50,7 @@ namespace QueryMaster
//consecutive rcon command replies start with an empty packet
if (BitConverter.ToInt32(recvData[i], 4) == (int)PacketId.Empty)
continue;
- //if (recvData[i].Length - BitConverter.ToInt32(recvData[i], 0) == 4)
- //{
str.Append(RconUtil.ProcessPacket(recvData[i]).Body);
- //}
- //else
- //{
- // str.Append(RconUtil.ProcessPacket(recvData[i]).Body + Util.BytesToString(recvData[++i].Take(recvData[i].Length - 2).ToArray()));
- //}
}
}
catch (Exception e)
diff --git a/src/QueryMaster/RconUtil.cs b/src/QueryMaster/RconUtil.cs
index 133e9596..a8d6c09b 100644
--- a/src/QueryMaster/RconUtil.cs
+++ b/src/QueryMaster/RconUtil.cs
@@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
namespace QueryMaster
{
diff --git a/src/ServerManager.Common/CommonConfig.Designer.cs b/src/ServerManager.Common/CommonConfig.Designer.cs
index 4e793e96..590d4991 100644
--- a/src/ServerManager.Common/CommonConfig.Designer.cs
+++ b/src/ServerManager.Common/CommonConfig.Designer.cs
@@ -12,7 +12,7 @@ namespace ServerManagerTool.Common {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.0.3.0")]
public sealed partial class CommonConfig : global::System.Configuration.ApplicationSettingsBase {
private static CommonConfig defaultInstance = ((CommonConfig)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new CommonConfig())));
@@ -23,15 +23,6 @@ namespace ServerManagerTool.Common {
}
}
- [global::System.Configuration.ApplicationScopedSettingAttribute()]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("http://whatismyip.akamai.com/")]
- public string PublicIPCheckUrl {
- get {
- return ((string)(this["PublicIPCheckUrl"]));
- }
- }
-
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("SteamCMD")]
@@ -160,5 +151,23 @@ namespace ServerManagerTool.Common {
this["SteamCmdRemoveQuit"] = value;
}
}
+
+ [global::System.Configuration.ApplicationScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("https://api.ipify.org")]
+ public string PublicIPCheckUrl1 {
+ get {
+ return ((string)(this["PublicIPCheckUrl1"]));
+ }
+ }
+
+ [global::System.Configuration.ApplicationScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("http://whatismyip.akamai.com/")]
+ public string PublicIPCheckUrl2 {
+ get {
+ return ((string)(this["PublicIPCheckUrl2"]));
+ }
+ }
}
}
diff --git a/src/ServerManager.Common/CommonConfig.settings b/src/ServerManager.Common/CommonConfig.settings
index 74eaade6..290ed90c 100644
--- a/src/ServerManager.Common/CommonConfig.settings
+++ b/src/ServerManager.Common/CommonConfig.settings
@@ -2,9 +2,6 @@
-
- http://whatismyip.akamai.com/
-
SteamCMD
@@ -44,5 +41,11 @@
False
+
+ https://api.ipify.org
+
+
+ http://whatismyip.akamai.com/
+
\ No newline at end of file
diff --git a/src/ServerManager.Common/Extensions/IEnumerableExtensions.cs b/src/ServerManager.Common/Extensions/IEnumerableExtensions.cs
new file mode 100644
index 00000000..1c7814cd
--- /dev/null
+++ b/src/ServerManager.Common/Extensions/IEnumerableExtensions.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+
+namespace ServerManagerTool.Common.Extensions
+{
+ public static class IEnumerableExtensions
+ {
+ public static bool IsEmpty(this IEnumerable source)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException(nameof(source));
+ }
+
+ using (IEnumerator enumerator = source.GetEnumerator())
+ {
+ if (enumerator.MoveNext())
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static bool HasOne(this IEnumerable source)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException(nameof(source));
+ }
+
+ var count = 0;
+
+ using (IEnumerator enumerator = source.GetEnumerator())
+ {
+ while (enumerator.MoveNext())
+ {
+ if (++count > 1)
+ return false;
+ }
+ }
+
+ return count == 1;
+ }
+ }
+}
diff --git a/src/ServerManager.Common/Interfaces/IIniSectionCollection.cs b/src/ServerManager.Common/Interfaces/IIniSectionCollection.cs
index 332d72de..7ae69f60 100644
--- a/src/ServerManager.Common/Interfaces/IIniSectionCollection.cs
+++ b/src/ServerManager.Common/Interfaces/IIniSectionCollection.cs
@@ -1,10 +1,12 @@
-namespace ServerManagerTool.Common.Interfaces
+using System.Collections.Generic;
+
+namespace ServerManagerTool.Common.Interfaces
{
public interface IIniSectionCollection
{
IIniValuesCollection[] Sections { get; }
- void Add(string sectionName, string[] values);
+ void Add(string sectionName, IEnumerable values);
void Update();
}
diff --git a/src/ServerManager.Common/Lib/SteamCmdUpdater.cs b/src/ServerManager.Common/Lib/SteamCmdUpdater.cs
index 47bd926c..4a8936aa 100644
--- a/src/ServerManager.Common/Lib/SteamCmdUpdater.cs
+++ b/src/ServerManager.Common/Lib/SteamCmdUpdater.cs
@@ -23,15 +23,10 @@ namespace ServerManagerTool.Common.Lib
this.StatusKey = statusKey;
this.CompletionPercent = completionPercent;
this.Cancelled = false;
+ this.Failure = null;
this.FailureText = null;
}
- public Update SetFailed(string failureText)
- {
- this.FailureText = failureText;
- return this;
- }
-
public static Update AsCompleted(string statusKey)
{
return new Update { StatusKey = statusKey, CompletionPercent = 100, Cancelled = false };
@@ -42,9 +37,17 @@ namespace ServerManagerTool.Common.Lib
return new Update { StatusKey = statusKey, CompletionPercent = 100, Cancelled = true };
}
+ public Update SetFailed(Exception ex)
+ {
+ this.Failure = ex;
+ this.FailureText = ex.Message;
+ return this;
+ }
+
public string StatusKey;
public float CompletionPercent;
public bool Cancelled;
+ public Exception Failure;
public string FailureText;
}
@@ -56,10 +59,11 @@ namespace ServerManagerTool.Common.Lib
RunningSteamCmd,
InstallSteamCmdComplete,
Complete,
- Cancelled
+ Cancelled,
+ Failed,
}
- Dictionary statuses = new Dictionary()
+ readonly Dictionary statuses = new Dictionary()
{
{ Status.CleaningSteamCmd, new Update("AutoUpdater_Status_CleaningSteamCmd", 0) },
{ Status.DownloadingSteamCmd, new Update("AutoUpdater_Status_DownloadingSteamCmd", 10) },
@@ -67,7 +71,8 @@ namespace ServerManagerTool.Common.Lib
{ Status.RunningSteamCmd, new Update("AutoUpdater_Status_RunningSteamCmd", 50) },
{ Status.InstallSteamCmdComplete, new Update("AutoUpdater_Status_InstallSteamCmdComplete", 80) },
{ Status.Complete, Update.AsCompleted("AutoUpdater_Status_Complete") },
- { Status.Cancelled, Update.AsCancelled("AutoUpdater_Status_Cancelled") }
+ { Status.Cancelled, Update.AsCancelled("AutoUpdater_Status_Cancelled") },
+ { Status.Failed, Update.AsCancelled("AutoUpdater_Status_Failed") },
};
public static string GetSteamCmdFile(string dataPath) => IOUtils.NormalizePath(Path.Combine(dataPath, CommonConfig.Default.SteamCmdRelativePath, CommonConfig.Default.SteamCmdExeFile));
@@ -99,7 +104,7 @@ namespace ServerManagerTool.Common.Lib
}
catch (Exception ex)
{
- reporter?.Report(statuses[Status.Complete].SetFailed(ex.ToString()));
+ reporter?.Report(statuses[Status.Failed].SetFailed(ex));
}
}
@@ -189,7 +194,7 @@ namespace ServerManagerTool.Common.Lib
}
catch(Exception ex)
{
- reporter?.Report(statuses[Status.Complete].SetFailed(ex.ToString()));
+ reporter?.Report(statuses[Status.Failed].SetFailed(ex));
}
}
}
diff --git a/src/ServerManager.Common/Lib/UserScopedSettingContractResolver.cs b/src/ServerManager.Common/Lib/UserScopedSettingContractResolver.cs
index 94855d0f..4ed0a4ea 100644
--- a/src/ServerManager.Common/Lib/UserScopedSettingContractResolver.cs
+++ b/src/ServerManager.Common/Lib/UserScopedSettingContractResolver.cs
@@ -13,7 +13,7 @@ namespace ServerManagerTool.Common.Lib
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
- var customAttributes = member.CustomAttributes?.ToArray() ?? new CustomAttributeData[0];
+ var customAttributes = member.CustomAttributes ?? new CustomAttributeData[0];
if (customAttributes.Any(a => a.AttributeType == typeof(System.Configuration.UserScopedSettingAttribute)))
{
property.ShouldSerialize = instance => { return property.PropertyType.IsValueType || property.PropertyType == typeof(string); };
diff --git a/src/ServerManager.Common/Model/AggregateIniValue.cs b/src/ServerManager.Common/Model/AggregateIniValue.cs
index 291a7faa..7edb9020 100644
--- a/src/ServerManager.Common/Model/AggregateIniValue.cs
+++ b/src/ServerManager.Common/Model/AggregateIniValue.cs
@@ -171,16 +171,15 @@ namespace ServerManagerTool.Common.Model
kvPropertyValue = kvPropertyValue.Substring(0, kvPropertyValue.Length - 1);
}
- var collection = property.GetValue(this) as IIniValuesCollection;
- if (collection != null)
+ if (property.GetValue(this) is IIniValuesCollection collection)
{
- var values = SplitCollectionValues(kvPropertyValue, DELIMITER);
- values = values.Where(v => !string.IsNullOrWhiteSpace(v)).ToArray();
+ var values = SplitCollectionValues(kvPropertyValue, DELIMITER)
+ .Where(v => !string.IsNullOrWhiteSpace(v));
if (attr?.ListValueWithinBrackets ?? false)
{
- values = values.Select(v => v.Substring(1)).ToArray();
- values = values.Select(v => v.Substring(0, v.Length - 1)).ToArray();
+ values = values.Select(v => v.Substring(1));
+ values = values.Select(v => v.Substring(0, v.Length - 1));
}
collection.FromIniValues(values);
}
@@ -267,7 +266,7 @@ namespace ServerManagerTool.Common.Model
return result.ToString();
}
- protected string[] SplitCollectionValues(string valueString, char delimiter)
+ protected IEnumerable SplitCollectionValues(string valueString, char delimiter)
{
if (string.IsNullOrWhiteSpace(valueString))
return new string[0];
@@ -307,7 +306,7 @@ namespace ServerManagerTool.Common.Model
result.Add(tempString.Substring(startIndex));
- return result.ToArray();
+ return result;
}
public void Update(AggregateIniValue other)
diff --git a/src/ServerManager.Common/Model/AggregateIniValueList.cs b/src/ServerManager.Common/Model/AggregateIniValueList.cs
index b62fb4af..87630037 100644
--- a/src/ServerManager.Common/Model/AggregateIniValueList.cs
+++ b/src/ServerManager.Common/Model/AggregateIniValueList.cs
@@ -59,17 +59,16 @@ namespace ServerManagerTool.Common.Model
public virtual void FromIniValues(IEnumerable iniValues)
{
- var items = iniValues?.Select(AggregateIniValue.FromINIValue).ToArray();
+ var items = iniValues?.Select(AggregateIniValue.FromINIValue);
Clear();
AddRange(items);
- IsEnabled = (Count != 0);
+ IsEnabled = (Count > 0);
// Add any default values which were missing
if (_resetFunc != null)
{
- var defaultItemsToAdd = _resetFunc().Where(r => !this.Any(v => v.IsEquivalent(r))).ToArray();
- AddRange(defaultItemsToAdd);
+ AddRange(_resetFunc().Where(r => !this.Any(v => v.IsEquivalent(r))));
}
Sort(AggregateIniValue.SortKeySelector);
diff --git a/src/ServerManager.Common/Model/CustomSectionList.cs b/src/ServerManager.Common/Model/CustomSectionList.cs
index dc46c5b4..fc395447 100644
--- a/src/ServerManager.Common/Model/CustomSectionList.cs
+++ b/src/ServerManager.Common/Model/CustomSectionList.cs
@@ -1,5 +1,6 @@
using ServerManagerTool.Common.Interfaces;
using System;
+using System.Collections.Generic;
using System.Linq;
namespace ServerManagerTool.Common.Model
@@ -14,12 +15,12 @@ namespace ServerManagerTool.Common.Model
}
}
- public void Add(string sectionName, string[] values)
+ public void Add(string sectionName, IEnumerable values)
{
Add(sectionName, values, true);
}
- public void Add(string sectionName, string[] values, bool clearExisting)
+ public void Add(string sectionName, IEnumerable values, bool clearExisting)
{
var section = this.Items.FirstOrDefault(s => s.SectionName.Equals(sectionName, StringComparison.OrdinalIgnoreCase) && !s.IsDeleted);
if (section == null)
diff --git a/src/ServerManager.Common/Model/DiscordBotWhitelist.cs b/src/ServerManager.Common/Model/DiscordBotWhitelist.cs
new file mode 100644
index 00000000..ea456fd9
--- /dev/null
+++ b/src/ServerManager.Common/Model/DiscordBotWhitelist.cs
@@ -0,0 +1,15 @@
+using System.Windows;
+
+namespace ServerManagerTool.Common.Model
+{
+ public class DiscordBotWhitelist : DependencyObject
+ {
+ public static readonly DependencyProperty BotIdProperty = DependencyProperty.Register(nameof(BotId), typeof(string), typeof(DiscordBotWhitelist), new PropertyMetadata(""));
+
+ public string BotId
+ {
+ get { return (string)GetValue(BotIdProperty); }
+ set { SetValue(BotIdProperty, value); }
+ }
+ }
+}
diff --git a/src/ServerManager.Common/Model/IniValueList.cs b/src/ServerManager.Common/Model/IniValueList.cs
index 22febae9..71540c3c 100644
--- a/src/ServerManager.Common/Model/IniValueList.cs
+++ b/src/ServerManager.Common/Model/IniValueList.cs
@@ -98,8 +98,7 @@ namespace ServerManagerTool.Common.Model
// Add any default values which were missing
if (this.ResetFunc != null)
{
- var defaultItemsToAdd = this.ResetFunc().Where(r => !this.Any(v => this.EquivalencyFunc(v, r))).ToArray();
- this.AddRange(defaultItemsToAdd);
+ this.AddRange(this.ResetFunc().Where(r => !this.Any(v => this.EquivalencyFunc(v, r))));
this.Sort(this.SortKeySelectorFunc);
}
}
diff --git a/src/ServerManager.Common/Model/PlayerUserList.cs b/src/ServerManager.Common/Model/PlayerUserList.cs
index 44e6a076..fadb48b6 100644
--- a/src/ServerManager.Common/Model/PlayerUserList.cs
+++ b/src/ServerManager.Common/Model/PlayerUserList.cs
@@ -1,4 +1,5 @@
-using System.Collections.ObjectModel;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.Serialization;
@@ -22,7 +23,7 @@ namespace ServerManagerTool.Common.Model
}
}
- public static PlayerUserList GetList(SteamUserDetailResponse response, string[] ids)
+ public static PlayerUserList GetList(SteamUserDetailResponse response, IEnumerable ids)
{
var result = new PlayerUserList();
if (ids != null)
@@ -68,16 +69,15 @@ namespace ServerManagerTool.Common.Model
public void Remove(string steamId)
{
- var items = this.Where(i => i.PlayerId.Equals(steamId, System.StringComparison.OrdinalIgnoreCase)).ToArray();
- foreach (var item in items)
+ foreach (var item in this.Where(i => i.PlayerId.Equals(steamId, System.StringComparison.OrdinalIgnoreCase)))
{
this.Remove(item);
}
}
- public string[] ToArray()
+ public IEnumerable ToEnumerable()
{
- return this.Select(i => i.PlayerId).ToArray();
+ return this.Select(i => i.PlayerId);
}
public string ToDelimitedString(string delimiter)
diff --git a/src/ServerManager.Common/Model/SteamCmdManifestDetailsResult.cs b/src/ServerManager.Common/Model/SteamCmdManifestDetailsResult.cs
index f6549537..bcc02796 100644
--- a/src/ServerManager.Common/Model/SteamCmdManifestDetailsResult.cs
+++ b/src/ServerManager.Common/Model/SteamCmdManifestDetailsResult.cs
@@ -18,7 +18,7 @@ namespace ServerManagerTool.Common.Model
var tableValue = value as VdfTable;
if (tableValue != null && tableValue.Count > 0)
{
- var betaKeyItems = tableValue.Where(v => v.Name.Equals("betakey", StringComparison.OrdinalIgnoreCase)).ToArray();
+ var betaKeyItems = tableValue.Where(v => v.Name.Equals("betakey", StringComparison.OrdinalIgnoreCase));
foreach (var item in betaKeyItems)
{
tableValue.Remove(item);
diff --git a/src/ServerManager.Common/Serialization/BaseSystemIniFile.cs b/src/ServerManager.Common/Serialization/BaseSystemIniFile.cs
index 7956d173..b4d89f88 100644
--- a/src/ServerManager.Common/Serialization/BaseSystemIniFile.cs
+++ b/src/ServerManager.Common/Serialization/BaseSystemIniFile.cs
@@ -32,29 +32,38 @@ namespace ServerManagerTool.Common.Serialization
get;
}
- public void Deserialize(object obj, Enum[] exclusions)
+ public void Deserialize(object obj, IEnumerable exclusions)
{
var iniFiles = new Dictionary();
- var fields = obj.GetType().GetProperties().Where(f => f.IsDefined(typeof(BaseIniFileEntryAttribute), false));
+ var fields = obj.GetType()
+ .GetProperties()
+ .Where(f => f.IsDefined(typeof(BaseIniFileEntryAttribute), false));
if (exclusions == null)
+ {
exclusions = new Enum[0];
+ }
foreach (var field in fields)
{
- var attributes = field.GetCustomAttributes(typeof(BaseIniFileEntryAttribute), false);
- foreach (var attr in attributes.OfType())
+ var attributes = field
+ .GetCustomAttributes(typeof(BaseIniFileEntryAttribute), false)
+ .OfType()
+ .Where(a => !exclusions.Contains(a.Category));
+
+ foreach (var attr in attributes)
{
if (exclusions.Contains(attr.Category))
+ {
continue;
+ }
try
{
if (attr.IsCustom)
{
// this code is to handle custom sections
- var collection = field.GetValue(obj) as IIniSectionCollection;
- if (collection != null)
+ if (field.GetValue(obj) is IIniSectionCollection collection)
{
ReadFile(iniFiles, attr.File);
@@ -77,61 +86,76 @@ namespace ServerManagerTool.Common.Serialization
}
else
{
- var iniValue = ReadValue(iniFiles, attr.File, attr.Section, keyName);
- var fieldType = field.PropertyType;
- var collection = field.GetValue(obj) as IIniValuesCollection;
-
- if (collection != null)
+ if (field.GetValue(obj) is IIniValuesCollection collection)
{
var section = ReadSection(iniFiles, attr.File, attr.Section);
- var filteredSection = collection.IsArray
- ? section.Where(s => s.StartsWith(collection.IniCollectionKey + "["))
+ var filteredSection = collection.IsArray
+ ? section.Where(s => s.StartsWith(collection.IniCollectionKey + "["))
: section.Where(s => s.StartsWith(collection.IniCollectionKey + "="));
collection.FromIniValues(filteredSection);
}
- else if (fieldType == typeof(string))
- {
- var stringValue = iniValue;
- if (attr.QuotedString == QuotedStringType.True)
- {
- // remove the leading and trailing quotes, if any
- if (stringValue.StartsWith("\""))
- stringValue = stringValue.Substring(1);
- if (stringValue.EndsWith("\""))
- stringValue = stringValue.Substring(0, stringValue.Length - 1);
- }
- else if (attr.QuotedString == QuotedStringType.Remove)
- {
- // remove the leading and trailing quotes, if any
- if (stringValue.StartsWith("\""))
- stringValue = stringValue.Substring(1);
- if (stringValue.EndsWith("\""))
- stringValue = stringValue.Substring(0, stringValue.Length - 1);
- }
- if (attr.Multiline)
- {
- stringValue = stringValue.Replace(attr.MultilineSeparator, Environment.NewLine);
- }
- field.SetValue(obj, stringValue);
- }
else
{
- if (string.IsNullOrWhiteSpace(iniValue))
+ var iniValue = ReadValue(iniFiles, attr.File, attr.Section, keyName);
+
+ var fieldType = field.PropertyType;
+ if (fieldType == typeof(string))
{
- // Skip non-string values which are not found
- continue;
+ var stringValue = iniValue;
+ if (attr.QuotedString == QuotedStringType.True)
+ {
+ // remove the leading and trailing quotes, if any
+ if (stringValue.StartsWith("\""))
+ {
+ stringValue = stringValue.Substring(1);
+ }
+
+ if (stringValue.EndsWith("\""))
+ {
+ stringValue = stringValue.Substring(0, stringValue.Length - 1);
+ }
+ }
+ else if (attr.QuotedString == QuotedStringType.Remove)
+ {
+ // remove the leading and trailing quotes, if any
+ if (stringValue.StartsWith("\""))
+ {
+ stringValue = stringValue.Substring(1);
+ }
+
+ if (stringValue.EndsWith("\""))
+ {
+ stringValue = stringValue.Substring(0, stringValue.Length - 1);
+ }
+ }
+ if (attr.Multiline)
+ {
+ stringValue = stringValue.Replace(attr.MultilineSeparator, Environment.NewLine);
+ }
+ field.SetValue(obj, stringValue);
+ }
+ else
+ {
+ if (string.IsNullOrWhiteSpace(iniValue))
+ {
+ // Skip non-string values which are not found
+ continue;
+ }
+
+ // Update the ConditionedOn flag, if this field has one.
+ if (!string.IsNullOrWhiteSpace(attr.ConditionedOn))
+ {
+ var conditionField = obj.GetType().GetProperty(attr.ConditionedOn);
+ conditionField.SetValue(obj, true);
+ }
+
+ var valueSet = StringUtils.SetPropertyValue(iniValue, obj, field, attr);
+ if (!valueSet)
+ {
+ throw new ArgumentException($"Unexpected field type {fieldType} for INI key {keyName} in section {attr.Section}.");
+ }
}
- // Update the ConditionedOn flag, if this field has one.
- if (!string.IsNullOrWhiteSpace(attr.ConditionedOn))
- {
- var conditionField = obj.GetType().GetProperty(attr.ConditionedOn);
- conditionField.SetValue(obj, true);
- }
-
- var valueSet = StringUtils.SetPropertyValue(iniValue, obj, field, attr);
- if (!valueSet)
- throw new ArgumentException($"Unexpected field type {fieldType} for INI key {keyName} in section {attr.Section}.");
}
}
}
@@ -144,29 +168,33 @@ namespace ServerManagerTool.Common.Serialization
}
}
- public void Serialize(object obj, Enum[] exclusions)
+ public void Serialize(object obj, IEnumerable exclusions)
{
var iniFiles = new Dictionary();
- var fields = obj.GetType().GetProperties().Where(f => f.IsDefined(typeof(BaseIniFileEntryAttribute), false));
+ var fields = obj.GetType()
+ .GetProperties()
+ .Where(f => f.IsDefined(typeof(BaseIniFileEntryAttribute), false));
if (exclusions == null)
+ {
exclusions = new Enum[0];
+ }
foreach (var field in fields)
{
- var attributes = field.GetCustomAttributes(typeof(BaseIniFileEntryAttribute), false).OfType();
+ var attributes = field
+ .GetCustomAttributes(typeof(BaseIniFileEntryAttribute), false)
+ .OfType()
+ .Where(a => !exclusions.Contains(a.Category));
+
foreach (var attr in attributes)
{
- if (exclusions.Contains(attr.Category))
- continue;
-
try
{
if (attr.IsCustom)
{
// this code is to handle custom sections
- var collection = field.GetValue(obj) as IIniSectionCollection;
- if (collection != null)
+ if (field.GetValue(obj) is IIniSectionCollection collection)
{
collection.Update();
@@ -177,7 +205,7 @@ namespace ServerManagerTool.Common.Serialization
if (section.IsEnabled)
{
- WriteSection(iniFiles, attr.File, section.IniCollectionKey, section.ToIniValues().ToArray());
+ WriteSection(iniFiles, attr.File, section.IniCollectionKey, section.ToIniValues());
}
}
}
@@ -200,8 +228,7 @@ namespace ServerManagerTool.Common.Serialization
{
var section = ReadSection(iniFiles, attr.File, attr.Section);
var filteredSection = section
- .Where(s => !s.StartsWith(collection.IniCollectionKey + (collection.IsArray ? "[" : "=")))
- .ToArray();
+ .Where(s => !s.StartsWith(collection.IniCollectionKey + (collection.IsArray ? "[" : "=")));
WriteSection(iniFiles, attr.File, attr.Section, filteredSection);
}
@@ -286,7 +313,7 @@ namespace ServerManagerTool.Common.Serialization
result = result.Concat(collection.ToIniValues());
}
- WriteSection(iniFiles, attr.File, attr.Section, result?.ToArray());
+ WriteSection(iniFiles, attr.File, attr.Section, result);
}
}
else
@@ -353,74 +380,94 @@ namespace ServerManagerTool.Common.Serialization
SaveFiles(iniFiles);
}
- public string[] ReadSection(Enum iniFile, Enum section)
+ public IEnumerable ReadSection(Enum iniFile, Enum section)
{
return ReadSection(iniFile, SectionNames[section]);
}
- public string[] ReadSection(Enum iniFile, string sectionName)
+ public IEnumerable ReadSection(Enum iniFile, string sectionName)
{
var file = Path.Combine(this.BasePath, FileNames[iniFile]);
return IniFileUtils.ReadSection(file, sectionName);
}
- public void WriteSection(Enum iniFile, Enum section, string[] values)
+ public void WriteSection(Enum iniFile, Enum section, IEnumerable values)
{
WriteSection(iniFile, SectionNames[section], values);
}
- public void WriteSection(Enum iniFile, string sectionName, string[] values)
+ public void WriteSection(Enum iniFile, string sectionName, IEnumerable values)
{
var file = Path.Combine(this.BasePath, FileNames[iniFile]);
- var result = IniFileUtils.WriteSection(file, sectionName, values);
+ IniFileUtils.WriteSection(file, sectionName, values);
}
- private string[] ReadCustomSectionNames(Dictionary iniFiles, Enum iniFile)
+ private IEnumerable ReadCustomSectionNames(Dictionary iniFiles, Enum iniFile)
{
- ReadFile(iniFiles, iniFile);
-
if (!iniFiles.ContainsKey(FileNames[iniFile]))
- return new string[0];
+ {
+ ReadFile(iniFiles, iniFile);
- return iniFiles[FileNames[iniFile]].Sections.Select(s => s.SectionName).Where(s => !SectionNames.ContainsValue(s)).ToArray();
+ if (!iniFiles.ContainsKey(FileNames[iniFile]))
+ {
+ return new string[0];
+ }
+ }
+
+ return iniFiles[FileNames[iniFile]].Sections.Select(s => s.SectionName).Where(s => !SectionNames.ContainsValue(s));
}
- private string[] ReadSection(Dictionary iniFiles, Enum iniFile, Enum section)
+ private IEnumerable ReadSection(Dictionary iniFiles, Enum iniFile, Enum section)
{
return ReadSection(iniFiles, iniFile, SectionNames[section]);
}
- private string[] ReadSection(Dictionary iniFiles, Enum iniFile, string sectionName)
+ private IEnumerable ReadSection(Dictionary iniFiles, Enum iniFile, string sectionName)
{
- ReadFile(iniFiles, iniFile);
-
if (!iniFiles.ContainsKey(FileNames[iniFile]))
- return new string[0];
+ {
+ ReadFile(iniFiles, iniFile);
- return iniFiles[FileNames[iniFile]].GetSection(sectionName)?.KeysToStringArray() ?? new string[0];
+ if (!iniFiles.ContainsKey(FileNames[iniFile]))
+ {
+ return new string[0];
+ }
+ }
+
+ return iniFiles[FileNames[iniFile]].GetSection(sectionName)?.KeysToStringEnumerable() ?? new string[0];
}
private string ReadValue(Dictionary iniFiles, Enum iniFile, Enum section, string keyName)
{
- ReadFile(iniFiles, iniFile);
-
if (!iniFiles.ContainsKey(FileNames[iniFile]))
- return string.Empty;
+ {
+ ReadFile(iniFiles, iniFile);
+
+ if (!iniFiles.ContainsKey(FileNames[iniFile]))
+ {
+ return string.Empty;
+ }
+ }
return iniFiles[FileNames[iniFile]].GetKey(SectionNames[section], keyName)?.KeyValue ?? string.Empty;
}
- private void WriteSection(Dictionary iniFiles, Enum iniFile, Enum section, string[] values)
+ private void WriteSection(Dictionary iniFiles, Enum iniFile, Enum section, IEnumerable values)
{
WriteSection(iniFiles, iniFile, SectionNames[section], values);
}
- private void WriteSection(Dictionary iniFiles, Enum iniFile, string sectionName, string[] values)
+ private void WriteSection(Dictionary iniFiles, Enum iniFile, string sectionName, IEnumerable values)
{
- ReadFile(iniFiles, iniFile);
-
if (!iniFiles.ContainsKey(FileNames[iniFile]))
- return;
+ {
+ ReadFile(iniFiles, iniFile);
+
+ if (!iniFiles.ContainsKey(FileNames[iniFile]))
+ {
+ return;
+ }
+ }
iniFiles[FileNames[iniFile]].WriteSection(sectionName, values);
}
@@ -432,10 +479,15 @@ namespace ServerManagerTool.Common.Serialization
private void WriteValue(Dictionary iniFiles, Enum iniFile, string sectionName, string keyName, string keyValue)
{
- ReadFile(iniFiles, iniFile);
-
if (!iniFiles.ContainsKey(FileNames[iniFile]))
- return;
+ {
+ ReadFile(iniFiles, iniFile);
+
+ if (!iniFiles.ContainsKey(FileNames[iniFile]))
+ {
+ return;
+ }
+ }
iniFiles[FileNames[iniFile]].WriteKey(sectionName, keyName, keyValue);
}
@@ -454,7 +506,7 @@ namespace ServerManagerTool.Common.Serialization
foreach (var iniFile in iniFiles)
{
var file = Path.Combine(this.BasePath, iniFile.Key);
- var result = IniFileUtils.SaveToFile(file, iniFile.Value);
+ IniFileUtils.SaveToFile(file, iniFile.Value);
}
}
}
diff --git a/src/ServerManager.Common/Serialization/IniFile.cs b/src/ServerManager.Common/Serialization/IniFile.cs
index 8d7e856d..15c6fdd1 100644
--- a/src/ServerManager.Common/Serialization/IniFile.cs
+++ b/src/ServerManager.Common/Serialization/IniFile.cs
@@ -68,7 +68,7 @@ namespace ServerManagerTool.Common.Serialization
Sections.Remove(section);
}
- public bool WriteSection(string sectionName, string[] keysValuePairs)
+ public bool WriteSection(string sectionName, IEnumerable keysValuePairs)
{
if (sectionName == null)
return false;
@@ -186,7 +186,7 @@ namespace ServerManagerTool.Common.Serialization
{
result.AppendLine($"[{section.SectionName}]");
- foreach (var keyString in section.KeysToStringArray())
+ foreach (var keyString in section.KeysToStringEnumerable())
{
result.AppendLine(keyString);
}
diff --git a/src/ServerManager.Common/Serialization/IniSection.cs b/src/ServerManager.Common/Serialization/IniSection.cs
index 72c360a2..8a848b01 100644
--- a/src/ServerManager.Common/Serialization/IniSection.cs
+++ b/src/ServerManager.Common/Serialization/IniSection.cs
@@ -41,9 +41,9 @@ namespace ServerManagerTool.Common.Serialization
return Keys?.FirstOrDefault(s => s.KeyName.Equals(keyName, StringComparison.OrdinalIgnoreCase));
}
- public string[] KeysToStringArray()
+ public IEnumerable KeysToStringEnumerable()
{
- return Keys.Select(k => k.ToString()).ToArray();
+ return Keys.Select(k => k.ToString());
}
public void RemoveKey(string keyName)
diff --git a/src/ServerManager.Common/ServerManager.Common.csproj b/src/ServerManager.Common/ServerManager.Common.csproj
index b76aa89e..ad48231c 100644
--- a/src/ServerManager.Common/ServerManager.Common.csproj
+++ b/src/ServerManager.Common/ServerManager.Common.csproj
@@ -43,4 +43,17 @@
+
+
+ True
+ True
+ CommonConfig.settings
+
+
+
+
+ PublicSettingsSingleFileGenerator
+ CommonConfig.Designer.cs
+
+
\ No newline at end of file
diff --git a/src/ServerManager.Common/Utils/IniFileUtils.cs b/src/ServerManager.Common/Utils/IniFileUtils.cs
index ebfacfcd..1cbc29ab 100644
--- a/src/ServerManager.Common/Utils/IniFileUtils.cs
+++ b/src/ServerManager.Common/Utils/IniFileUtils.cs
@@ -1,5 +1,6 @@
using ServerManagerTool.Common.Serialization;
using System;
+using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
@@ -13,13 +14,13 @@ namespace ServerManagerTool.Common.Utils
/// The name of the initialization file.
/// The name of the section in the initialization file.
/// A string array containing the key name and value pairs associated with the named section.
- public static string[] ReadSection(string file, string sectionName)
+ public static IEnumerable ReadSection(string file, string sectionName)
{
if (sectionName == null)
return new string[0];
var iniFile = ReadFromFile(file);
- return iniFile?.GetSection(sectionName)?.KeysToStringArray() ?? new string[0];
+ return iniFile?.GetSection(sectionName)?.KeysToStringEnumerable() ?? new string[0];
}
///
@@ -46,7 +47,7 @@ namespace ServerManagerTool.Common.Utils
/// The name of the section in which data is written.
/// An array of key names and associated values that are to be written to the named section.
/// True if the function succeeds; otherwise False.
- public static bool WriteSection(string file, string sectionName, string[] keysValuePairs)
+ public static bool WriteSection(string file, string sectionName, IEnumerable keysValuePairs)
{
if (sectionName == null)
return false;
@@ -85,10 +86,14 @@ namespace ServerManagerTool.Common.Utils
public static IniFile ReadFromFile(string file)
{
if (string.IsNullOrWhiteSpace(file))
+ {
return null;
+ }
if (!File.Exists(file))
+ {
return new IniFile();
+ }
var iniFile = new IniFile();
@@ -96,18 +101,24 @@ namespace ServerManagerTool.Common.Utils
{
while (!reader.EndOfStream)
{
- var line = reader.ReadLine();
+ var line = reader.ReadLine().Trim();
if (string.IsNullOrWhiteSpace(line) || line.StartsWith(";") || line.StartsWith("#"))
+ {
continue;
+ }
- var sectionName = Regex.Match(line, @"(?<=^\[).*(?=\]$)").Value.Trim();
+ var sectionName = string.Empty;
+ if (line.StartsWith("[") && line.EndsWith("]"))
+ {
+ sectionName = Regex.Match(line, @"(?<=^\[).*(?=\]$)").Value.Trim();
+ }
var section = iniFile.AddSection(sectionName);
- if (section != null)
- continue;
-
- iniFile.AddKey(line);
+ if (section is null)
+ {
+ iniFile.AddKey(line);
+ }
}
reader.Close();
@@ -155,7 +166,7 @@ namespace ServerManagerTool.Common.Utils
{
writer.WriteLine($"[{section.SectionName}]");
- foreach (var keyString in section.KeysToStringArray())
+ foreach (var keyString in section.KeysToStringEnumerable())
{
writer.WriteLine(keyString);
}
diff --git a/src/ServerManager.Common/Utils/NetworkUtils.cs b/src/ServerManager.Common/Utils/NetworkUtils.cs
index 390a9329..a0e255bb 100644
--- a/src/ServerManager.Common/Utils/NetworkUtils.cs
+++ b/src/ServerManager.Common/Utils/NetworkUtils.cs
@@ -81,8 +81,14 @@ namespace ServerManagerTool.Common.Utils
{
try
{
- var publicIP = webClient.DownloadString(CommonConfig.Default.PublicIPCheckUrl);
- if (IPAddress.TryParse(publicIP, out IPAddress address))
+ var publicIP = webClient.DownloadString(CommonConfig.Default.PublicIPCheckUrl1);
+ if (IPAddress.TryParse(publicIP, out IPAddress address1))
+ {
+ return publicIP;
+ }
+
+ publicIP = webClient.DownloadString(CommonConfig.Default.PublicIPCheckUrl2);
+ if (IPAddress.TryParse(publicIP, out IPAddress address2))
{
return publicIP;
}
@@ -102,8 +108,14 @@ namespace ServerManagerTool.Common.Utils
{
try
{
- var publicIP = await webClient.DownloadStringTaskAsync(CommonConfig.Default.PublicIPCheckUrl);
- if (IPAddress.TryParse(publicIP, out IPAddress address))
+ var publicIP = await webClient.DownloadStringTaskAsync(CommonConfig.Default.PublicIPCheckUrl1);
+ if (IPAddress.TryParse(publicIP, out IPAddress address1))
+ {
+ return publicIP;
+ }
+
+ publicIP = await webClient.DownloadStringTaskAsync(CommonConfig.Default.PublicIPCheckUrl2);
+ if (IPAddress.TryParse(publicIP, out IPAddress address2))
{
return publicIP;
}
diff --git a/src/ServerManager.Common/Utils/ProcessUtils.cs b/src/ServerManager.Common/Utils/ProcessUtils.cs
index 42009d28..4e5fbad9 100644
--- a/src/ServerManager.Common/Utils/ProcessUtils.cs
+++ b/src/ServerManager.Common/Utils/ProcessUtils.cs
@@ -285,7 +285,7 @@ namespace ServerManagerTool.Common.Utils
}
}
- public static BigInteger[] GetProcessorAffinityList()
+ public static IEnumerable GetProcessorAffinityList()
{
var processorCount = ProcessorCount;
var results = new List(processorCount + 1);
@@ -295,7 +295,7 @@ namespace ServerManagerTool.Common.Utils
{
results.Add((BigInteger)Math.Pow(2, index));
}
- return results.ToArray();
+ return results;
}
public static string[] GetProcessPriorityList()
diff --git a/src/ServerManager.Common/Utils/SettingsUtils.cs b/src/ServerManager.Common/Utils/SettingsUtils.cs
index e5f4f63d..6e727f9f 100644
--- a/src/ServerManager.Common/Utils/SettingsUtils.cs
+++ b/src/ServerManager.Common/Utils/SettingsUtils.cs
@@ -49,7 +49,7 @@ namespace ServerManagerTool.Common.Utils
try
{
- var filesToDelete = new DirectoryInfo(backupPath).GetFiles($"{settingsFileName}_*{settingsFileExt}").Where(f => f.LastWriteTimeUtc.AddDays(7) < DateTime.UtcNow).ToArray();
+ var filesToDelete = new DirectoryInfo(backupPath).GetFiles($"{settingsFileName}_*{settingsFileExt}").Where(f => f.LastWriteTimeUtc.AddDays(7) < DateTime.UtcNow);
foreach (var fileToDelete in filesToDelete)
{
try
diff --git a/src/ServerManager.Common/Utils/TaskSchedulerUtils.cs b/src/ServerManager.Common/Utils/TaskSchedulerUtils.cs
index 5b961c1d..9114452c 100644
--- a/src/ServerManager.Common/Utils/TaskSchedulerUtils.cs
+++ b/src/ServerManager.Common/Utils/TaskSchedulerUtils.cs
@@ -1,5 +1,6 @@
using Microsoft.Win32.TaskScheduler;
using NLog;
+using ServerManagerTool.Common.Extensions;
using System;
using System.Diagnostics;
using System.Linq;
@@ -202,7 +203,7 @@ namespace ServerManagerTool.Common.Utils
// Add/Edit the trigger that will fire every x minutes
var triggers = taskDefinition.Triggers.OfType();
- if (triggers.Count() == 0)
+ if (triggers.IsEmpty())
{
var trigger = new TimeTrigger
{
@@ -445,7 +446,7 @@ namespace ServerManagerTool.Common.Utils
if (onBoot)
{
var triggers = taskDefinition.Triggers.OfType();
- if (triggers.Count() == 0)
+ if (triggers.IsEmpty())
{
var trigger = new BootTrigger
{
@@ -465,7 +466,7 @@ namespace ServerManagerTool.Common.Utils
else
{
var triggers = taskDefinition.Triggers.OfType();
- if (triggers.Count() == 0)
+ if (triggers.IsEmpty())
{
var trigger = new LogonTrigger
{
@@ -572,7 +573,7 @@ namespace ServerManagerTool.Common.Utils
// Add/Edit the trigger that will fire every x minutes
var triggers = taskDefinition.Triggers.OfType();
- if (triggers.Count() == 0)
+ if (triggers.IsEmpty())
{
var trigger = new TimeTrigger
{
diff --git a/src/ServerManager.Common/Utils/ZipUtils.cs b/src/ServerManager.Common/Utils/ZipUtils.cs
index f246bae6..df1acf3b 100644
--- a/src/ServerManager.Common/Utils/ZipUtils.cs
+++ b/src/ServerManager.Common/Utils/ZipUtils.cs
@@ -1,5 +1,7 @@
using Ionic.Zip;
+using ServerManagerTool.Common.Extensions;
using System;
+using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -68,11 +70,12 @@ namespace ServerManagerTool.Common.Utils
}
}
- public static void UpdateFiles(string zipFile, string[] filesToZip, string comment = "", bool preserveDirHierarchy = true, string directoryPathInArchive = "")
+ public static void UpdateFiles(string zipFile, IEnumerable filesToZip, string comment = "", bool preserveDirHierarchy = true, string directoryPathInArchive = "")
{
if (string.IsNullOrWhiteSpace(zipFile))
throw new ArgumentNullException(nameof(zipFile));
- if (filesToZip == null || filesToZip.Length == 0)
+
+ if (filesToZip is null || filesToZip.IsEmpty())
return;
if (!File.Exists(zipFile))
@@ -160,11 +163,12 @@ namespace ServerManagerTool.Common.Utils
}
}
- public static void ZipFiles(string zipFile, string[] filesToZip, string comment = "", bool preserveDirHierarchy = true, string directoryPathInArchive = "")
+ public static void ZipFiles(string zipFile, IEnumerable filesToZip, string comment = "", bool preserveDirHierarchy = true, string directoryPathInArchive = "")
{
if (string.IsNullOrWhiteSpace(zipFile))
throw new ArgumentNullException(nameof(zipFile));
- if (filesToZip == null || filesToZip.Length == 0)
+
+ if (filesToZip is null || filesToZip.IsEmpty())
throw new ArgumentNullException(nameof(filesToZip));
using (var zip = new ZipFile(zipFile))
diff --git a/src/ServerManager.Common/app.config b/src/ServerManager.Common/app.config
index 9f599428..2160090b 100644
--- a/src/ServerManager.Common/app.config
+++ b/src/ServerManager.Common/app.config
@@ -10,9 +10,6 @@
-
- http://whatismyip.akamai.com/
-
SteamCMD
@@ -29,7 +26,7 @@
+login anonymous +quit
-
+
https://steamcommunity.com/dev/apikey
@@ -40,15 +37,21 @@
Steam
+
+ https://api.ipify.org
+
+
+ http://whatismyip.akamai.com/
+
-
+
-
+
True
diff --git a/src/ServerManager.Discord/Delegates/HandleCommandDelegate.cs b/src/ServerManager.Discord/Delegates/HandleCommandDelegate.cs
index e4301ce4..ef626b53 100644
--- a/src/ServerManager.Discord/Delegates/HandleCommandDelegate.cs
+++ b/src/ServerManager.Discord/Delegates/HandleCommandDelegate.cs
@@ -4,5 +4,5 @@ using System.Threading;
namespace ServerManagerTool.DiscordBot.Delegates
{
- public delegate IList HandleCommandDelegate(CommandType commandType, string serverId, string channelId, string profileId, CancellationToken token);
+ public delegate IList HandleCommandDelegate(CommandType commandType, string serverId, string channelId, string profileIdOrAlias, CancellationToken token);
}
diff --git a/src/ServerManager.Discord/DiscordBot.cs b/src/ServerManager.Discord/DiscordBot.cs
deleted file mode 100644
index 63cc1c7a..00000000
--- a/src/ServerManager.Discord/DiscordBot.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using ServerManagerTool.DiscordBot.Delegates;
-
-namespace ServerManagerTool.DiscordBot
-{
- public static class DiscordBot
- {
- public const string PREFIX_DELIMITER = "!";
- }
-}
diff --git a/src/ServerManager.Discord/Enums/BotStatus.cs b/src/ServerManager.Discord/Enums/BotStatus.cs
new file mode 100644
index 00000000..3ae2f730
--- /dev/null
+++ b/src/ServerManager.Discord/Enums/BotStatus.cs
@@ -0,0 +1,10 @@
+namespace ServerManagerTool.DiscordBot.Enums
+{
+ public enum BotState
+ {
+ Unknown,
+ Disabled,
+ Stopped,
+ Running,
+ }
+}
diff --git a/src/ServerManager.Discord/Enums/LogLevel.cs b/src/ServerManager.Discord/Enums/LogLevel.cs
new file mode 100644
index 00000000..8c18aeae
--- /dev/null
+++ b/src/ServerManager.Discord/Enums/LogLevel.cs
@@ -0,0 +1,25 @@
+using Discord;
+using System;
+
+namespace ServerManagerTool.DiscordBot.Enums
+{
+ public enum LogLevel
+ {
+ Critical = 0,
+ Error = 1,
+ Warning = 2,
+ Info = 3,
+ Verbose = 4,
+ Debug = 5
+ }
+
+ public class LogLevelHelper
+ {
+ public static LogSeverity GetLogSeverity(LogLevel logLevel)
+ {
+ if (Enum.TryParse(logLevel.ToString(), out LogSeverity logSeverity))
+ return logSeverity;
+ return LogSeverity.Info;
+ }
+ }
+}
diff --git a/src/ServerManager.Discord/Interfaces/IServerManagerBot.cs b/src/ServerManager.Discord/Interfaces/IServerManagerBot.cs
index f44c1878..a4ef8f1e 100644
--- a/src/ServerManager.Discord/Interfaces/IServerManagerBot.cs
+++ b/src/ServerManager.Discord/Interfaces/IServerManagerBot.cs
@@ -1,4 +1,6 @@
using ServerManagerTool.DiscordBot.Delegates;
+using ServerManagerTool.DiscordBot.Enums;
+using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
@@ -8,6 +10,6 @@ namespace ServerManagerTool.DiscordBot.Interfaces
{
CancellationToken Token { get; }
- Task StartAsync(string discordToken, string commandPrefix, string dataDirectory, HandleCommandDelegate handleCommandCallback, HandleTranslationDelegate handleTranslationCallback, CancellationToken token);
+ Task StartAsync(LogLevel logLevel, string discordToken, string commandPrefix, string dataDirectory, bool allowAllBots, IEnumerable botWhitelist, HandleCommandDelegate handleCommandCallback, HandleTranslationDelegate handleTranslationCallback, CancellationToken token);
}
}
diff --git a/src/ServerManager.Discord/Models/DiscordBotConfig.cs b/src/ServerManager.Discord/Models/DiscordBotConfig.cs
new file mode 100644
index 00000000..c6a0ca59
--- /dev/null
+++ b/src/ServerManager.Discord/Models/DiscordBotConfig.cs
@@ -0,0 +1,11 @@
+using System.Collections.Generic;
+
+namespace ServerManagerTool.DiscordBot.Models
+{
+ public class DiscordBotConfig
+ {
+ public bool AllowAllBots { get; set; } = false;
+
+ public List DiscordBotWhitelists { get; set; } = new List();
+ }
+}
diff --git a/src/ServerManager.Discord/Models/DiscordBotWhitelist.cs b/src/ServerManager.Discord/Models/DiscordBotWhitelist.cs
new file mode 100644
index 00000000..4fb932b6
--- /dev/null
+++ b/src/ServerManager.Discord/Models/DiscordBotWhitelist.cs
@@ -0,0 +1,7 @@
+namespace ServerManagerTool.DiscordBot.Models
+{
+ public class DiscordBotWhitelist
+ {
+ public string BotId { get; set; } = string.Empty;
+ }
+}
diff --git a/src/ServerManager.Discord/Modules/ServerCommandModule.cs b/src/ServerManager.Discord/Modules/ServerCommandModule.cs
index ea993166..b2bd5461 100644
--- a/src/ServerManager.Discord/Modules/ServerCommandModule.cs
+++ b/src/ServerManager.Discord/Modules/ServerCommandModule.cs
@@ -29,16 +29,16 @@ namespace ServerManagerTool.DiscordBot.Modules
[Command("backup", RunMode = RunMode.Async)]
[Summary("Backup the server")]
- [Remarks("backup profileId")]
+ [Remarks("backup profileId|alias")]
[RequireBotPermission(ChannelPermission.ViewChannel | ChannelPermission.SendMessages)]
- public async Task BackupServerAsync(string profileId)
+ public async Task BackupServerAsync(string profileIdOrAlias)
{
try
{
var serverId = Context?.Guild?.Id.ToString() ?? string.Empty;
var channelId = Context?.Channel?.Id.ToString() ?? string.Empty;
- var response = _handleCommandCallback?.Invoke(CommandType.Backup, serverId, channelId, profileId, _serverManagerBot.Token);
+ var response = _handleCommandCallback?.Invoke(CommandType.Backup, serverId, channelId, profileIdOrAlias, _serverManagerBot.Token);
if (response is null)
{
await ReplyAsync("No servers associated with this channel.");
@@ -60,16 +60,16 @@ namespace ServerManagerTool.DiscordBot.Modules
[Command("restart", RunMode = RunMode.Async)]
[Summary("Restart the server")]
- [Remarks("restart profileId")]
+ [Remarks("restart profileId|alias")]
[RequireBotPermission(ChannelPermission.ViewChannel | ChannelPermission.SendMessages)]
- public async Task RestartServerAsync(string profileId)
+ public async Task RestartServerAsync(string profileIdOrAlias)
{
try
{
var serverId = Context?.Guild?.Id.ToString() ?? string.Empty;
var channelId = Context?.Channel?.Id.ToString() ?? string.Empty;
- var response = _handleCommandCallback?.Invoke(CommandType.Restart, serverId, channelId, profileId, _serverManagerBot.Token);
+ var response = _handleCommandCallback?.Invoke(CommandType.Restart, serverId, channelId, profileIdOrAlias, _serverManagerBot.Token);
if (response is null)
{
await ReplyAsync("No servers associated with this channel.");
@@ -91,16 +91,16 @@ namespace ServerManagerTool.DiscordBot.Modules
[Command("shutdown", RunMode = RunMode.Async)]
[Summary("Shuts down the server properly")]
- [Remarks("shutdown profileId")]
+ [Remarks("shutdown profileId|alias")]
[RequireBotPermission(ChannelPermission.ViewChannel | ChannelPermission.SendMessages)]
- public async Task ShutdownServerAsync(string profileId)
+ public async Task ShutdownServerAsync(string profileIdOrAlias)
{
try
{
var serverId = Context?.Guild?.Id.ToString() ?? string.Empty;
var channelId = Context?.Channel?.Id.ToString() ?? string.Empty;
- var response = _handleCommandCallback?.Invoke(CommandType.Shutdown, serverId, channelId, profileId, _serverManagerBot.Token);
+ var response = _handleCommandCallback?.Invoke(CommandType.Shutdown, serverId, channelId, profileIdOrAlias, _serverManagerBot.Token);
if (response is null)
{
await ReplyAsync("No servers associated with this channel.");
@@ -122,16 +122,16 @@ namespace ServerManagerTool.DiscordBot.Modules
[Command("start", RunMode = RunMode.Async)]
[Summary("Starts the server")]
- [Remarks("start profileId")]
+ [Remarks("start profileId|alias")]
[RequireBotPermission(ChannelPermission.ViewChannel | ChannelPermission.SendMessages)]
- public async Task StartServerAsync(string profileId)
+ public async Task StartServerAsync(string profileIdOrAlias)
{
try
{
var serverId = Context?.Guild?.Id.ToString() ?? string.Empty;
var channelId = Context?.Channel?.Id.ToString() ?? string.Empty;
- var response = _handleCommandCallback?.Invoke(CommandType.Start, serverId, channelId, profileId, _serverManagerBot.Token);
+ var response = _handleCommandCallback?.Invoke(CommandType.Start, serverId, channelId, profileIdOrAlias, _serverManagerBot.Token);
if (response is null)
{
await ReplyAsync("No servers associated with this channel.");
@@ -153,16 +153,16 @@ namespace ServerManagerTool.DiscordBot.Modules
[Command("stop", RunMode = RunMode.Async)]
[Summary("Forcibly stops the server")]
- [Remarks("stop profileId")]
+ [Remarks("stop profileId|alias")]
[RequireBotPermission(ChannelPermission.ViewChannel | ChannelPermission.SendMessages)]
- public async Task StopServerAsync(string profileId)
+ public async Task StopServerAsync(string profileIdOrAlias)
{
try
{
var serverId = Context?.Guild?.Id.ToString() ?? string.Empty;
var channelId = Context?.Channel?.Id.ToString() ?? string.Empty;
- var response = _handleCommandCallback?.Invoke(CommandType.Stop, serverId, channelId, profileId, _serverManagerBot.Token);
+ var response = _handleCommandCallback?.Invoke(CommandType.Stop, serverId, channelId, profileIdOrAlias, _serverManagerBot.Token);
if (response is null)
{
await ReplyAsync("No servers associated with this channel.");
@@ -184,16 +184,16 @@ namespace ServerManagerTool.DiscordBot.Modules
[Command("update", RunMode = RunMode.Async)]
[Summary("Updates the server")]
- [Remarks("update profileId")]
+ [Remarks("update profileId|alias")]
[RequireBotPermission(ChannelPermission.ViewChannel | ChannelPermission.SendMessages)]
- public async Task UpdateServerAsync(string profileId)
+ public async Task UpdateServerAsync(string profileIdOrAlias)
{
try
{
var serverId = Context?.Guild?.Id.ToString() ?? string.Empty;
var channelId = Context?.Channel?.Id.ToString() ?? string.Empty;
- var response = _handleCommandCallback?.Invoke(CommandType.Update, serverId, channelId, profileId, _serverManagerBot.Token);
+ var response = _handleCommandCallback?.Invoke(CommandType.Update, serverId, channelId, profileIdOrAlias, _serverManagerBot.Token);
if (response is null)
{
await ReplyAsync("No servers associated with this channel.");
diff --git a/src/ServerManager.Discord/Modules/ServerQueryModule.cs b/src/ServerManager.Discord/Modules/ServerQueryModule.cs
index a793c3b7..407486c3 100644
--- a/src/ServerManager.Discord/Modules/ServerQueryModule.cs
+++ b/src/ServerManager.Discord/Modules/ServerQueryModule.cs
@@ -38,16 +38,16 @@ namespace ServerManagerTool.DiscordBot.Modules
[Command("info", RunMode = RunMode.Async)]
[Summary("Poll server for information")]
- [Remarks("info profileId")]
+ [Remarks("info profileId|alias")]
[RequireBotPermission(ChannelPermission.ViewChannel | ChannelPermission.SendMessages)]
- public async Task ServerInfoAsync(string profileId)
+ public async Task ServerInfoAsync(string profileIdOrAlias)
{
try
{
var serverId = Context?.Guild?.Id.ToString() ?? string.Empty;
var channelId = Context?.Channel?.Id.ToString() ?? string.Empty;
- var response = _handleCommandCallback?.Invoke(CommandType.Info, serverId, channelId, profileId, _serverManagerBot.Token);
+ var response = _handleCommandCallback?.Invoke(CommandType.Info, serverId, channelId, profileIdOrAlias, _serverManagerBot.Token);
if (response is null)
{
await ReplyAsync("No servers associated with this channel.");
@@ -109,16 +109,16 @@ namespace ServerManagerTool.DiscordBot.Modules
[Command("status", RunMode = RunMode.Async)]
[Summary("Poll server for status")]
- [Remarks("status profileId")]
+ [Remarks("status profileId|alias")]
[RequireBotPermission(ChannelPermission.ViewChannel | ChannelPermission.SendMessages)]
- public async Task ServerStatusAsync(string profileId)
+ public async Task ServerStatusAsync(string profileIdOrAlias)
{
try
{
var serverId = Context?.Guild?.Id.ToString() ?? string.Empty;
var channelId = Context?.Channel?.Id.ToString() ?? string.Empty;
- var response = _handleCommandCallback?.Invoke(CommandType.Status, serverId, channelId, profileId, _serverManagerBot.Token);
+ var response = _handleCommandCallback?.Invoke(CommandType.Status, serverId, channelId, profileIdOrAlias, _serverManagerBot.Token);
if (response is null)
{
await ReplyAsync("No servers associated with this channel.");
diff --git a/src/ServerManager.Discord/ServerManagerBot.cs b/src/ServerManager.Discord/ServerManagerBot.cs
index 6c7f0d63..41684c39 100644
--- a/src/ServerManager.Discord/ServerManagerBot.cs
+++ b/src/ServerManager.Discord/ServerManagerBot.cs
@@ -1,12 +1,13 @@
-using Discord;
-using Discord.Addons.Interactive;
+using Discord.Addons.Interactive;
using Discord.Commands;
using Discord.Net.Providers.WS4Net;
using Discord.WebSocket;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using ServerManagerTool.DiscordBot.Delegates;
+using ServerManagerTool.DiscordBot.Enums;
using ServerManagerTool.DiscordBot.Interfaces;
+using ServerManagerTool.DiscordBot.Models;
using ServerManagerTool.DiscordBot.Services;
using System;
using System.Collections.Generic;
@@ -27,35 +28,26 @@ namespace ServerManagerTool.DiscordBot
public CancellationToken Token { get; private set; }
public bool Started { get; private set; }
- public async Task StartAsync(string discordToken, string commandPrefix, string dataDirectory, HandleCommandDelegate handleCommandCallback, HandleTranslationDelegate handleTranslationCallback, CancellationToken token)
+ public async Task StartAsync(LogLevel logLevel, string discordToken, string commandPrefix, string dataDirectory, bool allowAllBots, IEnumerable botWhitelist, HandleCommandDelegate handleCommandCallback, HandleTranslationDelegate handleTranslationCallback, CancellationToken token)
{
- if (Started)
- {
- return;
- }
- Started = true;
-
if (string.IsNullOrWhiteSpace(commandPrefix) || string.IsNullOrWhiteSpace(discordToken) || handleTranslationCallback is null || handleCommandCallback is null)
{
return;
}
+ if (Started)
+ {
+ return;
+ }
+
+ Started = true;
Token = token;
- if (commandPrefix.Any(c => !char.IsLetterOrDigit(c)))
- {
- throw new Exception("#DiscordBot_InvalidPrefixError");
- }
-
- if (!commandPrefix.EndsWith(DiscordBot.PREFIX_DELIMITER))
- {
- commandPrefix += DiscordBot.PREFIX_DELIMITER;
- }
-
var settings = new Dictionary
{
{ "DiscordSettings:Token", discordToken },
{ "DiscordSettings:Prefix", commandPrefix },
+ { "DiscordSettings:LogLevel", logLevel.ToString() },
{ "ServerManager:DataDirectory", dataDirectory },
};
@@ -66,12 +58,7 @@ namespace ServerManagerTool.DiscordBot
var socketConfig = new DiscordSocketConfig
{
-#if DEBUG
- LogLevel = LogSeverity.Verbose,
-#else
- LogLevel = LogSeverity.Info,
-#endif
- // Tell Discord.Net to cache 1000 messages per channel
+ LogLevel = LogLevelHelper.GetLogSeverity(logLevel),
MessageCacheSize = 1000,
};
if (Environment.OSVersion.Version < new Version(6, 2))
@@ -84,11 +71,14 @@ namespace ServerManagerTool.DiscordBot
{
// Force all commands to run async
DefaultRunMode = RunMode.Async,
-#if DEBUG
- LogLevel = LogSeverity.Verbose,
-#else
- LogLevel = LogSeverity.Info,
-#endif
+ LogLevel = LogLevelHelper.GetLogSeverity(logLevel),
+ CaseSensitiveCommands = false,
+ };
+
+ var discordBotConfig = new DiscordBotConfig
+ {
+ AllowAllBots = allowAllBots,
+ DiscordBotWhitelists = new List ( botWhitelist.Select(i => new DiscordBotWhitelist { BotId = i }) ),
};
// Build the service provider
@@ -105,6 +95,7 @@ namespace ServerManagerTool.DiscordBot
.AddSingleton()
.AddSingleton()
.AddSingleton(config)
+ .AddSingleton(discordBotConfig)
.AddSingleton(handleCommandCallback)
.AddSingleton(handleTranslationCallback)
.AddSingleton(this);
@@ -132,6 +123,7 @@ namespace ServerManagerTool.DiscordBot
}
await provider?.GetRequiredService().StopAsync();
+ Started = false;
}
}
}
diff --git a/src/ServerManager.Discord/Services/CommandHandlerService.cs b/src/ServerManager.Discord/Services/CommandHandlerService.cs
index dcb2f917..70fc6474 100644
--- a/src/ServerManager.Discord/Services/CommandHandlerService.cs
+++ b/src/ServerManager.Discord/Services/CommandHandlerService.cs
@@ -1,7 +1,11 @@
-using Discord.Commands;
+using Discord;
+using Discord.Commands;
using Discord.WebSocket;
using Microsoft.Extensions.Configuration;
+using ServerManagerTool.DiscordBot.Enums;
+using ServerManagerTool.DiscordBot.Models;
using System;
+using System.Linq;
using System.Threading.Tasks;
namespace ServerManagerTool.DiscordBot.Services
@@ -10,47 +14,71 @@ namespace ServerManagerTool.DiscordBot.Services
{
private readonly DiscordSocketClient _discord;
private readonly CommandService _commands;
+ private readonly LoggingService _logger;
private readonly IConfigurationRoot _config;
private readonly IServiceProvider _provider;
+ private readonly DiscordBotConfig _botConfig;
- public CommandHandlerService(DiscordSocketClient discord, CommandService commands, IConfigurationRoot config, IServiceProvider provider)
+ public CommandHandlerService(DiscordSocketClient discord, CommandService commands, LoggingService logger, IConfigurationRoot config, IServiceProvider provider, DiscordBotConfig botConfig)
{
_discord = discord;
_commands = commands;
+ _logger = logger;
_config = config;
_provider = provider;
-
+ _botConfig = botConfig ?? new DiscordBotConfig();
_discord.MessageReceived += OnMessageReceivedAsync;
}
private async Task OnMessageReceivedAsync(SocketMessage s)
{
- // Ensure the message is from a user/bot
- var msg = s as SocketUserMessage;
- if (msg is null)
+ if (LogLevel.Debug.ToString().Equals(_config["DiscordSettings:LogLevel"]))
+ await _logger?.OnLogAsync(new LogMessage(LogSeverity.Debug, MessageSource.System.ToString(), $"Intercepted the following message from {s.Author.Username} ({s.Author.Id}) - {s.Content}"));
+
+ // Ensure the message is a valid user socket message
+ if (!(s is SocketUserMessage msg))
+ return;
+
+ // Ignore self
+ if (msg.Author.Id == _discord.CurrentUser.Id)
{
+ if (LogLevel.Debug.ToString().Equals(_config["DiscordSettings:LogLevel"]))
+ await _logger?.OnLogAsync(new LogMessage(LogSeverity.Debug, MessageSource.System.ToString(), $"Message has come from this bot, message will be ignored."));
+
return;
}
- // Ignore self when checking commands
- if (msg.Author == _discord.CurrentUser)
- {
- return;
- }
-
- //Tell bot to ignore itself.
+ // check if the author is a bot
if (msg.Author.IsBot)
- {
- return;
- }
+ if (_botConfig.AllowAllBots)
+ {
+ if (LogLevel.Debug.ToString().Equals(_config["DiscordSettings:LogLevel"]))
+ await _logger?.OnLogAsync(new LogMessage(LogSeverity.Debug, MessageSource.System.ToString(), $"Message has come from another bot, allow all bots enabled."));
+ }
+ else
+ {
+ if (LogLevel.Debug.ToString().Equals(_config["DiscordSettings:LogLevel"]))
+ await _logger?.OnLogAsync(new LogMessage(LogSeverity.Debug, MessageSource.System.ToString(), $"Message has come from another bot, checking if bot is in the whitelist."));
- // Create the command context
- var context = new SocketCommandContext(_discord, msg);
+ if (!_botConfig.DiscordBotWhitelists.Any(b => b.BotId.Equals(msg.Author.Id.ToString())))
+ {
+ if (LogLevel.Debug.ToString().Equals(_config["DiscordSettings:LogLevel"]))
+ await _logger?.OnLogAsync(new LogMessage(LogSeverity.Debug, MessageSource.System.ToString(), $"Message has come from another bot, bot is not in the whitelist, message will be ignored."));
+
+ return;
+ }
+ }
// Check if the message has a valid command prefix
var argPos = 0;
- if (msg.HasStringPrefix(_config["DiscordSettings:Prefix"], ref argPos) || msg.HasMentionPrefix(_discord.CurrentUser, ref argPos))
+ if (msg.HasStringPrefix(_config["DiscordSettings:Prefix"], ref argPos, StringComparison.OrdinalIgnoreCase) || msg.HasMentionPrefix(_discord.CurrentUser, ref argPos))
{
+ if (LogLevel.Debug.ToString().Equals(_config["DiscordSettings:LogLevel"]))
+ await _logger?.OnLogAsync(new LogMessage(LogSeverity.Debug, MessageSource.System.ToString(), $"Message prefix matched, message will be processed."));
+
+ // Create the command context
+ var context = new SocketCommandContext(_discord, msg);
+
// Execute the command
var result = await _commands.ExecuteAsync(context, argPos, _provider);
diff --git a/src/ServerManager.Discord/Services/LoggingService.cs b/src/ServerManager.Discord/Services/LoggingService.cs
index 03b0d34e..83a27406 100644
--- a/src/ServerManager.Discord/Services/LoggingService.cs
+++ b/src/ServerManager.Discord/Services/LoggingService.cs
@@ -31,7 +31,7 @@ namespace ServerManagerTool.DiscordBot.Services
_commands.Log += OnLogAsync;
}
- private async Task OnLogAsync(LogMessage message)
+ internal async Task OnLogAsync(LogMessage message)
{
// Create the log directory if it doesn't exist
if (!Directory.Exists(LogDirectory))
diff --git a/src/ServerManager.Updater/Extensions/IEnumerableExtensions.cs b/src/ServerManager.Updater/Extensions/IEnumerableExtensions.cs
new file mode 100644
index 00000000..50db86f1
--- /dev/null
+++ b/src/ServerManager.Updater/Extensions/IEnumerableExtensions.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+
+namespace ServerManagerTool.Updater
+{
+ public static class IEnumerableExtensions
+ {
+ public static bool IsEmpty(this IEnumerable source)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException(nameof(source));
+ }
+
+ using (IEnumerator enumerator = source.GetEnumerator())
+ {
+ if (enumerator.MoveNext())
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static bool HasOne(this IEnumerable source)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException(nameof(source));
+ }
+
+ var count = 0;
+
+ using (IEnumerator enumerator = source.GetEnumerator())
+ {
+ while (enumerator.MoveNext())
+ {
+ if (++count > 1)
+ return false;
+ }
+ }
+
+ return count == 1;
+ }
+ }
+}
diff --git a/src/ServerManager.Updater/Program.cs b/src/ServerManager.Updater/Program.cs
index ec4ea0c9..a7c9238c 100644
--- a/src/ServerManager.Updater/Program.cs
+++ b/src/ServerManager.Updater/Program.cs
@@ -277,7 +277,7 @@ namespace ServerManagerTool.Updater
var processes = ProcessUtils.GetProcesses(process.ProcessName, executablePath);
// check if there is more than one instance of the application running
- if (processes.Length != 1)
+ if (!processes.HasOne())
throw new Exception("The application to be updated has more than one instance running.");
// get the command line of the process
diff --git a/src/ServerManager.Updater/Utils/ProcessUtils.cs b/src/ServerManager.Updater/Utils/ProcessUtils.cs
index ccf7248f..c60d54c5 100644
--- a/src/ServerManager.Updater/Utils/ProcessUtils.cs
+++ b/src/ServerManager.Updater/Utils/ProcessUtils.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
@@ -83,7 +84,7 @@ namespace ServerManagerTool.Updater
return Process.GetProcessById(processId);
}
- public static Process[] GetProcesses(string processName, string executablePath)
+ public static IEnumerable GetProcesses(string processName, string executablePath)
{
var runningProcesses = Process.GetProcessesByName(processName).ToList();
@@ -95,7 +96,7 @@ namespace ServerManagerTool.Updater
runningProcesses.RemoveAt(i);
}
- return runningProcesses.ToArray();
+ return runningProcesses;
}
public static bool IsAlreadyRunning()