mirror of
https://github.com/Strongleong/ScrapModLoader.git
synced 2024-08-15 00:03:19 +00:00
Compare commits
13 commits
Author | SHA1 | Date | |
---|---|---|---|
4f80b72603 | |||
deffd05581 | |||
|
25c3fd0425 | ||
085320215a | |||
110029692d | |||
8da74ffa6d | |||
ca870eb66b | |||
75333e8f68 | |||
|
90764c8636 | ||
|
1e25aa210a | ||
9deb717eea | |||
515aa519a4 | |||
02d9df8160 |
9 changed files with 383 additions and 304 deletions
83
README.md
83
README.md
|
@ -1,4 +1,4 @@
|
||||||
WIP ScrapModLoader
|
WIP ScrapModLoader
|
||||||
==============
|
==============
|
||||||
|
|
||||||
This applications is for managing mods for Scrapland.
|
This applications is for managing mods for Scrapland.
|
||||||
|
@ -24,45 +24,68 @@ ScrapModLoader supports both original and remastered versions of Scrapland.
|
||||||
|
|
||||||
For now mod for Scrapland is a *.sm file that basically is a zip arhive with following content:
|
For now mod for Scrapland is a *.sm file that basically is a zip arhive with following content:
|
||||||
|
|
||||||
| Filename | Description |
|
| Filename | Description |
|
||||||
|--------------------|----------------------------------------------|
|
|------------------------|--------------------------------------------------|
|
||||||
| icon.png | Icon for mod that will show up in mod loader |
|
| icon.png | Icon for mod that will show up in mod loader |
|
||||||
| config.xml | Information about mod |
|
| config.toml | Information about mod |
|
||||||
| <filename\>.packed | Container with all mod game assets |
|
| <game_version\>\ | Folder that named as game version mod made for |
|
||||||
|
| <filename\>.packed | Container with all mod game assets |
|
||||||
|
|
||||||
### meta.ini sample
|
You can have as many .packed files as you want. Mod loader will load everything.
|
||||||
```xml
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ScrapMod>
|
|
||||||
<Title>Mod Title</Title>
|
|
||||||
<Description>Mod Desciption</Description>
|
|
||||||
|
|
||||||
<Category>Category</Category>
|
.packed files in the root of mod will be copied to the `Mods` folder of Scrapland.
|
||||||
<Version>1.0</Version>
|
|
||||||
<RequiredLauncher>1.0</RequiredLauncher>
|
.pakced files under game version folder will load only to the appopriate game version.
|
||||||
<RequiredGame>1.1</RequiredGame>
|
|
||||||
|
### .sm structure sample
|
||||||
<Author name="Author1" website="https://example.com" />
|
```
|
||||||
<Author name="Author2" />
|
│ icon.png
|
||||||
|
│ config.toml
|
||||||
<Credits group="Mod author">
|
│ mod_assets.packed
|
||||||
<Credit name="Author1" />
|
├──1.0/
|
||||||
</Credits>
|
│ only_for_original.packed
|
||||||
<Credits group="Some credit" >
|
└──1.1/
|
||||||
<Credit name="Credit1" />
|
only_for_remastered.packed
|
||||||
<Credit name="Credit2" />
|
```
|
||||||
<Credit name="Credit3" />
|
|
||||||
</Credits>
|
### config.toml sample
|
||||||
</ScrapMod>
|
```toml
|
||||||
|
title = "Mod title"
|
||||||
|
description = "Mod description"
|
||||||
|
category = "Mod category"
|
||||||
|
version = "1.0"
|
||||||
|
requiredLauncher = "1.0"
|
||||||
|
supportedGameVersions = ["1.0", "1.1"]
|
||||||
|
|
||||||
|
authors = [
|
||||||
|
{ name = "Author 1" },
|
||||||
|
{ name = "Author 2" }
|
||||||
|
]
|
||||||
|
|
||||||
|
[[credits]]
|
||||||
|
group = "Group 1"
|
||||||
|
credits = [
|
||||||
|
{ name = "Author 1" },
|
||||||
|
{ name = "Author 2" },
|
||||||
|
{ name = "Author 3" }
|
||||||
|
]
|
||||||
|
|
||||||
|
[[credits]]
|
||||||
|
group = "Group 2"
|
||||||
|
credits = [
|
||||||
|
{ name = "Author 3" },
|
||||||
|
{ name = "Author 4" }
|
||||||
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
## TODO:
|
## TODO:
|
||||||
|
|
||||||
- [X] Support for custom *.packed
|
- [X] Support for custom *.packed
|
||||||
- [X] Supoprt for Scrapland Remastered
|
- [X] Supoprt for Scrapland Remastered
|
||||||
|
- [ ] Support for both Scrapland versions in single .sm file
|
||||||
- [ ] Support for custom game files (i.e. `\Traslation\` files or custom `QuickConsole.py`)
|
- [ ] Support for custom game files (i.e. `\Traslation\` files or custom `QuickConsole.py`)
|
||||||
- [ ] Recompiling *.py to *.pyc
|
- [ ] Recompiling *.py to *.pyc
|
||||||
- [ ] Mod settings.
|
- [ ] Mod settings.
|
||||||
- [ ] More meta info in `config.xml`
|
- [ ] More meta info in `config.toml`
|
||||||
- [ ] Multilanguage support
|
- [ ] Multilanguage support
|
||||||
- [ ] More mods :wink:
|
- [ ] More mods :wink:
|
|
@ -18,7 +18,7 @@
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="2*" />
|
<ColumnDefinition Width="2*" />
|
||||||
<ColumnDefinition Width="5" />
|
<ColumnDefinition Width="5" />
|
||||||
<ColumnDefinition Width="0*" />
|
<ColumnDefinition Name="PreviewColumn" Width="0*" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<ListView d:ItemsSource="{d:SampleData ItemCount=5}" Name="ModsList" Initialized="ModsList_Initialized" MouseDown="ModsList_MouseDown">
|
<ListView d:ItemsSource="{d:SampleData ItemCount=5}" Name="ModsList" Initialized="ModsList_Initialized" MouseDown="ModsList_MouseDown">
|
||||||
<ListView.View>
|
<ListView.View>
|
||||||
|
@ -28,14 +28,15 @@
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Stretch" HorizontalAlignment="Left">
|
<StackPanel Orientation="Horizontal" VerticalAlignment="Stretch" HorizontalAlignment="Left">
|
||||||
<CheckBox IsChecked="{Binding Checked}" VerticalAlignment="Center" HorizontalAlignment="Center" Checked="CheckBox_Checked" />
|
<CheckBox IsChecked="{Binding Checked}" VerticalAlignment="Center" HorizontalAlignment="Center" Checked="CheckBox_Checked" />
|
||||||
<Image Source="{Binding Icon}" Stretch="Fill" Width="16" Height="16" />
|
<Image Source="{Binding Icon}" Stretch="Fill" Width="16" Height="16" />
|
||||||
<Label Content="{Binding Name}" HorizontalAlignment="Stretch" VerticalAlignment="Center" />
|
<Label Content="{Binding Name}" HorizontalAlignment="Stretch" VerticalAlignment="Center" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</GridViewColumn.CellTemplate>
|
</GridViewColumn.CellTemplate>
|
||||||
</GridViewColumn>
|
</GridViewColumn>
|
||||||
|
<GridViewColumn Header="Category" DisplayMemberBinding="{Binding Category}" />
|
||||||
<GridViewColumn Header="Mod Version" DisplayMemberBinding="{Binding Version}" />
|
<GridViewColumn Header="Mod Version" DisplayMemberBinding="{Binding Version}" />
|
||||||
<GridViewColumn Header="Game Version" DisplayMemberBinding="{Binding RequiredGame}" />
|
<GridViewColumn Header="Game Version" DisplayMemberBinding="{Binding SupportedGameVersionsDisplay}" />
|
||||||
</GridView>
|
</GridView>
|
||||||
</ListView.View>
|
</ListView.View>
|
||||||
<ListView.ItemContainerStyle>
|
<ListView.ItemContainerStyle>
|
||||||
|
@ -70,8 +71,8 @@
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<StackPanel Grid.Column="2" Orientation="Horizontal" HorizontalAlignment="Left">
|
<StackPanel Grid.Column="2" Orientation="Horizontal" HorizontalAlignment="Left">
|
||||||
<ComboBox Name="ScraplandVersion" Margin="0,0,10,0" SelectionChanged="ScraplandVersion_SelectionChanged">
|
<ComboBox Name="ScraplandVersion" Margin="0,0,10,0" SelectionChanged="ScraplandVersion_SelectionChanged">
|
||||||
<ComboBoxItem Content="Original" IsEnabled="False" />
|
<ComboBoxItem Name="OriginalVersionItem" Content="Original" IsEnabled="False" />
|
||||||
<ComboBoxItem Content="Remastered" />
|
<ComboBoxItem Name ="RemasteredVersionItem" Content="Remastered" />
|
||||||
</ComboBox>
|
</ComboBox>
|
||||||
<CheckBox Name="Windowed" Content=" Windowed " Margin="0,0,10,0" HorizontalAlignment="Center" VerticalAlignment="Center" />
|
<CheckBox Name="Windowed" Content=" Windowed " Margin="0,0,10,0" HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||||
<CheckBox Name="CloseLauncher" Content=" Close launcher " Margin="0,0,10,0" HorizontalAlignment="Center" VerticalAlignment="Center" />
|
<CheckBox Name="CloseLauncher" Content=" Close launcher " Margin="0,0,10,0" HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||||
|
|
|
@ -28,8 +28,7 @@ namespace ScrapModLoader
|
||||||
{
|
{
|
||||||
if (Settings.Default.ModsPathes.Count == 0)
|
if (Settings.Default.ModsPathes.Count == 0)
|
||||||
{
|
{
|
||||||
String path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
|
String path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Scrapland mods");
|
||||||
+ Path.DirectorySeparatorChar + "Scrapland mods";
|
|
||||||
Settings.Default.ModsPathes.Add(path);
|
Settings.Default.ModsPathes.Add(path);
|
||||||
Directory.CreateDirectory(path);
|
Directory.CreateDirectory(path);
|
||||||
}
|
}
|
||||||
|
@ -37,16 +36,24 @@ namespace ScrapModLoader
|
||||||
// TODO: Refactor it to separate window with pretty loading animation
|
// TODO: Refactor it to separate window with pretty loading animation
|
||||||
if (modsLauncher.ScraplandPath == String.Empty && modsLauncher.ScraplandRemasteredPath == String.Empty)
|
if (modsLauncher.ScraplandPath == String.Empty && modsLauncher.ScraplandRemasteredPath == String.Empty)
|
||||||
{
|
{
|
||||||
Boolean isFoundScrapland = modsLauncher.SearchForScrapland();
|
try
|
||||||
if (!isFoundScrapland)
|
|
||||||
{
|
{
|
||||||
ButtonRunScrapland.IsEnabled = false;
|
Boolean isFoundScrapland = modsLauncher.SearchForScrapland();
|
||||||
MessageBox.Show("Error: unable to find Scrapland instalation. Please, specify yours game installation folder in settings.");
|
if (!isFoundScrapland)
|
||||||
|
{
|
||||||
|
ButtonRunScrapland.IsEnabled = false;
|
||||||
|
MessageBox.Show("Unable to find Scrapland instalation. Please, specify yours game installation folder in settings.",
|
||||||
|
"Warning", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (KeyNotFoundException ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show(ex.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
((ComboBoxItem)ScraplandVersion.Items[0]).IsEnabled = modsLauncher.ScraplandPath != String.Empty;
|
OriginalVersionItem.IsEnabled = modsLauncher.ScraplandPath != String.Empty;
|
||||||
((ComboBoxItem)ScraplandVersion.Items[1]).IsEnabled = modsLauncher.ScraplandRemasteredPath != String.Empty;
|
RemasteredVersionItem.IsEnabled = modsLauncher.ScraplandRemasteredPath != String.Empty;
|
||||||
|
|
||||||
ScraplandVersion.SelectedIndex = modsLauncher.ScraplandRemasteredPath != String.Empty ? 1 : 0;
|
ScraplandVersion.SelectedIndex = modsLauncher.ScraplandRemasteredPath != String.Empty ? 1 : 0;
|
||||||
|
|
||||||
|
@ -55,18 +62,18 @@ namespace ScrapModLoader
|
||||||
|
|
||||||
private void ModsList_Initialized(Object sender, EventArgs e) => ModsList.ItemsSource = modsLauncher.Mods;
|
private void ModsList_Initialized(Object sender, EventArgs e) => ModsList.ItemsSource = modsLauncher.Mods;
|
||||||
|
|
||||||
private void ModsList_MouseDown(Object sender, System.Windows.Input.MouseButtonEventArgs e)
|
private void ModsList_MouseDown(Object sender, MouseButtonEventArgs e)
|
||||||
{
|
{
|
||||||
if (MainGrid.ColumnDefinitions[2].Width.Value != 0)
|
if (PreviewColumn.Width.Value != 0)
|
||||||
{
|
{
|
||||||
gridLength = MainGrid.ColumnDefinitions[2].Width;
|
gridLength = PreviewColumn.Width;
|
||||||
MainGrid.ColumnDefinitions[2].Width = new GridLength(0, GridUnitType.Star);
|
PreviewColumn.Width = new GridLength(0, GridUnitType.Star);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ListViewItem_PreviewMouseLeftButtonDown(Object sender, MouseButtonEventArgs e)
|
private void ListViewItem_PreviewMouseLeftButtonDown(Object sender, MouseButtonEventArgs e)
|
||||||
{
|
{
|
||||||
MainGrid.ColumnDefinitions[2].Width = gridLength;
|
PreviewColumn.Width = gridLength;
|
||||||
|
|
||||||
if (sender is ListViewItem item)
|
if (sender is ListViewItem item)
|
||||||
{
|
{
|
||||||
|
@ -74,7 +81,7 @@ namespace ScrapModLoader
|
||||||
if (selectedModName == null)
|
if (selectedModName == null)
|
||||||
throw new KeyNotFoundException(nameof(selectedModName));
|
throw new KeyNotFoundException(nameof(selectedModName));
|
||||||
|
|
||||||
ScrapMod ? mod = modsLauncher.Mods.Find(mod => mod.Name == selectedModName);
|
ScrapMod? mod = modsLauncher.Mods.Find(mod => mod.Name == selectedModName);
|
||||||
|
|
||||||
if (mod == null)
|
if (mod == null)
|
||||||
throw new KeyNotFoundException(nameof(mod));
|
throw new KeyNotFoundException(nameof(mod));
|
||||||
|
@ -92,34 +99,35 @@ namespace ScrapModLoader
|
||||||
private void WriteModInfo(ScrapMod mod)
|
private void WriteModInfo(ScrapMod mod)
|
||||||
{
|
{
|
||||||
ModInfo.Document.Blocks.Clear();
|
ModInfo.Document.Blocks.Clear();
|
||||||
Paragraph parahraph = new Paragraph();
|
Paragraph paragraph = new Paragraph();
|
||||||
|
|
||||||
parahraph.Inlines.Add(new Bold(new Run("Description:\n")));
|
paragraph.Inlines.Add(new Bold(new Run("Description:\n")));
|
||||||
parahraph.Inlines.Add(new Run(mod.Description));
|
paragraph.Inlines.Add(new Run(mod.Description));
|
||||||
|
|
||||||
parahraph.Inlines.Add(new Bold(new Run("\n\nAuthors:\n")));
|
paragraph.Inlines.Add(new Bold(new Run("\n\nAuthors:\n")));
|
||||||
foreach (String autor in mod.Authors)
|
foreach (String autor in mod.Authors)
|
||||||
parahraph.Inlines.Add(new Run(autor + "\n"));
|
paragraph.Inlines.Add(new Run(autor + "\n"));
|
||||||
|
|
||||||
ModInfo.Document.Blocks.Add(parahraph);
|
ModInfo.Document.Blocks.Add(paragraph);
|
||||||
|
|
||||||
ModCreditsTab.Visibility = Visibility.Visible;
|
|
||||||
if (mod.Credits.Count == 0)
|
if (mod.Credits.Count == 0)
|
||||||
ModCreditsTab.Visibility = Visibility.Hidden;
|
ModCreditsTab.Visibility = Visibility.Hidden;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
ModCreditsTab.Visibility = Visibility.Visible;
|
||||||
|
|
||||||
ModCredits.Document.Blocks.Clear();
|
ModCredits.Document.Blocks.Clear();
|
||||||
parahraph = new Paragraph();
|
paragraph = new Paragraph();
|
||||||
|
|
||||||
foreach (KeyValuePair<String, List<String>> credit in mod.Credits)
|
foreach (KeyValuePair<String, List<String>> credit in mod.Credits)
|
||||||
{
|
{
|
||||||
parahraph.Inlines.Add(new Bold(new Run(credit.Key + "\n")));
|
paragraph.Inlines.Add(new Bold(new Run(credit.Key + "\n")));
|
||||||
foreach (String autor in credit.Value)
|
foreach (String autor in credit.Value)
|
||||||
parahraph.Inlines.Add(new Run(autor + "\n"));
|
paragraph.Inlines.Add(new Run(autor + "\n"));
|
||||||
parahraph.Inlines.Add(new Run("\n"));
|
paragraph.Inlines.Add(new Run("\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
ModCredits.Document.Blocks.Add(parahraph);
|
ModCredits.Document.Blocks.Add(paragraph);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,6 +140,8 @@ namespace ScrapModLoader
|
||||||
throw new NullReferenceException(nameof(isChecked));
|
throw new NullReferenceException(nameof(isChecked));
|
||||||
|
|
||||||
StackPanel parent = (StackPanel)checkbox.Parent;
|
StackPanel parent = (StackPanel)checkbox.Parent;
|
||||||
|
// TODO: replace by find template
|
||||||
|
// https://docs.microsoft.com/ru-ru/dotnet/desktop/wpf/data/how-to-find-datatemplate-generated-elements?view=netframeworkdesktop-4.8
|
||||||
Label label = (Label)parent.Children[2];
|
Label label = (Label)parent.Children[2];
|
||||||
String? selectedModName = label.Content.ToString();
|
String? selectedModName = label.Content.ToString();
|
||||||
|
|
||||||
|
@ -148,11 +158,16 @@ namespace ScrapModLoader
|
||||||
|
|
||||||
private void ButtonSettings_Click(Object sender, RoutedEventArgs e)
|
private void ButtonSettings_Click(Object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
SettingsWindow settingsWindow = new SettingsWindow();
|
SettingsWindow settingsWindow = new SettingsWindow(modsLauncher);
|
||||||
|
|
||||||
settingsWindow.ShowDialog();
|
settingsWindow.ShowDialog();
|
||||||
if (settingsWindow.Save)
|
if (settingsWindow.Save)
|
||||||
modsLauncher.ScanMods();
|
modsLauncher.ScanMods();
|
||||||
|
|
||||||
ModsList.Items.Refresh();
|
ModsList.Items.Refresh();
|
||||||
|
OriginalVersionItem.IsEnabled = modsLauncher.ScraplandPath != String.Empty;
|
||||||
|
RemasteredVersionItem.IsEnabled = modsLauncher.ScraplandRemasteredPath != String.Empty;
|
||||||
|
ScraplandVersion.SelectedIndex = modsLauncher.ScraplandRemasteredPath != String.Empty ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ButtonRunScrapland_Click(Object sender, RoutedEventArgs e)
|
private void ButtonRunScrapland_Click(Object sender, RoutedEventArgs e)
|
||||||
|
@ -166,7 +181,7 @@ namespace ScrapModLoader
|
||||||
String gamePath = modsLauncher.SelectedGameVersion == "1.0" ?
|
String gamePath = modsLauncher.SelectedGameVersion == "1.0" ?
|
||||||
modsLauncher.ScraplandPath : modsLauncher.ScraplandRemasteredPath;
|
modsLauncher.ScraplandPath : modsLauncher.ScraplandRemasteredPath;
|
||||||
|
|
||||||
Process.Start(gamePath + @"\bin\Scrap.exe", args);
|
Process.Start(Path.Combine(gamePath, @"bin\Scrap.exe"), args);
|
||||||
|
|
||||||
if (CloseLauncher.IsChecked ?? false)
|
if (CloseLauncher.IsChecked ?? false)
|
||||||
Close();
|
Close();
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
using Ionic.Zip;
|
||||||
|
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
|
|
||||||
|
@ -8,17 +12,17 @@ namespace ScrapModLoader
|
||||||
{
|
{
|
||||||
public class ModsLauncher
|
public class ModsLauncher
|
||||||
{
|
{
|
||||||
public List<ScrapMod> Mods { get; private set; }
|
public List<ScrapMod> Mods { get; private set; } = new List<ScrapMod>();
|
||||||
public String ScraplandPath { get; set; }
|
public List<String> ModsPathes { get; set; } = Utils.StringCollectionToList(Settings.Default.ModsPathes);
|
||||||
public String ScraplandRemasteredPath { get; set; }
|
public String ScraplandPath { get; set; } = Settings.Default.ScraplandPath;
|
||||||
public String SelectedGameVersion { get; set; }
|
public String ScraplandRemasteredPath { get; set; } = Settings.Default.ScraplandRemasteredPath;
|
||||||
|
public String SelectedGameVersion { get; set; } = "0.0";
|
||||||
|
public String LauncherVersion { get; set; } = "0.3";
|
||||||
|
public String SelectedGamePath { get; set; } = String.Empty;
|
||||||
|
|
||||||
public ModsLauncher()
|
public ModsLauncher()
|
||||||
{
|
{
|
||||||
Mods = new List<ScrapMod>();
|
|
||||||
ScraplandPath = Settings.Default.ScraplandPath;
|
|
||||||
ScraplandRemasteredPath = Settings.Default.ScraplandRemasteredPath;
|
|
||||||
SelectedGameVersion = "0.0";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ScanMods()
|
public void ScanMods()
|
||||||
|
@ -30,7 +34,7 @@ namespace ScrapModLoader
|
||||||
{
|
{
|
||||||
String[] files = Directory.GetFiles(folder, "*.sm", SearchOption.AllDirectories);
|
String[] files = Directory.GetFiles(folder, "*.sm", SearchOption.AllDirectories);
|
||||||
foreach (String file in files)
|
foreach (String file in files)
|
||||||
Mods.Add(new ScrapMod(file));
|
Mods.Add(ScrapMod.LoadFromFile(file));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,26 +55,32 @@ namespace ScrapModLoader
|
||||||
if (key == null)
|
if (key == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
foreach (String subkey_name in key.GetSubKeyNames())
|
foreach (String subKeyName in key.GetSubKeyNames())
|
||||||
{
|
{
|
||||||
using RegistryKey? subkey = key.OpenSubKey(subkey_name);
|
using RegistryKey? subKey = key.OpenSubKey(subKeyName);
|
||||||
if (subkey == null)
|
if (subKey == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
String? displayName = subkey.GetValue("DisplayName")?.ToString();
|
String? displayName = subKey.GetValue("DisplayName")?.ToString();
|
||||||
if (displayName == null)
|
if (displayName == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (displayName == "Scrapland")
|
if (displayName == "Scrapland" || displayName == "American McGee presents Scrapland")
|
||||||
{
|
{
|
||||||
ScraplandPath = subkey.GetValue("InstallLocation")?.ToString() ?? "";
|
ScraplandPath = subKey.GetValue("InstallLocation")?.ToString() ?? String.Empty;
|
||||||
|
if (String.IsNullOrEmpty(ScraplandPath))
|
||||||
|
throw new KeyNotFoundException("Installed Scrapland found, but unable to locate the instalation folder");
|
||||||
|
|
||||||
Settings.Default.ScraplandPath = ScraplandPath;
|
Settings.Default.ScraplandPath = ScraplandPath;
|
||||||
isFound = true;
|
isFound = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (displayName == "Scrapland Remastered")
|
if (displayName == "Scrapland Remastered")
|
||||||
{
|
{
|
||||||
ScraplandRemasteredPath = subkey.GetValue("InstallLocation")?.ToString() ?? "";
|
ScraplandRemasteredPath = subKey.GetValue("InstallLocation")?.ToString() ?? String.Empty;
|
||||||
|
if (String.IsNullOrEmpty(ScraplandRemasteredPath))
|
||||||
|
throw new KeyNotFoundException("Installed Scrapland Remastered found, but unable to locate the instalation folder");
|
||||||
|
|
||||||
Settings.Default.ScraplandRemasteredPath = ScraplandRemasteredPath;
|
Settings.Default.ScraplandRemasteredPath = ScraplandRemasteredPath;
|
||||||
isFound = true;
|
isFound = true;
|
||||||
}
|
}
|
||||||
|
@ -82,22 +92,76 @@ namespace ScrapModLoader
|
||||||
|
|
||||||
public void LoadMods()
|
public void LoadMods()
|
||||||
{
|
{
|
||||||
String gamePath = SelectedGameVersion == "1.0" ? ScraplandPath : ScraplandRemasteredPath;
|
SelectedGamePath = SelectedGameVersion == "1.0" ? ScraplandPath : ScraplandRemasteredPath;
|
||||||
|
|
||||||
foreach (ScrapMod mod in Mods)
|
foreach (ScrapMod mod in Mods)
|
||||||
{
|
{
|
||||||
if (mod.RequiredGame != SelectedGameVersion)
|
// TODO: Warning about not loading mods that not supports selected version
|
||||||
|
if (!mod.SupportedGameVersions.Contains(SelectedGameVersion) ||
|
||||||
|
Single.Parse(mod.RequiredLauncher, CultureInfo.InvariantCulture) < Single.Parse(LauncherVersion, CultureInfo.InvariantCulture))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (mod.Checked)
|
if (mod.Checked)
|
||||||
{
|
{
|
||||||
if (!mod.IsEnabled(gamePath))
|
if (!IsEnabled(mod))
|
||||||
mod.Enable(gamePath);
|
Enable(mod);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (mod.IsEnabled(gamePath))
|
if (IsEnabled(mod))
|
||||||
mod.Disable(gamePath);
|
Disable(mod);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String ModPath(ScrapMod mod) =>
|
||||||
|
Path.Combine(SelectedGamePath, "Mods", mod.Name);
|
||||||
|
|
||||||
|
public Boolean IsLoaded(ScrapMod mod) =>
|
||||||
|
Directory.Exists(ModPath(mod));
|
||||||
|
|
||||||
|
public Boolean IsEnabled(ScrapMod mod)
|
||||||
|
{
|
||||||
|
if (!IsLoaded(mod))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return Directory.EnumerateFiles(ModPath(mod), "*.disabled", SearchOption.AllDirectories).FirstOrDefault() == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Enable(ScrapMod mod)
|
||||||
|
{
|
||||||
|
if (!IsLoaded(mod))
|
||||||
|
LoadModToGame(mod);
|
||||||
|
|
||||||
|
if (IsEnabled(mod))
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (String file in Directory.EnumerateFiles(ModPath(mod), "*.disabled", SearchOption.AllDirectories))
|
||||||
|
File.Move(file, Path.ChangeExtension(file, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Disable(ScrapMod mod)
|
||||||
|
{
|
||||||
|
if (!IsEnabled(mod))
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (String file in Directory.EnumerateFiles(ModPath(mod), "*.packed", SearchOption.AllDirectories))
|
||||||
|
File.Move(file, file + ".disabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadModToGame(ScrapMod mod)
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(ModPath(mod));
|
||||||
|
|
||||||
|
using (ZipFile zipFile = ZipFile.Read(mod.ModPath))
|
||||||
|
{
|
||||||
|
foreach (ZipEntry zipEntry in zipFile)
|
||||||
|
{
|
||||||
|
if (!Path.GetFullPath(zipEntry.FileName).Contains(SelectedGameVersion))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (Path.GetExtension(zipEntry.FileName) == ".packed")
|
||||||
|
zipEntry.Extract(ModPath(mod));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,199 +2,113 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
using System.Xml;
|
|
||||||
|
|
||||||
using Ionic.Zip;
|
using Ionic.Zip;
|
||||||
|
|
||||||
|
using Tommy;
|
||||||
|
|
||||||
namespace ScrapModLoader
|
namespace ScrapModLoader
|
||||||
{
|
{
|
||||||
public class ScrapMod
|
public class ScrapMod
|
||||||
{
|
{
|
||||||
public String Name { get; private set; }
|
public String Name { get; private set; } = String.Empty;
|
||||||
public String Description { get; private set; }
|
|
||||||
public String ModPath { get; private set; }
|
|
||||||
public BitmapImage Icon { get; private set; }
|
|
||||||
public Boolean Checked { get; set; }
|
|
||||||
public String Category { get; private set; }
|
|
||||||
public String Version { get; private set; }
|
|
||||||
public String RequiredLauncher { get; private set; }
|
|
||||||
public String RequiredGame { get; private set; }
|
|
||||||
public List<String> Authors { get; private set; }
|
|
||||||
public Dictionary<String, List<String>> Credits { get; private set; }
|
|
||||||
|
|
||||||
public ScrapMod(String path)
|
public String Description { get; private set; } = String.Empty;
|
||||||
|
|
||||||
|
public String ModPath { get; private set; } = String.Empty;
|
||||||
|
|
||||||
|
public BitmapImage Icon { get; private set; } = new BitmapImage();
|
||||||
|
|
||||||
|
public Boolean Checked { get; set; } = false;
|
||||||
|
|
||||||
|
public String Category { get; private set; } = String.Empty;
|
||||||
|
|
||||||
|
public String Version { get; private set; } = String.Empty;
|
||||||
|
|
||||||
|
public String RequiredLauncher { get; private set; } = String.Empty;
|
||||||
|
|
||||||
|
public List<String> SupportedGameVersions { get; private set; } = new List<String>();
|
||||||
|
|
||||||
|
public String SupportedGameVersionsDisplay => String.Join(", ", SupportedGameVersions);
|
||||||
|
|
||||||
|
public List<String> Authors { get; private set; } = new List<String>();
|
||||||
|
|
||||||
|
public Dictionary<String, List<String>> Credits { get; private set; } = new Dictionary<String, List<String>>();
|
||||||
|
|
||||||
|
private ScrapMod()
|
||||||
{
|
{
|
||||||
ModPath = path;
|
|
||||||
Name = Path.GetFileNameWithoutExtension(path);
|
|
||||||
Description = String.Empty;
|
|
||||||
Icon = new BitmapImage();
|
|
||||||
Checked = false;
|
|
||||||
Category = String.Empty;
|
|
||||||
Version = String.Empty;
|
|
||||||
RequiredLauncher = String.Empty;
|
|
||||||
RequiredGame = String.Empty;
|
|
||||||
Authors = new List<String>();
|
|
||||||
Credits = new Dictionary<String, List<String>>();
|
|
||||||
LoadFromFile(path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ScrapMod LoadFromFile(String path)
|
||||||
public Boolean IsLoaded(String gamePath) => Directory.Exists(gamePath + @"Mods\" + Name);
|
|
||||||
|
|
||||||
public Boolean IsEnabled(String gamePath)
|
|
||||||
{
|
{
|
||||||
if (IsLoaded(gamePath))
|
using ZipFile zipFile = ZipFile.Read(path);
|
||||||
|
|
||||||
|
Byte[] iconBuffer = Utils.ExtractFromZip(zipFile, "icon.png");
|
||||||
|
Byte[] confBuffer = Utils.ExtractFromZip(zipFile, "config.toml");
|
||||||
|
|
||||||
|
ScrapMod mod = new ScrapMod()
|
||||||
{
|
{
|
||||||
foreach (String file in Directory.EnumerateFiles(gamePath + @"Mods\" + Name))
|
ModPath = path,
|
||||||
{
|
Icon = Utils.LoadImage(iconBuffer)
|
||||||
if (Path.GetExtension(file) == ".disabled")
|
};
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
LoadConfig(mod, confBuffer);
|
||||||
}
|
|
||||||
return false;
|
return mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Enable(String gamePath)
|
private static void LoadConfig(ScrapMod mod, Byte[] buffer)
|
||||||
{
|
{
|
||||||
if (!IsLoaded(gamePath))
|
using MemoryStream sourceStream = new MemoryStream(buffer);
|
||||||
LoadModToGame(gamePath);
|
using StreamReader reader = new StreamReader(sourceStream);
|
||||||
|
|
||||||
if (IsEnabled(gamePath))
|
TomlTable config = TOML.Parse(reader);
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (String file in Directory.EnumerateFiles(gamePath + @"Mods\" + Name))
|
CheckConfig(config);
|
||||||
{
|
|
||||||
if (Path.GetExtension(file) == ".disabled")
|
|
||||||
File.Move(file, Path.ChangeExtension(file, null));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Disable(String gamePath)
|
mod.Name = config["title"];
|
||||||
{
|
mod.Description = config["description"];
|
||||||
if (!IsEnabled(gamePath))
|
mod.Category = config["category"];
|
||||||
return;
|
mod.Version = config["version"];
|
||||||
|
mod.RequiredLauncher = config["requiredLauncher"];
|
||||||
|
|
||||||
foreach (String file in Directory.EnumerateFiles(gamePath + @"Mods\" + Name))
|
foreach (TomlNode version in config["supportedGameVersions"])
|
||||||
{
|
mod.SupportedGameVersions.Add(version);
|
||||||
if (Path.GetExtension(file) == ".packed")
|
|
||||||
File.Move(file, file + ".disabled");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void LoadModToGame(String gamePath)
|
foreach (TomlNode author in config["authors"])
|
||||||
{
|
mod.Authors.Add(author["name"]);
|
||||||
gamePath += @"Mods\" + Name;
|
|
||||||
Directory.CreateDirectory(gamePath);
|
|
||||||
|
|
||||||
using (ZipFile zipFile = ZipFile.Read(ModPath))
|
foreach (TomlNode credit in config["credits"])
|
||||||
{
|
|
||||||
foreach (ZipEntry zipEntry in zipFile)
|
|
||||||
{
|
|
||||||
if (Path.GetExtension(zipEntry.FileName) == ".packed")
|
|
||||||
{
|
|
||||||
zipEntry.Extract(gamePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void LoadFromFile(String path)
|
|
||||||
{
|
|
||||||
using (ZipFile zipFile = ZipFile.Read(path))
|
|
||||||
{
|
|
||||||
Byte[] iconBuffer = ExtractFromZip(zipFile, "icon.png");
|
|
||||||
Byte[] confBuffer = ExtractFromZip(zipFile, "config.xml");
|
|
||||||
LoadIcon(iconBuffer);
|
|
||||||
LoadConfig(confBuffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Byte[] ExtractFromZip(ZipFile zip, String entry_path)
|
|
||||||
{
|
|
||||||
ZipEntry? entry = zip[entry_path];
|
|
||||||
if (entry == null)
|
|
||||||
throw new FileFormatException($"No '{entry}' in {Name} found");
|
|
||||||
|
|
||||||
Byte[] buffer = new Byte[entry.UncompressedSize];
|
|
||||||
using (MemoryStream zipStream = new MemoryStream(buffer))
|
|
||||||
entry.Extract(zipStream);
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void LoadIcon(Byte[] buffer)
|
|
||||||
{
|
|
||||||
using (MemoryStream sourceStream = new MemoryStream(buffer))
|
|
||||||
{
|
|
||||||
Icon.BeginInit();
|
|
||||||
Icon.CacheOption = BitmapCacheOption.OnLoad;
|
|
||||||
Icon.StreamSource = sourceStream;
|
|
||||||
Icon.EndInit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void LoadConfig(Byte[] buffer)
|
|
||||||
{
|
|
||||||
using (MemoryStream sourceStream = new MemoryStream(buffer))
|
|
||||||
{
|
|
||||||
XmlDocument xmlDocument = new XmlDocument();
|
|
||||||
xmlDocument.Load(sourceStream);
|
|
||||||
ParseModInfoFromXml(xmlDocument);
|
|
||||||
ParseAuthorsFromXml(xmlDocument);
|
|
||||||
ParseCreditsFromXml(xmlDocument);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ParseModInfoFromXml(XmlDocument xmlDocument)
|
|
||||||
{
|
|
||||||
Description = xmlDocument.GetElementsByTagName("Description").Item(0)?.InnerText ??
|
|
||||||
throw new FileFormatException("No 'Description' tag in 'config.xml'");
|
|
||||||
Category = xmlDocument.GetElementsByTagName("Category").Item(0)?.InnerText ??
|
|
||||||
throw new FileFormatException("No 'Category' tag in 'config.xml'");
|
|
||||||
Version = xmlDocument.GetElementsByTagName("Version").Item(0)?.InnerText ??
|
|
||||||
throw new FileFormatException("No 'Version' tag in 'config.xml'");
|
|
||||||
RequiredLauncher = xmlDocument.GetElementsByTagName("RequiredLauncher").Item(0)?.InnerText ??
|
|
||||||
throw new FileFormatException("No 'RequiredLauncher' tag in 'config.xml'");
|
|
||||||
RequiredGame = xmlDocument.GetElementsByTagName("RequiredGame").Item(0)?.InnerText ??
|
|
||||||
throw new FileFormatException("No 'RequiredGame' tag in 'config.xml'");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ParseAuthorsFromXml(XmlDocument xmlDocument)
|
|
||||||
{
|
|
||||||
XmlNodeList authors = xmlDocument.GetElementsByTagName("Author");
|
|
||||||
foreach (XmlNode author in authors)
|
|
||||||
{
|
|
||||||
XmlAttribute? nameAttr = author.Attributes?["name"];
|
|
||||||
if (nameAttr == null)
|
|
||||||
throw new FileFormatException("No 'name' attribute in 'Author' tag in 'config.xml'");
|
|
||||||
Authors.Add(nameAttr.InnerText);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ParseCreditsFromXml(XmlDocument xmlDocument)
|
|
||||||
{
|
|
||||||
XmlNodeList credits = xmlDocument.GetElementsByTagName("Credits");
|
|
||||||
foreach (XmlNode credit in credits)
|
|
||||||
{
|
{
|
||||||
List<String> entries = new List<String>();
|
List<String> entries = new List<String>();
|
||||||
|
|
||||||
XmlAttribute? groupAttr = credit.Attributes?["group"];
|
foreach (TomlNode entry in credit["credits"])
|
||||||
if (groupAttr == null)
|
entries.Add(entry["name"]);
|
||||||
throw new FileFormatException("No 'group' attribute in 'Credits' tag in 'config.xml'");
|
|
||||||
|
|
||||||
foreach (XmlNode entry in credit)
|
mod.Credits.Add(credit["group"], entries);
|
||||||
{
|
|
||||||
XmlAttribute? nameAttr = entry.Attributes?["name"];
|
|
||||||
if (nameAttr == null)
|
|
||||||
throw new FileFormatException("No 'name' attribute in 'Author' tag in 'config.xml'");
|
|
||||||
|
|
||||||
entries.Add(nameAttr.InnerText);
|
|
||||||
}
|
|
||||||
|
|
||||||
Credits.Add(groupAttr.InnerText, entries);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void CheckConfig(TomlTable config)
|
||||||
|
{
|
||||||
|
if (!config.HasKey("title"))
|
||||||
|
throw new FileFormatException("No 'title' key in 'config.toml'");
|
||||||
|
|
||||||
|
if (!config.HasKey("description"))
|
||||||
|
throw new FileFormatException("No 'description' key in 'config.toml'");
|
||||||
|
|
||||||
|
if (!config.HasKey("category"))
|
||||||
|
throw new FileFormatException("No 'category' key in 'config.toml'");
|
||||||
|
|
||||||
|
if (!config.HasKey("version"))
|
||||||
|
throw new FileFormatException("No 'version' key in 'config.toml'");
|
||||||
|
|
||||||
|
if (!config.HasKey("requiredLauncher"))
|
||||||
|
throw new FileFormatException("No 'name' key in 'config.toml'");
|
||||||
|
|
||||||
|
if (!config.HasKey("supportedGameVersions"))
|
||||||
|
throw new FileFormatException("No 'supportedGameVersions' key in 'config.toml'");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="DotNetZip" Version="1.16.0" />
|
<PackageReference Include="DotNetZip" Version="1.16.0" />
|
||||||
|
<PackageReference Include="Tommy" Version="3.1.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -63,7 +63,7 @@
|
||||||
<TextBox Grid.Row="0" Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Center" x:Name="ScraplandPathTextBox" IsEnabled="False" />
|
<TextBox Grid.Row="0" Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Center" x:Name="ScraplandPathTextBox" IsEnabled="False" />
|
||||||
<StackPanel Grid.Row="0" Grid.Column="2" Orientation="Horizontal">
|
<StackPanel Grid.Row="0" Grid.Column="2" Orientation="Horizontal">
|
||||||
<Button Content=" Browse... " HorizontalAlignment="Right" VerticalAlignment="Center" Margin="5,0,5,0" Name="ButtonBrowseScrap" Click="ButtonBrowseScrap_Click"/>
|
<Button Content=" Browse... " HorizontalAlignment="Right" VerticalAlignment="Center" Margin="5,0,5,0" Name="ButtonBrowseScrap" Click="ButtonBrowseScrap_Click"/>
|
||||||
<Button Content=" Clear " HorizontalAlignment="Right" VerticalAlignment="Center" Margin="5,0,5,0" Name="ButtonClearScrap" Click="ButtonClearScrap_Click"/>
|
<Button Content=" Clear " HorizontalAlignment="Right" VerticalAlignment="Center" Margin="5,0,5,0" Name="ButtonClearScrap" Click="ButtonClearScrap_Click" IsEnabled="False"/>
|
||||||
<Button Content=" Show In Explorer " HorizontalAlignment="Right" VerticalAlignment="Center" Margin="5,0,5,0" Name="ButtonShowScrap" IsEnabled="False" Click="ButtonShowScrap_Click" />
|
<Button Content=" Show In Explorer " HorizontalAlignment="Right" VerticalAlignment="Center" Margin="5,0,5,0" Name="ButtonShowScrap" IsEnabled="False" Click="ButtonShowScrap_Click" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
|
@ -71,9 +71,10 @@
|
||||||
<TextBox Grid.Row="1" Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Center" x:Name="ScraplandRemasteredPathTextBox" IsEnabled="False" />
|
<TextBox Grid.Row="1" Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Center" x:Name="ScraplandRemasteredPathTextBox" IsEnabled="False" />
|
||||||
<StackPanel Grid.Row="1" Grid.Column="2" Orientation="Horizontal">
|
<StackPanel Grid.Row="1" Grid.Column="2" Orientation="Horizontal">
|
||||||
<Button Content=" Browse... " HorizontalAlignment="Right" VerticalAlignment="Center" Margin="5,0,5,0" Name="ButtonBrowseScrapRemaster" Click="ButtonBrowseScrapRemaster_Click"/>
|
<Button Content=" Browse... " HorizontalAlignment="Right" VerticalAlignment="Center" Margin="5,0,5,0" Name="ButtonBrowseScrapRemaster" Click="ButtonBrowseScrapRemaster_Click"/>
|
||||||
<Button Content=" Clear " HorizontalAlignment="Right" VerticalAlignment="Center" Margin="5,0,5,0" Name="ButtonClearScrapRemaster" Click="ButtonClearScrapRemaster_Click"/>
|
<Button Content=" Clear " HorizontalAlignment="Right" VerticalAlignment="Center" Margin="5,0,5,0" Name="ButtonClearScrapRemaster" Click="ButtonClearScrapRemaster_Click" IsEnabled="False"/>
|
||||||
<Button Content=" Show In Explorer " HorizontalAlignment="Right" VerticalAlignment="Center" Margin="5,0,5,0" Name="ButtonShowScrapRemaster" IsEnabled="False" Click="ButtonShowScrapRemaster_Click" />
|
<Button Content=" Show In Explorer " HorizontalAlignment="Right" VerticalAlignment="Center" Margin="5,0,5,0" Name="ButtonShowScrapRemaster" IsEnabled="False" Click="ButtonShowScrapRemaster_Click" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
<Button Grid.Column="2" Content=" Auto find " HorizontalAlignment="Right" Grid.Row="2" VerticalAlignment="Center" Margin="5,0,5,0" Name="ButtonAutoFind" Click="ButtonAutoFind_Click" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</GroupBox>
|
</GroupBox>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
|
@ -12,27 +12,28 @@ namespace ScrapModLoader
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class SettingsWindow : Window
|
public partial class SettingsWindow : Window
|
||||||
{
|
{
|
||||||
public List<String> ModsPathes { get; set; }
|
|
||||||
public String ScraplandPath { get; set; }
|
|
||||||
public String ScraplandRemasteredPath { get; set; }
|
|
||||||
public Boolean Save { get; set; }
|
public Boolean Save { get; set; }
|
||||||
|
private ModsLauncher ModsLauncherInstance { get; set; }
|
||||||
|
|
||||||
public SettingsWindow()
|
public SettingsWindow(ModsLauncher modsLauncher)
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
Save = false;
|
Save = false;
|
||||||
|
ModsLauncherInstance = modsLauncher;
|
||||||
|
|
||||||
ModsPathes = Utils.StringCollectionToList(Settings.Default.ModsPathes);
|
ModsPathesList.ItemsSource = ModsLauncherInstance.ModsPathes;
|
||||||
ScraplandPath = Settings.Default.ScraplandPath;
|
ScraplandPathTextBox.Text = ModsLauncherInstance.ScraplandPath;
|
||||||
ScraplandRemasteredPath = Settings.Default.ScraplandRemasteredPath;
|
ScraplandRemasteredPathTextBox.Text = ModsLauncherInstance.ScraplandRemasteredPath;
|
||||||
|
|
||||||
ModsPathesList.ItemsSource = ModsPathes;
|
Boolean enable = ModsLauncherInstance.ScraplandPath != String.Empty;
|
||||||
ScraplandPathTextBox.Text = ScraplandPath;
|
ButtonShowScrap.IsEnabled = enable;
|
||||||
ScraplandRemasteredPathTextBox.Text = ScraplandRemasteredPath;
|
ButtonClearScrap.IsEnabled = enable;
|
||||||
|
|
||||||
ButtonShowScrap.IsEnabled = ScraplandPath != String.Empty;
|
enable = ModsLauncherInstance.ScraplandRemasteredPath != String.Empty;
|
||||||
ButtonShowScrapRemaster.IsEnabled = ScraplandRemasteredPath != String.Empty;
|
ButtonShowScrapRemaster.IsEnabled = enable;
|
||||||
|
ButtonClearScrapRemaster.IsEnabled = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------
|
// -------------------------------------------
|
||||||
|
@ -44,13 +45,13 @@ namespace ScrapModLoader
|
||||||
{
|
{
|
||||||
String folder = Utils.GetFolderDialog();
|
String folder = Utils.GetFolderDialog();
|
||||||
if (folder != String.Empty)
|
if (folder != String.Empty)
|
||||||
ModsPathes.Add(folder);
|
ModsLauncherInstance.ModsPathes.Add(folder);
|
||||||
|
|
||||||
ModsPathesList.Items.Refresh();
|
ModsPathesList.Items.Refresh();
|
||||||
}
|
}
|
||||||
private void ButtonRemove_Click(Object sender, RoutedEventArgs e)
|
private void ButtonRemove_Click(Object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
ModsPathes.Remove((String)ModsPathesList.SelectedValue);
|
ModsLauncherInstance.ModsPathes.Remove((String)ModsPathesList.SelectedValue);
|
||||||
ModsPathesList.Items.Refresh();
|
ModsPathesList.Items.Refresh();
|
||||||
|
|
||||||
ButtonRemove.IsEnabled = false;
|
ButtonRemove.IsEnabled = false;
|
||||||
|
@ -64,21 +65,21 @@ namespace ScrapModLoader
|
||||||
if (index == 0)
|
if (index == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
String? temp = ModsPathes[index - 1];
|
String? temp = ModsLauncherInstance.ModsPathes[index - 1];
|
||||||
ModsPathes[index - 1] = ModsPathes[index];
|
ModsLauncherInstance.ModsPathes[index - 1] = ModsLauncherInstance.ModsPathes[index];
|
||||||
ModsPathes[index] = temp;
|
ModsLauncherInstance.ModsPathes[index] = temp;
|
||||||
|
|
||||||
ModsPathesList.Items.Refresh();
|
ModsPathesList.Items.Refresh();
|
||||||
}
|
}
|
||||||
private void ButtonDown_Click(Object sender, RoutedEventArgs e)
|
private void ButtonDown_Click(Object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
Int32 index = ModsPathesList.SelectedIndex;
|
Int32 index = ModsPathesList.SelectedIndex;
|
||||||
if (index == ModsPathes.Count - 1)
|
if (index == ModsLauncherInstance.ModsPathes.Count - 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
String? temp = ModsPathes[index + 1];
|
String? temp = ModsLauncherInstance.ModsPathes[index + 1];
|
||||||
ModsPathes[index + 1] = ModsPathes[index];
|
ModsLauncherInstance.ModsPathes[index + 1] = ModsLauncherInstance.ModsPathes[index];
|
||||||
ModsPathes[index] = temp;
|
ModsLauncherInstance.ModsPathes[index] = temp;
|
||||||
|
|
||||||
ModsPathesList.Items.Refresh();
|
ModsPathesList.Items.Refresh();
|
||||||
}
|
}
|
||||||
|
@ -108,50 +109,76 @@ namespace ScrapModLoader
|
||||||
|
|
||||||
private void ButtonBrowseScrap_Click(Object sender, RoutedEventArgs e)
|
private void ButtonBrowseScrap_Click(Object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
String scraplandPath = Utils.GetFolderDialog();
|
String ScraplandPath = Utils.GetFolderDialog();
|
||||||
if (scraplandPath != String.Empty)
|
if (ScraplandPath != String.Empty)
|
||||||
{
|
{
|
||||||
ScraplandPathTextBox.Text = scraplandPath;
|
ScraplandPathTextBox.Text = ScraplandPath + "\\";
|
||||||
ScraplandPath = scraplandPath;
|
ModsLauncherInstance.ScraplandPath = ScraplandPath + "\\";
|
||||||
ButtonShowScrap.IsEnabled = true;
|
ButtonShowScrap.IsEnabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void ButtonBrowseScrapRemaster_Click(Object sender, RoutedEventArgs e)
|
private void ButtonBrowseScrapRemaster_Click(Object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
String scraplandRemasteredPath = Utils.GetFolderDialog();
|
String ScraplandRemasteredPath = Utils.GetFolderDialog();
|
||||||
if (scraplandRemasteredPath != String.Empty)
|
if (ScraplandRemasteredPath != String.Empty)
|
||||||
{
|
{
|
||||||
ScraplandRemasteredPathTextBox.Text = scraplandRemasteredPath;
|
ScraplandRemasteredPathTextBox.Text = ScraplandRemasteredPath + "\\";
|
||||||
ScraplandRemasteredPath = scraplandRemasteredPath;
|
ModsLauncherInstance.ScraplandRemasteredPath = ScraplandRemasteredPath + "\\";
|
||||||
ButtonShowScrapRemaster.IsEnabled = true;
|
ButtonShowScrapRemaster.IsEnabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void ButtonClearScrap_Click(Object sender, RoutedEventArgs e)
|
private void ButtonClearScrap_Click(Object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
ScraplandPathTextBox.Text = String.Empty;
|
ScraplandPathTextBox.Text = String.Empty;
|
||||||
|
ButtonClearScrap.IsEnabled = false;
|
||||||
ButtonShowScrap.IsEnabled = false;
|
ButtonShowScrap.IsEnabled = false;
|
||||||
ScraplandPath = String.Empty;
|
ModsLauncherInstance.ScraplandPath = String.Empty;
|
||||||
}
|
}
|
||||||
private void ButtonClearScrapRemaster_Click(Object sender, RoutedEventArgs e)
|
private void ButtonClearScrapRemaster_Click(Object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
ScraplandRemasteredPathTextBox.Text = String.Empty;
|
ScraplandRemasteredPathTextBox.Text = String.Empty;
|
||||||
ButtonClearScrapRemaster.IsEnabled = false;
|
ButtonClearScrapRemaster.IsEnabled = false;
|
||||||
ScraplandRemasteredPath = String.Empty;
|
ButtonShowScrapRemaster.IsEnabled = false;
|
||||||
|
ModsLauncherInstance.ScraplandRemasteredPath = String.Empty;
|
||||||
}
|
}
|
||||||
private void ButtonShowScrap_Click(Object sender, RoutedEventArgs e)
|
private void ButtonShowScrap_Click(Object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
String? path = Path.GetDirectoryName(ScraplandPath);
|
String? path = Path.GetDirectoryName(ModsLauncherInstance.ScraplandPath);
|
||||||
if (path == null)
|
if (path == null)
|
||||||
throw new DirectoryNotFoundException("Cannot find direcotry for Scrapland");
|
throw new DirectoryNotFoundException("Cannot find direcotry for Scrapland");
|
||||||
Process.Start("explorer.exe", path);
|
Process.Start("explorer.exe", path);
|
||||||
}
|
}
|
||||||
private void ButtonShowScrapRemaster_Click(Object sender, RoutedEventArgs e)
|
private void ButtonShowScrapRemaster_Click(Object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
String? path = Path.GetDirectoryName(ScraplandRemasteredPath);
|
String? path = Path.GetDirectoryName(ModsLauncherInstance.ScraplandRemasteredPath);
|
||||||
if (path == null)
|
if (path == null)
|
||||||
throw new DirectoryNotFoundException("Cannot find direcotry for Scrapland");
|
throw new DirectoryNotFoundException("Cannot find direcotry for Scrapland");
|
||||||
Process.Start("explorer.exe", path);
|
Process.Start("explorer.exe", path);
|
||||||
}
|
}
|
||||||
|
private void ButtonAutoFind_Click(Object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Boolean isFoundScrapland = ModsLauncherInstance.SearchForScrapland();
|
||||||
|
if (!isFoundScrapland)
|
||||||
|
MessageBox.Show("Error: unable to find Scrapland instalation. Please, specify yours game installation folder in settings.");
|
||||||
|
}
|
||||||
|
catch (KeyNotFoundException ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show(ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
ScraplandPathTextBox.Text = ModsLauncherInstance.ScraplandPath;
|
||||||
|
ScraplandRemasteredPathTextBox.Text = ModsLauncherInstance.ScraplandRemasteredPath;
|
||||||
|
|
||||||
|
Boolean enable = ModsLauncherInstance.ScraplandPath != String.Empty;
|
||||||
|
ButtonShowScrap.IsEnabled = enable;
|
||||||
|
ButtonClearScrap.IsEnabled = enable;
|
||||||
|
|
||||||
|
enable = ModsLauncherInstance.ScraplandRemasteredPath != String.Empty;
|
||||||
|
ButtonShowScrapRemaster.IsEnabled = enable;
|
||||||
|
ButtonClearScrapRemaster.IsEnabled = enable;
|
||||||
|
}
|
||||||
|
|
||||||
// -------------------------------------------
|
// -------------------------------------------
|
||||||
// Window contols buttons
|
// Window contols buttons
|
||||||
|
@ -161,10 +188,11 @@ namespace ScrapModLoader
|
||||||
private void ButtonSave_Click(Object sender, RoutedEventArgs e)
|
private void ButtonSave_Click(Object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
Settings.Default.ModsPathes.Clear();
|
Settings.Default.ModsPathes.Clear();
|
||||||
Settings.Default.ModsPathes.AddRange(ModsPathes.ToArray());
|
Settings.Default.ModsPathes.AddRange(ModsLauncherInstance.ModsPathes.ToArray());
|
||||||
Settings.Default.ScraplandPath = ScraplandPath;
|
Settings.Default.ScraplandPath = ModsLauncherInstance.ScraplandPath;
|
||||||
Settings.Default.ScraplandRemasteredPath = ScraplandRemasteredPath;
|
Settings.Default.ScraplandRemasteredPath = ModsLauncherInstance.ScraplandRemasteredPath;
|
||||||
Settings.Default.Save();
|
Settings.Default.Save();
|
||||||
|
|
||||||
Save = true;
|
Save = true;
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +1,59 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
|
using System.IO;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
|
||||||
namespace ScrapModLoader
|
using Ionic.Zip;
|
||||||
|
|
||||||
|
|
||||||
|
namespace ScrapModLoader;
|
||||||
|
|
||||||
|
internal static class Utils
|
||||||
{
|
{
|
||||||
internal static class Utils
|
public static String GetFolderDialog()
|
||||||
{
|
{
|
||||||
public static String GetFolderDialog()
|
using System.Windows.Forms.FolderBrowserDialog dialog = new System.Windows.Forms.FolderBrowserDialog();
|
||||||
{
|
System.Windows.Forms.DialogResult result = dialog.ShowDialog();
|
||||||
using System.Windows.Forms.FolderBrowserDialog? dialog = new System.Windows.Forms.FolderBrowserDialog();
|
return dialog.SelectedPath;
|
||||||
System.Windows.Forms.DialogResult result = dialog.ShowDialog();
|
}
|
||||||
return dialog.SelectedPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<String> StringCollectionToList(StringCollection collection)
|
public static List<String> StringCollectionToList(StringCollection collection)
|
||||||
|
{
|
||||||
|
List<String> list = new List<String>();
|
||||||
|
foreach (String? item in collection)
|
||||||
{
|
{
|
||||||
List<String> list = new List<String>();
|
if (item != null)
|
||||||
foreach (String? item in collection)
|
list.Add(item);
|
||||||
{
|
|
||||||
if (item != null)
|
|
||||||
list.Add(item);
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Byte[] ExtractFromZip(ZipFile zip, String entry_path)
|
||||||
|
{
|
||||||
|
ZipEntry? entry = zip[entry_path];
|
||||||
|
if (entry == null)
|
||||||
|
throw new FileFormatException($"No '{entry_path}' in {zip.Name} found");
|
||||||
|
|
||||||
|
Byte[] buffer = new Byte[entry.UncompressedSize];
|
||||||
|
using (MemoryStream zipStream = new MemoryStream(buffer))
|
||||||
|
entry.Extract(zipStream);
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BitmapImage LoadImage(Byte[] buffer)
|
||||||
|
{
|
||||||
|
using MemoryStream sourceStream = new MemoryStream(buffer);
|
||||||
|
|
||||||
|
BitmapImage? image = new BitmapImage();
|
||||||
|
|
||||||
|
image.BeginInit();
|
||||||
|
image.CacheOption = BitmapCacheOption.OnLoad;
|
||||||
|
image.StreamSource = sourceStream;
|
||||||
|
image.EndInit();
|
||||||
|
|
||||||
|
return image;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue