Fixed diverse issues related to launching the app

This commit is contained in:
MilkBarModding 2025-03-12 20:50:48 -06:00
parent 51a730ea31
commit 82338132d8
10 changed files with 152 additions and 95 deletions

Binary file not shown.

View File

@ -13,7 +13,7 @@ try
#if (DEBUG) #if (DEBUG)
Console.WriteLine("DEV"); Console.WriteLine("DEV");
#else #else
Console.WriteLine("DEV 2.0"); Console.WriteLine("2.0.1");
#endif #endif
Console.WriteLine(); Console.WriteLine();

View File

@ -65,7 +65,22 @@
if (!Directory.Exists(LogsFolder)) if (!Directory.Exists(LogsFolder))
Directory.CreateDirectory(LogsFolder); Directory.CreateDirectory(LogsFolder);
File.Move(LogPath, $"{LogsFolder}\\{creationTime}.txt"); string postName = "";
// The correct way to manage a log file already existing is by creating a differently named log file
if(File.Exists($"{LogsFolder}\\{creationTime}.txt"))
postName = $"({Directory.GetFiles(LogsFolder).Where(file => Path.GetFileNameWithoutExtension(file).StartsWith(creationTime)).Count()})";
if (!File.Exists($"{LogsFolder}\\{creationTime}{postName}.txt"))
{
File.Move(LogPath, $"{LogsFolder}\\{creationTime}{postName}.txt");
}
else
{
// If for some reason, even after naming the file differently, it fails. Here we can delete it.
Console.WriteLine($"Failed to create file at: {LogsFolder}\\{creationTime}{postName}.txt. Deleting it...");
File.Delete(LogPath);
}
} }
File.CreateText(LogPath); File.CreateText(LogPath);
@ -83,15 +98,22 @@
logMutex.WaitOne(100); logMutex.WaitOne(100);
using (StreamWriter LogFile = new StreamWriter(LogPath, true)) try
{ {
LogFile.Write($"[{MessageTime}] {message}"); using (StreamWriter LogFile = new StreamWriter(LogPath, true))
{
LogFile.Write($"[{MessageTime}] {message}");
if (!string.IsNullOrEmpty(details)) if (!string.IsNullOrEmpty(details))
LogFile.Write($" - Details: {details}"); LogFile.Write($" - Details: {details}");
if(newLine) if (newLine)
LogFile.WriteLine(); LogFile.WriteLine();
}
}
catch(Exception ex)
{
WriteToConsole(LogWriteLevelEnum.ERR, "\nCould not write to log file. Please make sure that you don't have another server process and restart your server.", MessageTime, ConsoleColor.DarkRed, true);
} }
logMutex.ReleaseMutex(); logMutex.ReleaseMutex();

View File

@ -117,7 +117,6 @@ namespace Breath_of_the_Wild_Multiplayer.MVVM.ViewModel
this.IngameMenuVM = new IngameMenuModel(); this.IngameMenuVM = new IngameMenuModel();
SharedData.LoadingMessage = new LoadingModel(); SharedData.LoadingMessage = new LoadingModel();
this.disableBackground = false; this.disableBackground = false;
GameFilesModifier.CreateModifiedModel();
currentView = this.MainMenuVM; currentView = this.MainMenuVM;

View File

