Skip to content

Commit 9715dd9

Browse files
committed
forge support & lots of improvements (well not much but yuh)
1 parent 0b6a982 commit 9715dd9

25 files changed

+704
-254
lines changed

Program.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,20 @@ public static void Main(string[] args)
2828

2929
static async Task Run(string[] args, CancellationToken ct)
3030
{
31-
if (!File.Exists(Context.ModlistPath))
32-
{
33-
throw new ApplicationArgumentsException($"No package.json found");
34-
}
35-
3631
if (args.Length == 0)
3732
{
3833
Help.PrintHelp(null);
3934
return;
4035
}
4136

37+
if (!File.Exists(Context.ModlistPath))
38+
{
39+
Log.Warning($"No package.json found in the current folder. ({Path.GetFullPath(Context.ModlistPath)})");
40+
if (!Log.AskYesNo("Do you want to install it?")) return;
41+
42+
Actions.Install.PerformInstall();
43+
}
44+
4245
switch (args[0])
4346
{
4447
case "update":

Source/Actions/Add.cs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,29 @@ public static async Task PerformAdd(string[] queries, CancellationToken ct)
99
if (Context.Instance.Modlist.Mods.Any(v => v.Id == query) &&
1010
Context.Instance.ModlistLock.Any(v => v.Id == query))
1111
{
12-
Log.Error($"Mod {query} already added");
12+
Log.Error($"Mod {Context.Instance.GetModName(query)} already added");
1313
continue;
1414
}
1515

16-
(string? id, string? name) = await ModrinthUtils.FindModOnline(query, ct);
16+
(string Id, string Name)? v = await ModrinthUtils.FindModOnline(query, ct);
17+
if (!v.HasValue) continue;
18+
string id = v.Value.Id;
1719

18-
if (id is null) continue;
19-
20-
if (Context.Instance.Modlist.Mods.Any(v => v.Id == id) &&
21-
Context.Instance.ModlistLock.Any(v => v.Id == id))
20+
if (Context.Instance.Modlist.Mods.Any(v => v.Id == id))
2221
{
23-
Log.Error($"Mod {name ?? query} already added");
22+
Log.Error($"Mod {v.Value.Name} already added");
2423
continue;
2524
}
2625

26+
if (Context.Instance.ModlistLock.Any(v => v.Id == id))
27+
{
28+
Log.Info($"Mod already installed");
29+
}
30+
2731
Context.Instance.Modlist.Mods.Add(new ModEntry()
2832
{
2933
Id = id,
30-
Name = name,
34+
Name = v.Value.Name,
3135
});
3236
}
3337

Source/Actions/Check.cs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,15 @@ static async Task PrintLockFileErrors(Context context, CancellationToken ct)
3131

3232
if (hash != lockEntry.Hash)
3333
{
34-
Log.Error($"File {Path.GetFileName(file)} checksum mismatched");
34+
Log.Warning($"File {Path.GetFileName(file)} checksum mismatched");
3535
continue;
3636
}
3737
}
3838
}
39+
else
40+
{
41+
Log.Info($"Directory {context.ModsDirectory} does not exists");
42+
}
3943

4044
for (int i = 0; i < context.ModlistLock.Count; i++)
4145
{
@@ -52,6 +56,12 @@ static async Task PrintLockFileErrors(Context context, CancellationToken ct)
5256
}
5357
}
5458

59+
if (context.ModlistLock.Count == 0 &&
60+
!File.Exists(Context.ModlistLockPath))
61+
{
62+
Log.Info($"File {Context.ModlistLockPath} does not exists");
63+
}
64+
5565
progressBar.Dispose();
5666
}
5767

@@ -70,14 +80,13 @@ public static async Task PerformCheck(CancellationToken ct)
7080
{
7181
if (error.Level == DependencyErrorLevel.Depends)
7282
{
73-
(string? id, string? name) = await ModrinthUtils.FindModOnline(error.OtherId, ct);
74-
75-
if (id is null) continue;
83+
(string Id, string Name)? v = await ModrinthUtils.FindModOnline(error.OtherId, ct);
84+
if (!v.HasValue) continue;
7685

7786
Context.Instance.Modlist.Mods.Add(new ModEntry()
7887
{
79-
Id = id,
80-
Name = name,
88+
Id = v.Value.Id,
89+
Name = v.Value.Name,
8190
});
8291
}
8392
}

