Skip to content

Commit

Permalink
feat: Added Weapons category(#95)
Browse files Browse the repository at this point in the history
feat: The Elevator process will now automatically refresh mods in game when enabling/disabling mods in JASM

chore: Added more tooltips around the app and some minor text changes
  • Loading branch information
Jorixon authored Nov 28, 2023
1 parent 7349b41 commit 6c55bf3
Show file tree
Hide file tree
Showing 199 changed files with 2,116 additions and 831 deletions.
Binary file added Images/v1.8.0/ModInstallerHelper.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Unhandled exceptions are written to the Logs file as well. Debug logging can be
- Automatically sort unsorted mods into respective character's folders
- Move Mods between characters
- Start a 3Dmigto launcher and/or a certain game straight from the app
- The app watches character folders and automaticly updates if skins are added or removed from folders.
- The app watches character folders and automatically updates if skins are added or removed from folders.
- Edit merged.ini keys
- Export (copy) all mods managed by JASM to a user specified folder
- Refresh mods using F10 or the refresh button in app. (Requires an elevated side process, see description bellow)
Expand Down Expand Up @@ -52,20 +52,21 @@ If you don't have these downloaded the application will prompt you to download n

### Elevator process
The elevator process is a small program that can be started as an elevated process from the app. It is completely optional and is kind of a niche feature.
It is used to send the F10 key to the game to refresh the mods. This is done trough named pipes.
It is used to send the F10 key to the game to refresh the mods. Enabling and disabling mods in JASM will also automatically refresh the mods. This is done through named pipes.
The process does not listen for keybinds it only waits for a simple "1" command from the app. This makes it send the F10 key to the game.

The [H.InputSimulator](https://github.com/HavenDV/H.InputSimulator) library is used to send keyboard input.


### Limitations and Acknowledgements
- The Json file that stores the characters is a stripped down version of this [genshin-impact-tools ](https://github.com/tokafew420/genshin-impact-tools/blob/3d10e411a411b8ed532356ccb45fcd80b6b2383b/data/characters.json) and images are also from the same repository.
- The Json file that stores the Genshin characters is a modified and stripped down version of this [genshin-impact-tools ](https://github.com/tokafew420/genshin-impact-tools/blob/3d10e411a411b8ed532356ccb45fcd80b6b2383b/data/characters.json) and some of the images are also from the same repository.
- The Json file that stores the Genshin weapons is a modified and stripped down version of this [genshin-impact-tools ](https://github.com/tokafew420/genshin-impact-tools/blob/94d55e8b88d5580d84e6b0991ce82e2798220d44/data/weapons.json) and the weapon images are also from the same repository.
- 7-Zip is bundled with the app, 7-Zip is licensed under the GNU Lesser General Public License (LGPL). You can find the full license details and source code at [www.7-zip.org](https://www.7-zip.org/).
- SharpCompress is used if the bundled 7-zip is not found. SharpCompress is licensed under the MIT license. You can find the full license details and source code at [SharpCompress's GitHub Page](https://github.com/adamhathcock/sharpcompress)
- WinUI3Localizer is used for localization. WinUI3Localizer is licensed under the MIT license. You can find the full license details and source code at [WinUI3Localizer's GitHub Page](https://github.com/AndrewKeepCoding/WinUI3Localizer)
- I have tested this app mostly on two machines running Windows 11. I have tested it on Windows 10 in a virtual machine.
- There are definitely bugs. I have not tested this app enough and there are not tests written for it.
- Drag and drop is really finicky for some reason. It works but it's not perfect. So the code for it is still quite messy and it involed time consuming tirial and error until it worked.
- Drag and drop is really finicky for some reason. It works but it's not perfect. So the code for it is still quite messy and it involved time consuming trial and error until it worked.
- Changing the app's theme causes instability and usually it crashes when navigating to another page. This means it needs to restart after changing the theme
- I made everything in dark mode theme, so light mode does not look good.
- App settings are stored here ```C:\Users\<username>\AppData\Local\JASM\ApplicationData```
Expand Down
6 changes: 5 additions & 1 deletion src/GIMI-ModManager.Core/GIMI-ModManager.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@
</AssemblyAttribute>
</ItemGroup>


<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>UpdateGenshinAssets</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
<ItemGroup>
<PackageReference Include="ErrorOr" Version="1.2.1" />
<PackageReference Include="FuzzySharp" Version="2.0.2" />
Expand Down
34 changes: 33 additions & 1 deletion src/GIMI-ModManager.Core/GamesService/GameService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public class GameService : IGameService

private readonly EnableableList<INpc> _npcs = new();
private readonly EnableableList<IGameObject> _gameObjects = new();
private readonly EnableableList<IWeapon> _weapons = new();

private readonly List<ICategory> _categories = new();

Expand Down Expand Up @@ -88,6 +89,8 @@ public async Task InitializeAsync(string assetsDirectory, string localSettingsDi

await InitializeObjectsAsync().ConfigureAwait(false);

await InitializeWeaponsAsync().ConfigureAwait(false);

CheckIfDuplicateInternalNameExists();

_initialized = true;
Expand Down Expand Up @@ -157,6 +160,9 @@ public List<IModdableObject> GetModdableObjects(ICategory category, GetOnly getO
if (category.ModCategory == ModCategory.Object)
return _gameObjects.GetOfType(getOnlyStatus).Cast<IModdableObject>().ToList();

if (category.ModCategory == ModCategory.Weapons)
return _weapons.GetOfType(getOnlyStatus).Cast<IModdableObject>().ToList();

throw new ArgumentException($"Category {category.InternalName} is not supported");
}

Expand All @@ -168,6 +174,7 @@ public List<IModdableObject> GetAllModdableObjects(GetOnly getOnlyStatus = GetOn
moddableObjects.AddRange(_characters.GetOfType(getOnlyStatus));
moddableObjects.AddRange(_npcs.GetOfType(getOnlyStatus));
moddableObjects.AddRange(_gameObjects.GetOfType(getOnlyStatus));
moddableObjects.AddRange(_weapons.GetOfType(getOnlyStatus));

return moddableObjects;
}
Expand All @@ -183,6 +190,9 @@ public List<T> GetAllModdableObjectsAsCategory<T>(GetOnly getOnlyStatus = GetOnl
if (typeof(T) == typeof(IGameObject))
return _gameObjects.GetOfType(getOnlyStatus).Cast<T>().ToList();

if (typeof(T) == typeof(IWeapon))
return _weapons.GetOfType(getOnlyStatus).Cast<T>().ToList();


throw new ArgumentException($"Type {typeof(T)} is not supported");
}
Expand Down Expand Up @@ -460,8 +470,30 @@ private async Task InitializeObjectsAsync()
else
_logger.Warning("No gameObjects found in {ObjectFileName}", objectFileName);
}

//private async Task InitializeGlidersAsync()
//private async Task InitializeWeaponsAsync()
private async Task InitializeWeaponsAsync()
{
if (!Classes.AllClasses.Any())
throw new InvalidOperationException("Classes must be initialized before weapons");

const string weaponFileName = "weapons.json";
var imageFolderName = Path.Combine(_assetsDirectory.FullName, "Images", "Weapons");
var jsonWeapons = await SerializeAsync<JsonWeapon>(weaponFileName);

foreach (var jsonWeapon in jsonWeapons)
{
var weapon = Weapon.FromJson(jsonWeapon, imageFolderName, jsonWeapon.Rarity, Classes.AllClasses);

_weapons.Add(new Enableable<IWeapon>(weapon));
}

if (LanguageOverrideAvailable())
await MapDisplayNames(weaponFileName, _weapons.ToEnumerable());

if (_weapons.Any())
_categories.Add(Category.CreateForWeapons());
}
//private async Task InitializeCustomAsync()


Expand Down
3 changes: 2 additions & 1 deletion src/GIMI-ModManager.Core/GamesService/IGameService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,9 @@ public interface IGliders : IModdableObject
{
}

public interface IWeapon : IModdableObject
public interface IWeapon : IModdableObject, IRarity
{
public IGameClass GameClass { get; }
}

public interface ICategory : INameable, IEquatable<ICategory>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace GIMI_ModManager.Core.GamesService.JsonModels;

internal class JsonWeapon : JsonBaseModdableObject
{
public int Rarity { get; set; }
public string Type { get; set; } = string.Empty;
}
7 changes: 7 additions & 0 deletions src/GIMI-ModManager.Core/GamesService/Models/Category.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ internal static ICategory CreateForObjects()
return new Category(internalName, ModCategory.Object, "Object", "Objects", typeof(IGameObject));
}

internal static ICategory CreateForWeapons()
{
var internalName = new InternalName("Weapon");

return new Category(internalName, ModCategory.Weapons, "Weapon", "Weapons", typeof(IWeapon));
}

internal static ICategory CreateDefaultCustom()
{
var internalName = new InternalName("Custom");
Expand Down
25 changes: 25 additions & 0 deletions src/GIMI-ModManager.Core/GamesService/Models/Weapon.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using GIMI_ModManager.Core.GamesService.Interfaces;
using GIMI_ModManager.Core.GamesService.JsonModels;

namespace GIMI_ModManager.Core.GamesService.Models;

public class Weapon : BaseModdableObject, IWeapon
{
public int Rarity { get; private init; }
public IGameClass GameClass { get; }

private Weapon(IModdableObject moddableObject, IGameClass gameClass) : base(moddableObject)
{
GameClass = gameClass;
}

internal static IWeapon FromJson(JsonWeapon json, string imageFolder, int rarity,
IEnumerable<IGameClass> gameClasses)
{
var gameClass = gameClasses.FirstOrDefault(x => x.InternalName.Equals(json.Type)) ?? Class.NoneClass();
return new Weapon(FromJson(json, Category.CreateForWeapons(), imageFolder), gameClass)
{
Rarity = rarity
};
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 6c55bf3

Please sign in to comment.