@ -10,6 +10,7 @@ using Breath_of_the_Wild_Multiplayer.MVVM.Model.DTO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Text; using System.Text;
using System.Xml;
namespace Breath_of_the_Wild_Multiplayer.MVVM.ViewModel namespace Breath_of_the_Wild_Multiplayer.MVVM.ViewModel
{ {
@ -61,10 +62,23 @@ namespace Breath_of_the_Wild_Multiplayer.MVVM.ViewModel
} }
} }
public bool IsModInstalled
{
get
{
string modActorsPack = $@"{BcmlSettings.MergedDir}\Actor\Pack";
// If the directory for the directory doesn't even exist. That is a clear indicator that the mod is not installed
if (!Directory.Exists(modActorsPack))
return false;
// One of the unique assets created by the mod are the actors called JugadorXX.sbactorpack.
// If we don't have any Jugador, that means the mod is not installed.
return Directory.GetFiles(modActorsPack).Any(actor => actor.Contains("Jugador") && Path.GetExtension(actor) == ".sbactorpack");
}
}
private Dictionary<int, LocalServerDTO> ServerMapping; private Dictionary<int, LocalServerDTO> ServerMapping;
private string GameDir;
private string CemuDir;
public List<LocalServerDTO> ServerList; public List<LocalServerDTO> ServerList;
public RelayCommand serverButtonClick { get; set; } public RelayCommand serverButtonClick { get; set; }
@ -79,7 +93,7 @@ namespace Breath_of_the_Wild_Multiplayer.MVVM.ViewModel
{ {
SharedData.ServerBrowser = this; SharedData.ServerBrowser = this;
findCemuData(); //findCemuData();
isMaxOffset = true; isMaxOffset = true;
scrollState = 0; scrollState = 0;
@ -129,13 +143,13 @@ namespace Breath_of_the_Wild_Multiplayer.MVVM.ViewModel
foreach (var server in this.ServerList.Where(sv => sv.Favorite)) foreach (var server in this.ServerList.Where(sv => sv.Favorite))
{ {
serversToShow.Add(new serverDataModel(!string.IsNullOrEmpty(GameDir) && !string.IsNullOrEmpty(CemuDir), name: server.Name, ip: server.IP, port: server.Port, favorite: server.Favorite, password: server.Password)); serversToShow.Add(new serverDataModel(!string.IsNullOrEmpty(BcmlSettings.GameDir) && !string.IsNullOrEmpty(BcmlSettings.CemuDir), name: server.Name, ip: server.IP, port: server.Port, favorite: server.Favorite, password: server.Password));
ServerMapping[serverDataModel.serversAdded - 1] = server; ServerMapping[serverDataModel.serversAdded - 1] = server;
} }
foreach (var server in this.ServerList.Where(sv => !sv.Favorite)) foreach (var server in this.ServerList.Where(sv => !sv.Favorite))
{ {
serversToShow.Add(new serverDataModel(!string.IsNullOrEmpty(GameDir) && !string.IsNullOrEmpty(CemuDir), name: server.Name, ip: server.IP, port: server.Port, favorite: server.Favorite, password: server.Password)); serversToShow.Add(new serverDataModel(!string.IsNullOrEmpty(BcmlSettings.GameDir) && !string.IsNullOrEmpty(BcmlSettings.CemuDir), name: server.Name, ip: server.IP, port: server.Port, favorite: server.Favorite, password: server.Password));
ServerMapping[serverDataModel.serversAdded - 1] = server; ServerMapping[serverDataModel.serversAdded - 1] = server;
} }
@ -143,7 +157,7 @@ namespace Breath_of_the_Wild_Multiplayer.MVVM.ViewModel
if (_serversToShow.Count == 0) if (_serversToShow.Count == 0)
{ {
selectedServer.Add(new serverDataModel(!string.IsNullOrEmpty(GameDir) && !string.IsNullOrEmpty(CemuDir), name: "", ip: "", port: 0, favorite: false, password: "")); selectedServer.Add(new serverDataModel(!string.IsNullOrEmpty(BcmlSettings.GameDir) && !string.IsNullOrEmpty(BcmlSettings.CemuDir), name: "", ip: "", port: 0, favorite: false, password: ""));
} }
else else
{ {
@ -153,21 +167,21 @@ namespace Breath_of_the_Wild_Multiplayer.MVVM.ViewModel
} }
} }
void findCemuData() //void findCemuData()
{ //{
try // try
{ // {
string CemuSettings = File.ReadAllText(Properties.Settings.Default.bcmlLocation); // string CemuSettings = File.ReadAllText(Properties.Settings.Default.bcmlLocation);
Dictionary<string, string> settings = JsonConvert.DeserializeObject<Dictionary<string, string>>(CemuSettings)!; // Dictionary<string, string> settings = JsonConvert.DeserializeObject<Dictionary<string, string>>(CemuSettings)!;
CemuDir = settings["cemu_dir"]; // CemuDir = settings["cemu_dir"];
GameDir = settings["game_dir"]; // GameDir = settings["game_dir"];
} // }
catch(Exception ex) // catch(Exception ex)
{ // {
CemuDir = ""; // CemuDir = "";
GameDir = ""; // GameDir = "";
} // }
} //}
async Task connectToServer(serverDataModel serverToJoin = null) async Task connectToServer(serverDataModel serverToJoin = null)
{ {
@ -176,9 +190,44 @@ namespace Breath_of_the_Wild_Multiplayer.MVVM.ViewModel
if (serverToJoin == null) if (serverToJoin == null)
serverToJoin = _selectedServer[0]; serverToJoin = _selectedServer[0];
if (string.IsNullOrEmpty(GameDir) || string.IsNullOrEmpty(CemuDir)) if (string.IsNullOrEmpty(BcmlSettings.GameDir) || string.IsNullOrEmpty(BcmlSettings.CemuDir))
throw new ApplicationException("Bcml not setup."); throw new ApplicationException("Bcml not setup.");
if (!IsModInstalled)
throw new ApplicationException("Mod is not setup on BCML. Make sure to follow the instructions to install the mod.");
string cemuSettingsPath = Path.Combine(BcmlSettings.CemuDir, "settings.xml");
// Does the settings file for cemu exist?
if (!File.Exists(cemuSettingsPath))
throw new ApplicationException("Cemu settings file doesn't exist. Make sure to have open cemu and setup the graphic packs");
XmlDocument doc = new XmlDocument();
doc.Load(cemuSettingsPath);
XmlNode GraphicPacksNode = doc.DocumentElement.SelectSingleNode("/content/GraphicPack");
Dictionary<string, string> nodesToValidate = new Dictionary<string, string>() {
{" · Utilities", "bcmlPatches\\MilkBarLauncher\\rules.txt"},
{" · Extended Memory", "BreathOfTheWild\\Mods\\ExtendedMemory\\rules.txt" }
};
List<string> missingGraphicPacks = new List<string>();
try
{
missingGraphicPacks = nodesToValidate
.Where(sNode => !GraphicPacksNode.ChildNodes.Cast<XmlNode>().Any(node => node.Attributes.Cast<XmlAttribute>().Any(attribute => attribute.Value.Contains(sNode.Value)))).Select(sNode => sNode.Key).ToList();
}
catch(Exception ex)
{
// If any issue happened while reading settings xml.
throw new ApplicationException("Failed to read cemu graphic packs settings. Please make sure that your cemu is setup correctly.");
}
if(missingGraphicPacks.Any())
throw new ApplicationException("The following needed graphic packs are not selected on Cemu\n\n" + string.Join("\n", missingGraphicPacks) + "\n\nPlease make sure to select them before joining a server.");
if (string.IsNullOrEmpty(serverToJoin.IP) || !serverToJoin.open) if (string.IsNullOrEmpty(serverToJoin.IP) || !serverToJoin.open)
return; return;
@ -196,6 +245,8 @@ namespace Breath_of_the_Wild_Multiplayer.MVVM.ViewModel
SharedData.SetLoadingMessage("Loading player data..."); SharedData.SetLoadingMessage("Loading player data...");
await Task.Run(() => GameFilesModifier.CreateModifiedModel());
await Task.Run(() => GameFilesModifier.ChangeAttentionForJugadores(serverToJoin.playStyle != "Prop hunt")); await Task.Run(() => GameFilesModifier.ChangeAttentionForJugadores(serverToJoin.playStyle != "Prop hunt"));
await Task.Run(() => GameFilesModifier.CleanAnimations()); await Task.Run(() => GameFilesModifier.CleanAnimations());
@ -234,7 +285,7 @@ namespace Breath_of_the_Wild_Multiplayer.MVVM.ViewModel
SharedData.SetLoadingMessage("Starting Cemu..."); SharedData.SetLoadingMessage("Starting Cemu...");
await Task.Run(() => Process.Start($"{CemuDir}/cemu.exe", $"-g \"{GameDir.Replace("content", "code")}/U-King.rpx\"")); await Task.Run(() => Process.Start($"{BcmlSettings.CemuDir}/cemu.exe", $"-g \"{BcmlSettings.GameDir.Replace("content", "code")}/U-King.rpx\""));
await Task.Delay(500); await Task.Delay(500);
@ -329,7 +380,7 @@ namespace Breath_of_the_Wild_Multiplayer.MVVM.ViewModel
this.ServerList.Add(serverToAdd); this.ServerList.Add(serverToAdd);
this.serversToShow.Add(new serverDataModel(!string.IsNullOrEmpty(GameDir) && !string.IsNullOrEmpty(CemuDir), name: serverinfo.name, ip: serverinfo.ip, port: Int32.Parse(serverinfo.port), favorite: false, password: serverinfo.password)); this.serversToShow.Add(new serverDataModel(!string.IsNullOrEmpty(BcmlSettings.GameDir) && !string.IsNullOrEmpty(BcmlSettings.CemuDir), name: serverinfo.name, ip: serverinfo.ip, port: Int32.Parse(serverinfo.port), favorite: false, password: serverinfo.password));
this.ServerMapping[serverDataModel.serversAdded - 1] = serverToAdd; this.ServerMapping[serverDataModel.serversAdded - 1] = serverToAdd;
changeSelected(this._serversToShow.Count - 1); changeSelected(this._serversToShow.Count - 1);
@ -337,7 +388,7 @@ namespace Breath_of_the_Wild_Multiplayer.MVVM.ViewModel
} }
else if(serverinfo.serverIndex == -2) else if(serverinfo.serverIndex == -2)
{ {
serverDataModel serverToconnect = new serverDataModel(!string.IsNullOrEmpty(GameDir) && !string.IsNullOrEmpty(CemuDir), name: serverinfo.name, ip: serverinfo.ip, port: Int32.Parse(serverinfo.port), favorite: false, password: serverinfo.password, async: false); serverDataModel serverToconnect = new serverDataModel(!string.IsNullOrEmpty(BcmlSettings.GameDir) && !string.IsNullOrEmpty(BcmlSettings.CemuDir), name: serverinfo.name, ip: serverinfo.ip, port: Int32.Parse(serverinfo.port), favorite: false, password: serverinfo.password, async: false);
if (!serverToconnect.open) if (!serverToconnect.open)
throw new Exception("Could not connect to server. Check if the server is open."); throw new Exception("Could not connect to server. Check if the server is open.");

View File

@ -0,0 +1,23 @@
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
namespace Breath_of_the_Wild_Multiplayer.Source_files
{
public static class BcmlSettings
{
public static string GameDir { get => getSetting("game_dir"); }
public static string UpdateDir { get => getSetting("update_dir"); }
public static string CemuDir { get => getSetting("cemu_dir"); }
public static string MergedDir { get => @$"{getSetting("store_dir")}\merged\content"; }
private static string getSetting(string setting)
{
if (!File.Exists(Properties.Settings.Default.bcmlLocation))
return null;
string CemuSettings = File.ReadAllText(Properties.Settings.Default.bcmlLocation);
return JsonConvert.DeserializeObject<Dictionary<string, string>>(CemuSettings)![setting];
}
}
}

View File

@ -30,14 +30,11 @@ namespace Breath_of_the_Wild_Multiplayer.Source_files
public static void ChangeAttentionForJugadores(bool enabled) public static void ChangeAttentionForJugadores(bool enabled)
{ {
// Get bcml mod path to save data in that folder
string bcmlPath = Properties.Settings.Default.bcmlLocation.Replace("settings.json", @"merged\content");
List<Tuple<ISarcFile, AampLibAction>> filesToModify = new List<Tuple<ISarcFile, AampLibAction>>(); List<Tuple<ISarcFile, AampLibAction>> filesToModify = new List<Tuple<ISarcFile, AampLibAction>>();
List<ActorPack> jugadores = new List<ActorPack>(); List<ActorPack> jugadores = new List<ActorPack>();
foreach (string path in Directory.GetFiles(@$"{bcmlPath}\Actor\Pack\").Where(file => Path.GetFileName(file).StartsWith("Jugador"))) foreach (string path in Directory.GetFiles(@$"{BcmlSettings.MergedDir}\Actor\Pack\").Where(file => Path.GetFileName(file).StartsWith("Jugador")))
{ {
ActorPack jugador = new ActorPack(path); ActorPack jugador = new ActorPack(path);
ActorLink actorLinkFile = jugador.ActorLink.Files()[0]; ActorLink actorLinkFile = jugador.ActorLink.Files()[0];
@ -60,15 +57,9 @@ namespace Breath_of_the_Wild_Multiplayer.Source_files
Stopwatch stopwatch = Stopwatch.StartNew(); Stopwatch stopwatch = Stopwatch.StartNew();
/* Obtaining the data */ /* Obtaining the data */
// Get game folders so that we can extract the armors and files
string CemuSettings = File.ReadAllText(Properties.Settings.Default.bcmlLocation);
Dictionary<string, string> settings = JsonConvert.DeserializeObject<Dictionary<string, string>>(CemuSettings)!;
string GameDir = settings["game_dir"];
string UpdateDir = settings["update_dir"];
// Get bcml mod path to save data in that folder // Get bcml mod path to save data in that folder
string bcmlPath = Properties.Settings.Default.bcmlLocation.Replace("settings.json", @"merged\content"); string bcmlPath = Properties.Settings.Default.bcmlLocation.Replace("settings.json", @"merged\content");
string titleBGPath = @$"{UpdateDir}\Pack\TitleBG.pack"; string titleBGPath = @$"{BcmlSettings.UpdateDir}\Pack\TitleBG.pack";
/* Instantiate objects */ /* Instantiate objects */
// Create title bg object and load it's data // Create title bg object and load it's data
@ -78,7 +69,7 @@ namespace Breath_of_the_Wild_Multiplayer.Source_files
List<Model> totalModels = new List<Model>(); List<Model> totalModels = new List<Model>();
/* Get armor models */ /* Get armor models */
foreach (string path in Directory.GetFiles(@$"{UpdateDir}\Model\").Where(file => Path.GetFileName(file).StartsWith("Armor_") && !file.Contains("Tex"))) foreach (string path in Directory.GetFiles(@$"{BcmlSettings.UpdateDir}\Model\").Where(file => Path.GetFileName(file).StartsWith("Armor_") && !file.Contains("Tex")))
{ {
BfresFile armorFile = new BfresFile(new MemoryStream(Yaz0.Decompress(File.ReadAllBytes(path)))); BfresFile armorFile = new BfresFile(new MemoryStream(Yaz0.Decompress(File.ReadAllBytes(path))));
@ -140,15 +131,7 @@ namespace Breath_of_the_Wild_Multiplayer.Source_files
public static void CreateModifiedModel() public static void CreateModifiedModel()
{ {
/* Obtaining the data */ /* Obtaining the data */
// Get game folders so that we can extract the armors and files string titleBGPath = @$"{BcmlSettings.UpdateDir}\Pack\TitleBG.pack";
string CemuSettings = File.ReadAllText(Properties.Settings.Default.bcmlLocation);
Dictionary<string, string> settings = JsonConvert.DeserializeObject<Dictionary<string, string>>(CemuSettings)!;
string GameDir = settings["game_dir"];
string UpdateDir = settings["update_dir"];
// Get bcml mod path to save data in that folder
string bcmlPath = Properties.Settings.Default.bcmlLocation.Replace("settings.json", @"merged\content");
string titleBGPath = @$"{UpdateDir}\Pack\TitleBG.pack";
/* Instantiate objects */ /* Instantiate objects */
// Create title bg object and load it's data // Create title bg object and load it's data
@ -158,7 +141,7 @@ namespace Breath_of_the_Wild_Multiplayer.Source_files
/************ Player model ************/ /************ Player model ************/
/* Modify Link models */ /* Modify Link models */
// Create outputModel // Create outputModel
if(!File.Exists($@"{bcmlPath}/Model/Jugador1ModelNameLongForASpecificReason.sbfres")) if(!File.Exists($@"{BcmlSettings.MergedDir}/Model/Jugador1ModelNameLongForASpecificReason.sbfres"))
{ {
byte[] LinkDecompressed = Yaz0.Decompress(titleBG.LoadedData["Model/Link.sbfres"].ToArray()); byte[] LinkDecompressed = Yaz0.Decompress(titleBG.LoadedData["Model/Link.sbfres"].ToArray());
BfresFile outputModel = new BfresFile(new MemoryStream(LinkDecompressed)); BfresFile outputModel = new BfresFile(new MemoryStream(LinkDecompressed));
@ -184,7 +167,7 @@ namespace Breath_of_the_Wild_Multiplayer.Source_files
outputModel.Models[2].Shapes.Clear(); outputModel.Models[2].Shapes.Clear();
/* Get armor models */ /* Get armor models */
foreach (string path in Directory.GetFiles(@$"{UpdateDir}\Model\").Where(file => Path.GetFileName(file).StartsWith("Armor_") && !file.Contains("Tex"))) foreach (string path in Directory.GetFiles(@$"{BcmlSettings.UpdateDir}\Model\").Where(file => Path.GetFileName(file).StartsWith("Armor_") && !file.Contains("Tex")))
{ {
BfresFile armorFile = new BfresFile(new MemoryStream(Yaz0.Decompress(File.ReadAllBytes(path)))); BfresFile armorFile = new BfresFile(new MemoryStream(Yaz0.Decompress(File.ReadAllBytes(path))));
@ -211,18 +194,18 @@ namespace Breath_of_the_Wild_Multiplayer.Source_files
outputModel.ToBinary(ms); outputModel.ToBinary(ms);
} }
File.WriteAllBytes($@"{bcmlPath}/Model/Jugador1ModelNameLongForASpecificReason.sbfres", Yaz0.Compress(ms.ToArray()).ToArray()); File.WriteAllBytes($@"{BcmlSettings.MergedDir}/Model/Jugador1ModelNameLongForASpecificReason.sbfres", Yaz0.Compress(ms.ToArray()).ToArray());
} }
/************ Player textures ************/ /************ Player textures ************/
/* Modify Link's tex1 file */ /* Modify Link's tex1 file */
if(!File.Exists($@"{bcmlPath}/Model/Jugador1ModelNameLongForASpecificReason.Tex1.sbfres")) if(!File.Exists($@"{BcmlSettings.MergedDir}/Model/Jugador1ModelNameLongForASpecificReason.Tex1.sbfres"))
{ {
byte[] LinkDecompressed = Yaz0.Decompress(File.ReadAllBytes($@"{GameDir}\Model\Link.Tex1.sbfres")); byte[] LinkDecompressed = Yaz0.Decompress(File.ReadAllBytes($@"{BcmlSettings.GameDir}\Model\Link.Tex1.sbfres"));
BfresFile outputTexture = new BfresFile(new MemoryStream(LinkDecompressed)); BfresFile outputTexture = new BfresFile(new MemoryStream(LinkDecompressed));
/* Get armor models from game dir*/ /* Get armor models from game dir*/
foreach (string path in Directory.GetFiles(@$"{GameDir}\Model\").Where(file => Path.GetFileName(file).StartsWith("Armor_") && file.Contains("Tex1"))) foreach (string path in Directory.GetFiles(@$"{BcmlSettings.GameDir}\Model\").Where(file => Path.GetFileName(file).StartsWith("Armor_") && file.Contains("Tex1")))
{ {
BfresFile armorFile = new BfresFile(new MemoryStream(Yaz0.Decompress(File.ReadAllBytes(path)))); BfresFile armorFile = new BfresFile(new MemoryStream(Yaz0.Decompress(File.ReadAllBytes(path))));
@ -233,7 +216,7 @@ namespace Breath_of_the_Wild_Multiplayer.Source_files
} }
/* Get armor models from update dir*/ /* Get armor models from update dir*/
foreach (string path in Directory.GetFiles(@$"{UpdateDir}\Model\").Where(file => Path.GetFileName(file).StartsWith("Armor_") && file.Contains("Tex1"))) foreach (string path in Directory.GetFiles(@$"{BcmlSettings.UpdateDir}\Model\").Where(file => Path.GetFileName(file).StartsWith("Armor_") && file.Contains("Tex1")))
{ {
BfresFile armorFile = new BfresFile(new MemoryStream(Yaz0.Decompress(File.ReadAllBytes(path)))); BfresFile armorFile = new BfresFile(new MemoryStream(Yaz0.Decompress(File.ReadAllBytes(path))));
@ -250,17 +233,17 @@ namespace Breath_of_the_Wild_Multiplayer.Source_files
outputTexture.ToBinary(ms); outputTexture.ToBinary(ms);
} }
File.WriteAllBytes($@"{bcmlPath}/Model/Jugador1ModelNameLongForASpecificReason.Tex1.sbfres", Yaz0.Compress(ms.ToArray()).ToArray()); File.WriteAllBytes($@"{BcmlSettings.MergedDir}/Model/Jugador1ModelNameLongForASpecificReason.Tex1.sbfres", Yaz0.Compress(ms.ToArray()).ToArray());
} }
/* Modify Link's tex2 file */ /* Modify Link's tex2 file */
if (!File.Exists($@"{bcmlPath}/Model/Jugador1ModelNameLongForASpecificReason.Tex2.sbfres")) if (!File.Exists($@"{BcmlSettings.MergedDir}/Model/Jugador1ModelNameLongForASpecificReason.Tex2.sbfres"))
{ {
byte[] LinkDecompressed = Yaz0.Decompress(titleBG.LoadedData["Model/Link.Tex2.sbfres"].ToArray()); byte[] LinkDecompressed = Yaz0.Decompress(titleBG.LoadedData["Model/Link.Tex2.sbfres"].ToArray());
BfresFile outputTexture = new BfresFile(new MemoryStream(LinkDecompressed)); BfresFile outputTexture = new BfresFile(new MemoryStream(LinkDecompressed));
/* Get armor models */ /* Get armor models */
foreach (string path in Directory.GetFiles(@$"{UpdateDir}\Model\").Where(file => Path.GetFileName(file).StartsWith("Armor_") && file.Contains("Tex2"))) foreach (string path in Directory.GetFiles(@$"{BcmlSettings.UpdateDir}\Model\").Where(file => Path.GetFileName(file).StartsWith("Armor_") && file.Contains("Tex2")))
{ {
BfresFile armorFile = new BfresFile(new MemoryStream(Yaz0.Decompress(File.ReadAllBytes(path)))); BfresFile armorFile = new BfresFile(new MemoryStream(Yaz0.Decompress(File.ReadAllBytes(path))));
@ -285,7 +268,7 @@ namespace Breath_of_the_Wild_Multiplayer.Source_files
outputTexture.ToBinary(ms); outputTexture.ToBinary(ms);
} }
File.WriteAllBytes($@"{bcmlPath}/Model/Jugador1ModelNameLongForASpecificReason.Tex2.sbfres", Yaz0.Compress(ms.ToArray()).ToArray()); File.WriteAllBytes($@"{BcmlSettings.MergedDir}/Model/Jugador1ModelNameLongForASpecificReason.Tex2.sbfres", Yaz0.Compress(ms.ToArray()).ToArray());
} }
} }
@ -335,17 +318,10 @@ namespace Breath_of_the_Wild_Multiplayer.Source_files
public static void CleanAnimations() public static void CleanAnimations()
{ {
/* Obtaining the data */ /* Obtaining the data */
// Get game folders so that we can extract the armors and files
string CemuSettings = File.ReadAllText(Properties.Settings.Default.bcmlLocation);
Dictionary<string, string> settings = JsonConvert.DeserializeObject<Dictionary<string, string>>(CemuSettings)!;
string GameDir = settings["game_dir"];
// Get bcml mod path to save data in that folder if (!File.Exists($@"{BcmlSettings.MergedDir}/Model/Player_Animation_NoFace.sbfres"))
string bcmlPath = Properties.Settings.Default.bcmlLocation.Replace("settings.json", @"merged\content");
if (!File.Exists($@"{bcmlPath}/Model/Player_Animation_NoFace.sbfres"))
{ {
var res = new BfresFile(new MemoryStream(Yaz0.Decompress(File.ReadAllBytes($@"{GameDir}\Model\Player_Animation.sbfres")))); var res = new BfresFile(new MemoryStream(Yaz0.Decompress(File.ReadAllBytes($@"{BcmlSettings.GameDir}\Model\Player_Animation.sbfres"))));
res.Name = "Player_Animation_NoFace"; res.Name = "Player_Animation_NoFace";
List<string> bannedBones = new List<string>() { List<string> bannedBones = new List<string>() {
@ -372,31 +348,15 @@ namespace Breath_of_the_Wild_Multiplayer.Source_files
res.ToBinary(ms); res.ToBinary(ms);
} }
File.WriteAllBytes($@"{bcmlPath}/Model/Player_Animation_NoFace.sbfres", Yaz0.Compress(ms.ToArray()).ToArray()); File.WriteAllBytes($@"{BcmlSettings.MergedDir}/Model/Player_Animation_NoFace.sbfres", Yaz0.Compress(ms.ToArray()).ToArray());
} }
} }
public static void WrapperTests()
{
//string bcmlPath = Properties.Settings.Default.bcmlLocation.Replace("settings.json", "merged\\content");
//string titleBGPath = $"{bcmlPath}\\Pack\\TitleBG.pack";
//TitleBG titleBG = new TitleBG(titleBGPath);
//ActorPack gameRomPlayer = titleBG.Actor.Pack.Actors.File("GameROMPlayer");
//gameRomPlayer.ModelList.File("Player_Link").LoadedData.ModifyModel("TestNew", "Link");
//gameRomPlayer.ASList.File("Player").LoadedData.ModifyAnimation(true);
//titleBG.Save(true);
}
public static void ModifyGameROMPlayerModel(string folder, string model, bool isNotLink, string bumiiPath = null) public static void ModifyGameROMPlayerModel(string folder, string model, bool isNotLink, string bumiiPath = null)
{ {
List<Tuple<ISarcFile, AampLibAction>> filesToModify = new List<Tuple<ISarcFile, AampLibAction>>(); List<Tuple<ISarcFile, AampLibAction>> filesToModify = new List<Tuple<ISarcFile, AampLibAction>>();
string bcmlPath = Properties.Settings.Default.bcmlLocation.Replace("settings.json", @"merged\content"); string titleBGPath = @$"{BcmlSettings.MergedDir}\Pack\TitleBG.pack";
string titleBGPath = @$"{bcmlPath}\Pack\TitleBG.pack";
TitleBG titleBG = new TitleBG(titleBGPath); TitleBG titleBG = new TitleBG(titleBGPath);
ActorPack gameRomPlayer = titleBG.Actor.Pack.Actors.File("GameROMPlayer"); ActorPack gameRomPlayer = titleBG.Actor.Pack.Actors.File("GameROMPlayer");
@ -426,13 +386,13 @@ namespace Breath_of_the_Wild_Multiplayer.Source_files
filesToModify.Add(titleBG.Actor.Pack.Actors.File("Armor_Default_Extra_00").ModelList.Files()[0].ModifyModel(armorFolder, armorModelBase.Replace("##", "00"))); filesToModify.Add(titleBG.Actor.Pack.Actors.File("Armor_Default_Extra_00").ModelList.Files()[0].ModifyModel(armorFolder, armorModelBase.Replace("##", "00")));
filesToModify.Add(titleBG.Actor.Pack.Actors.File("Armor_Default_Extra_01").ModelList.Files()[0].ModifyModel(armorFolder, armorModelBase.Replace("##", "01"))); filesToModify.Add(titleBG.Actor.Pack.Actors.File("Armor_Default_Extra_01").ModelList.Files()[0].ModifyModel(armorFolder, armorModelBase.Replace("##", "01")));
ActorPack pauseMenuActor = new ActorPack(@$"{bcmlPath}\Actor\Pack\PauseMenuPlayer.sbactorpack"); ActorPack pauseMenuActor = new ActorPack(@$"{BcmlSettings.MergedDir}\Actor\Pack\PauseMenuPlayer.sbactorpack");
filesToModify.Add(pauseMenuActor.ModelList.Files()[0].ModifyModel(folder, model)); filesToModify.Add(pauseMenuActor.ModelList.Files()[0].ModifyModel(folder, model));
filesToModify.Add(pauseMenuActor.ASList.Files()[0].ModifyAnimation(isNotLink)); filesToModify.Add(pauseMenuActor.ASList.Files()[0].ModifyAnimation(isNotLink));
List<ActorPack> armors = new List<ActorPack>(); List<ActorPack> armors = new List<ActorPack>();
foreach (string path in Directory.GetFiles(@$"{bcmlPath}\Actor\Pack\").Where(file => Path.GetFileName(file).StartsWith("Armor_"))) foreach (string path in Directory.GetFiles(@$"{BcmlSettings.MergedDir}\Actor\Pack\").Where(file => Path.GetFileName(file).StartsWith("Armor_")))
{ {
ActorPack armorActor = new ActorPack(path); ActorPack armorActor = new ActorPack(path);
ModelList modelListFile = armorActor.ModelList.Files()[0]; ModelList modelListFile = armorActor.ModelList.Files()[0];

View File

@ -2,6 +2,8 @@ import subprocess
from shutil import copy, rmtree, copytree from shutil import copy, rmtree, copytree
import os import os
# Make sure to have msbuild in your PATH
abovePath = "\\".join(os.getcwd().split("\\")[:-1]) abovePath = "\\".join(os.getcwd().split("\\")[:-1])
WPFProject = r"WPF .NET 6\Breath of the Wild Multiplayer" WPFProject = r"WPF .NET 6\Breath of the Wild Multiplayer"