Source/Actions/Install.cs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
using System.Text.Json;
2+
3+
namespace MMM.Actions;
4+
5+
public static class Install
6+
{
7+
public static void PerformInstall()
8+
{
9+
string loader = "fabric";
10+
Log.Warning($"The loader will be Fabric. I'll implement more loaders in the future.");
11+
string? gameVersion = null;
12+
string? modsFolder = "./mods";
13+
14+
do
15+
{
16+
gameVersion = Log.AskInput("What is the version of Minecraft?", static v =>
17+
{
18+
if (!SemanticVersion.TryParse(v, out _))
19+
{
20+
Log.Error($"Invalid version \"{v}\". It must be a semantic version, like 1.21.5");
21+
return false;
22+
}
23+
24+
return true;
25+
}, gameVersion);
26+
modsFolder = Log.AskInput("Where is the mods folder located?", static v =>
27+
{
28+
v = Path.GetFullPath(Path.Combine(Context.MinecraftPath, v));
29+
30+
if (File.Exists(v))
31+
{
32+
Log.Error($"This is a file. ({v})");
33+
return false;
34+
}
35+
36+
if (Directory.Exists(v) && Directory.EnumerateFileSystemEntries(v).Any())
37+
{
38+
return Log.AskYesNo("The folder isn't empty. Do you want to use it anyway?");
39+
}
40+
41+
return true;
42+
}, modsFolder);
43+
44+
Console.WriteLine($"Minecraft version: {gameVersion}");
45+
Console.WriteLine($"Mods folder: {modsFolder}");
46+
47+
if (Log.AskYesNo("Looks good?", true)) break;
48+
} while (true);
49+
50+
File.WriteAllText(Context.ModlistPath, JsonSerializer.Serialize(new ModList()
51+
{
52+
Loader = loader,
53+
GameVersion = gameVersion,
54+
ModsFolder = modsFolder,
55+
Mods = [],
56+
}, ModListJsonSerializerContext.Default.ModList));
57+
58+
Log.Info($"The package.json was written to {Path.GetFullPath(Context.ModlistPath)}");
59+
}
60+
}

Source/Actions/List.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ namespace MMM.Actions;
22

33
public static class List
44
{
5-
public static Task PerformList(CancellationToken ct) => Task.Run(() =>
5+
public static async Task PerformList(CancellationToken ct)
66
{
77
Log.MajorAction("Reading mods");
88

@@ -11,7 +11,7 @@ public static Task PerformList(CancellationToken ct) => Task.Run(() =>
1111
ModEntry? modEntry = Context.Instance.Modlist.Mods.FirstOrDefault(v => v.Id == lockEntry.Id);
1212
bool isDependency = Context.Instance.ModlistLock.Any(v => v.Dependencies.Contains(lockEntry.Id));
1313

14-
string? name = Context.Instance.GetModName(lockEntry.Id) ?? lockEntry.FileName;
14+
string name = await ModrinthUtils.GetModName(lockEntry.Id, ct);
1515

1616
Log.Write($"{name} ({lockEntry.Id})");
1717

@@ -33,5 +33,5 @@ public static Task PerformList(CancellationToken ct) => Task.Run(() =>
3333

3434
Log.NewLine();
3535
}
36-
}, ct);
36+
}
3737
}

Source/Actions/Remove.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public static async Task PerformRemove(string[] modNames, CancellationToken ct)
3030

3131
foreach ((string modId, ModEntry? mod, ModLock modlock) in toUninstall)
3232
{
33-
string? modName = Context.Instance.GetModName(modId);
33+
string modName = await ModrinthUtils.GetModName(modId, ct);
3434

3535
List<ModLock> usedBy = [
3636
.. Context.Instance.ModlistLock
@@ -40,7 +40,7 @@ .. Context.Instance.ModlistLock
4040

4141
if (usedBy.Count > 0)
4242
{
43-
Log.Error($"Mod {modlock.Name ?? modName} is used by the following mod(s):");
43+
Log.Error($"Mod {modName} is used by the following mod(s):");
4444
foreach (ModLock item in usedBy)
4545
{
4646
Log.None(item.Name ?? item.FileName ?? item.Id);

Source/Actions/Update.cs

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ void AddThese(IEnumerable<string> mods)
3535

3636
ImmutableArray<string> checkThese = [.. checkTheseSet];
3737

38+
List<string> unsupportedModIds = [];
39+
3840
for (int i = 0; i < checkThese.Length; i++)
3941
{
4042
string modId = checkThese[i];
@@ -48,17 +50,7 @@ void AddThese(IEnumerable<string> mods)
4850
}
4951
catch (ModNotSupported e)
5052
{
51-
ModLock? modLock = Context.Instance.ModlistLock.FirstOrDefault(v => v.Id == modId);
52-
if (modLock is not null)
53-
{
54-
string file = Context.Instance.GetModPath(modLock);
55-
unsupportedMods.Add(new ModUninstallInfo()
56-
{
57-
Reason = ModUninstallReason.NotSupported,
58-
LockEntry = modLock,
59-
File = File.Exists(file) ? file : null,
60-
});
61-
}
53+
unsupportedModIds.Add(modId);
6254
Log.Error(e);
6355
continue;
6456
}
@@ -75,6 +67,48 @@ void AddThese(IEnumerable<string> mods)
7567

7668
progressBar.Dispose();
7769

70+
if (unsupportedModIds.Count > 0 && Log.AskYesNo($"Do you want to uninstall {unsupportedModIds.Count} unsupported mods?", true))
71+
{
72+
foreach (string modId in unsupportedModIds)
73+
{
74+
string name = await ModrinthUtils.GetModName(modId, ct);
75+
76+
foreach (ModLock other in Context.Instance.ModlistLock)
77+
{
78+
if (other.Dependencies.Contains(modId))
79+
{
80+
Log.Error($"Mod {name} is unsupported but required by mod {await ModrinthUtils.GetModName(other.Id, ct)}");
81+
}
82+
}
83+
84+
ModEntry? mod = Context.Instance.Modlist.Mods.FirstOrDefault(v => v.Id == modId);
85+
if (mod is not null) Context.Instance.Modlist.Mods.Remove(mod);
86+
87+
ModLock? modLock = Context.Instance.ModlistLock.FirstOrDefault(v => v.Id == modId);
88+
if (modLock is not null)
89+
{
90+
string file = Context.Instance.GetModPath(modLock);
91+
unsupportedMods.Add(new ModUninstallInfo()
92+
{
93+
Reason = ModUninstallReason.NotSupported,
94+
LockEntry = modLock,
95+
File = File.Exists(file) ? file : null,
96+
Name = name,
97+
});
98+
}
99+
else
100+
{
101+
unsupportedMods.Add(new ModUninstallInfo()
102+
{
103+
Reason = ModUninstallReason.NotSupported,
104+
LockEntry = null,
105+
File = null,
106+
Name = name,
107+
});
108+
}
109+
}
110+
}
111+
78112
return new Changes()
79113
{
80114
Install = modUpdates.ToImmutable(),

Source/Change/ModInstallInfo.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ public class ModInstallInfo
88
public required ModLock? LockEntry { get; init; }
99
public required string DownloadFileName { get; init; }
1010
public required ModEntry Mod { get; init; }
11+
public required string Name { get; init; }
1112

1213
public override string ToString() => $"{Mod.Name ?? DownloadFileName}";
1314
}

Source/Change/ModUninstallInfo.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ public class ModUninstallInfo
44
{
55
public required ModUninstallReason Reason { get; init; }
66
public required string? File { get; init; }
7-
public required ModLock LockEntry { get; init; }
7+
public required ModLock? LockEntry { get; init; }
8+
public required string Name { get; init; }
89

9-
public override string ToString() => $"{LockEntry?.Name ?? Path.GetFileName(File)}";
10+
public override string ToString() => $"{Name ?? LockEntry?.Name ?? Path.GetFileName(File)}";
1011
}

Source/Context.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using System.Collections.Immutable;
22
using System.Text.Json;
3-
using MMM.Fabric;
43
using Modrinth;
54

65
namespace MMM;
@@ -14,8 +13,8 @@ public class Context
1413
Environment.CurrentDirectory;
1514
#endif
1615

17-
public static readonly string ModlistPath = Path.Combine(MinecraftPath, "modlist.json");
18-
public static readonly string ModlistLockPath = Path.Combine(MinecraftPath, "modlist-lock.json");
16+
public static readonly string ModlistPath = Path.GetFullPath(Path.Combine(MinecraftPath, "modlist.json"));
17+
public static readonly string ModlistLockPath = Path.GetFullPath(Path.Combine(MinecraftPath, "modlist-lock.json"));
1918

2019
public required ModList Modlist { get; init; }
2120
public required List<ModLock> ModlistLock { get; init; }
@@ -108,11 +107,15 @@ public async Task<ImmutableArray<InstalledMod>> GetMods(CancellationToken ct)
108107
public readonly struct InstalledComponent
109108
{
110109
public required string? FileName { get; init; }
111-
public required GenericComponent Component { get; init; }
110+
public required IMod Component { get; init; }
111+
112+
public override string? ToString() => Component.Name ?? Component.Id ?? FileName;
112113
}
113114

114115
public readonly struct InstalledMod
115116
{
116117
public required string FileName { get; init; }
117-
public required FabricMod Mod { get; init; }
118+
public required IMod Mod { get; init; }
119+
120+
public override string ToString() => Mod.Name ?? Mod.Id ?? FileName;
118121
}

0 commit comments

Comments
 (0)