2 Commits
1.2.0 ... main

Author SHA1 Message Date
mikx
2b8b3fc74e readme update 2025-10-23 19:20:32 -04:00
mikx
54ec385800 1.3.0 (Generator Energy/Biiofuel Modding) 2025-10-22 19:42:04 -04:00
2 changed files with 222 additions and 143 deletions

View File

@@ -6,55 +6,95 @@ using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace Jsarus
{
internal class Program
{
public static string version = "1.2.0";
public static string version = "1.3.0";
public static string cd = Directory.GetCurrentDirectory();
public static Process p = new Process();
private static ConsoleKeyInfo keyInfo;
static void Main(string[] args)
{
WebClient wc = new WebClient();
Message.Splash("Jsarus", "mikx");
Message.CMW("Creating directories...", true, 1);
if (!Directory.Exists($@"Data\Modded")) { Directory.CreateDirectory($@"Data\Modded"); }
if (!Directory.Exists($@"Data\Modded\data")) { Directory.CreateDirectory($@"Data\Modded\data"); }
Message.CMW("Preparing variables...",true,1);
Message.CMW("Preparing variables...", true, 1);
JObject settings = JObject.Parse(File.ReadAllText("settings.json"));
string ModName = settings["ModName"].ToObject<string>();
string GameContentPath = settings["GameContentPath"].ToObject<string>();
bool KeepData = settings["KeepData"].ToObject<bool>();
string[] CopyList = settings["CopyList"].ToObject<string[]>();
int ItemWeight = settings["D_Itemable"]["ItemWeight"].ToObject<int>();
int ItemStack = settings["D_Itemable"]["ItemStack"].ToObject<int>();
if (!File.Exists("data.json")) { wc.DownloadFile("https://mxio.ovh/icarus/jsarus/data.json", "data.json"); }
int ExperienceMultiplier = settings["D_ExperienceEvents"]["ExperienceMultiplier"].ToObject<int>();
JObject data = JObject.Parse(File.ReadAllText("data.json"));
int DataVersion = data["version"].ToObject<int>();
JObject dataRemote = JObject.Parse(wc.DownloadString("https://mxio.ovh/icarus/jsarus/data.json"));
int DataVersionRemote = dataRemote["version"].ToObject<int>();
string[] ActionList = settings["D_StaminaActionCosts"]["ActionList"].ToObject<string>().Split('|');
int DivideCostPer = settings["D_StaminaActionCosts"]["DivideCostPer"].ToObject<int>();
if (KeepData)
{
Message.CMW("Keeping your custom data.", true, 1);
if (DataVersion < DataVersionRemote)
{
Message.CMW("Consider setting \"KeepData\" to \"true\" in your \"settings.json\"!", true, 1);
Message.CMW("Your data is outdated. Should we update it? (y/n)", true, 3);
Message.CMW("If you are not sure, answer \"y\".", true, 1);
keyInfo = Console.ReadKey(true);
if (keyInfo.Key == ConsoleKey.Y)
{
Message.CMW("Getting the latest data...", true, 1);
if (File.Exists("data.json")) { File.Copy("data.json", "data.backup.json", true); }
Message.CMW("A backup has been made to \"data.backup.json\".", true, 1);
wc.DownloadFile("https://mxio.ovh/icarus/jsarus/data.json", "data.json");
}
}
}
else
{
Message.CMW("Getting the latest data...", true, 1);
wc.DownloadFile("https://mxio.ovh/icarus/jsarus/data.json", "data.json");
}
string[] PickList = settings["D_ToolDamage"]["PickList"].ToObject<string>().Split('|');
string[] PickEfficiencyList = settings["D_ToolDamage"]["PickEfficiencyList"].ToObject<string>().Split('|');
int ItemWeight = data["D_Itemable"]["ItemWeight"].ToObject<int>();
int ItemStack = data["D_Itemable"]["ItemStack"].ToObject<int>();
string[] AxeList = settings["D_ToolDamage"]["AxeList"].ToObject<string>().Split('|');
string[] AxeEfficiencyList = settings["D_ToolDamage"]["AxeEfficiencyList"].ToObject<string>().Split('|');
int ExperienceMultiplier = data["D_ExperienceEvents"]["ExperienceMultiplier"].ToObject<int>();
string[] RecipeListOre = settings["D_ProcessorRecipes"]["RecipeListOre"].ToObject<string>().Split('|');
string[] RecipeList = settings["D_ProcessorRecipes"]["RecipeList"].ToObject<string>().Split('|');
string[] RecipeListStack = settings["D_ProcessorRecipes"]["RecipeListStack"].ToObject<string>().Split('|');
int RequiredMillijoules = settings["D_ProcessorRecipes"]["RequiredMillijoules"].ToObject<int>();
int RequiredAmount = settings["D_ProcessorRecipes"]["RequiredAmount"].ToObject<int>();
int CraftedAmount = settings["D_ProcessorRecipes"]["CraftedAmount"].ToObject<int>();
string[] ActionList = data["D_StaminaActionCosts"]["ActionList"].ToObject<string>().Split('|');
int DivideCostPer = data["D_StaminaActionCosts"]["DivideCostPer"].ToObject<int>();
string[] InventoryList = settings["D_InventoryInfo"]["InventoryList"].ToObject<string>().Split('|');
int InventorySize = settings["D_InventoryInfo"]["InventorySize"].ToObject<int>();
string[] PickList = data["D_ToolDamage"]["PickList"].ToObject<string>().Split('|');
string[] PickEfficiencyList = data["D_ToolDamage"]["PickEfficiencyList"].ToObject<string>().Split('|');
string[] supportedJson = { @"Traits\D_Itemable.json", @"Experience\D_ExperienceEvents.json", @"Tools\D_StaminaActionCosts.json", @"Tools\D_ToolDamage.json", @"Crafting\D_ProcessorRecipes.json", @"Inventory\D_InventoryInfo.json" };
string[] AxeList = data["D_ToolDamage"]["AxeList"].ToObject<string>().Split('|');
string[] AxeEfficiencyList = data["D_ToolDamage"]["AxeEfficiencyList"].ToObject<string>().Split('|');
string[] RecipeListOre = data["D_ProcessorRecipes"]["RecipeListOre"].ToObject<string>().Split('|');
string[] RecipeList = data["D_ProcessorRecipes"]["RecipeList"].ToObject<string>().Split('|');
string[] RecipeListStack = data["D_ProcessorRecipes"]["RecipeListStack"].ToObject<string>().Split('|');
int RequiredMillijoules = data["D_ProcessorRecipes"]["RequiredMillijoules"].ToObject<int>();
int RequiredAmount = data["D_ProcessorRecipes"]["RequiredAmount"].ToObject<int>();
int CraftedAmount = data["D_ProcessorRecipes"]["CraftedAmount"].ToObject<int>();
string[] InventoryList = data["D_InventoryInfo"]["InventoryList"].ToObject<string>().Split('|');
int InventorySize = data["D_InventoryInfo"]["InventorySize"].ToObject<int>();
string[] GeneratorList = data["D_Generator"]["GeneratorList"].ToObject<string>().Split('|');
int GenerationRate = data["D_Generator"]["GenerationRate"].ToObject<int>();
int GenerationRatio = data["D_Generator"]["GenerationRatio"].ToObject<int>();
string[] supportedJson = { @"Traits\D_Itemable.json", @"Experience\D_ExperienceEvents.json", @"Tools\D_StaminaActionCosts.json", @"Tools\D_ToolDamage.json", @"Crafting\D_ProcessorRecipes.json", @"Inventory\D_InventoryInfo.json", @"Traits\D_Generator.json" };
var dir = Directory.GetDirectories(@"Data\Vanilla");
@@ -75,153 +115,191 @@ namespace Jsarus
Message.CMW($"Copied {sj.Split('\\')[1]}.", true, 2);
}
Message.CMW($"We extracted the data, should we continue and mod it? (y/n)", true, 1);
ConsoleKeyInfo keyInfo = Console.ReadKey(true);
if (keyInfo.Key == ConsoleKey.N) { return; } else
foreach (var d in dir)
{
var json = Directory.GetFiles(d);
foreach (var file in json)
Message.CMW("Generating the Item Database for dynamic modding...", true, 1);
JArray itemsDB = new JArray();
JObject items = new JObject();
JObject item = JObject.Parse(File.ReadAllText(@"Data\Vanilla\Traits\D_Itemable.json"));
foreach (var i in item["Rows"])
{
string iname = i["Name"].ToObject<string>().Substring(5);
int iweight = 0;
if (i["Weight"] != null) { iweight = i["Weight"].ToObject<int>(); } else { iweight = 0; }
bool istack = false;
int istacksize = 1;
if (i["MaxStack"] != null) { istack = true; istacksize = i["MaxStack"].ToObject<int>(); }
items = new JObject()
{
string f = Path.GetFileName(file);
Message.CMW($"Processing {f}...", true, 1);
JObject job = JObject.Parse(File.ReadAllText(file));
switch (f)
{
case "D_Itemable.json":
foreach (var r in job["Rows"])
{ "name", iname },
{ "weight", iweight },
{ "dostack", istack },
{ "stack", istacksize }
};
itemsDB.Add(items);
}
var rawDB = JsonConvert.SerializeObject(itemsDB, Formatting.Indented);
File.WriteAllText($@"Data/itemDB.json", rawDB);
foreach (var d in dir)
{
var json = Directory.GetFiles(d);
foreach (var file in json)
{
string f = Path.GetFileName(file);
Message.CMW($"Processing {f}...", true, 1);
JObject job = JObject.Parse(File.ReadAllText(file));
switch (f)
{
case "D_Itemable.json":
foreach (var r in job["Rows"])
{
r["Name"] = r["Name"].ToObject<string>();
r["DisplayName"] = r["DisplayName"].ToObject<string>();
if (r["Icon"] != null)
{
r["Name"] = r["Name"].ToObject<string>();
r["DisplayName"] = r["DisplayName"].ToObject<string>();
if (r["Icon"] != null)
r["Icon"] = r["Icon"].ToObject<string>();
}
if (r["Description"] != null)
{
r["Description"] = r["Description"].ToObject<string>();
}
if (r["FlavorText"] != null)
{
r["FlavorText"] = r["FlavorText"].ToObject<string>();
}
r["Weight"] = ItemWeight;
if (r["MaxStack"] != null)
{
r["MaxStack"] = ItemStack;
}
}
break;
case "D_ExperienceEvents.json":
foreach (var r in job["Rows"])
{
r["Name"] = r["Name"].ToObject<string>();
if (r["EventDescription"] != null)
{
r["EventDescription"] = r["EventDescription"].ToObject<string>();
}
if (r["SharedExperience"] != null)
{
r["SharedExperience"] = r["SharedExperience"].ToObject<bool>();
}
if (r["ExperienceGranted"] != null)
{
r["ExperienceGranted"] = r["ExperienceGranted"].ToObject<int>() * ExperienceMultiplier;
}
}
break;
case "D_StaminaActionCosts.json":
foreach (var r in job["Rows"])
{
if (ActionList.Contains(r["Name"].ToString()))
{
if (r["PerSecondCost"] != null)
{
r["Icon"] = r["Icon"].ToObject<string>();
r["PerSecondCost"] = r["PerSecondCost"].ToObject<int>() / DivideCostPer;
}
if (r["Description"] != null)
if (r["BeginActionCost"] != null)
{
r["Description"] = r["Description"].ToObject<string>();
}
if (r["FlavorText"] != null)
{
r["FlavorText"] = r["FlavorText"].ToObject<string>();
}
r["Weight"] = ItemWeight;
if (r["MaxStack"] != null)
{
r["MaxStack"] = ItemStack;
r["BeginActionCost"] = r["BeginActionCost"].ToObject<int>() / DivideCostPer;
}
}
break;
}
break;
case "D_ExperienceEvents.json":
foreach (var r in job["Rows"])
case "D_ToolDamage.json":
foreach (var r in job["Rows"])
{
if (PickList.Contains(r["Name"].ToString()))
{
r["Name"] = r["Name"].ToObject<string>();
if (r["EventDescription"] != null)
{
r["EventDescription"] = r["EventDescription"].ToObject<string>();
}
if (r["SharedExperience"] != null)
{
r["SharedExperience"] = r["SharedExperience"].ToObject<bool>();
}
if (r["ExperienceGranted"] != null)
{
r["ExperienceGranted"] = r["ExperienceGranted"].ToObject<int>() * ExperienceMultiplier;
}
int index = Array.IndexOf(PickList, r["Name"].ToString());
r["Mining_Efficiency"] = PickEfficiencyList[index];
}
break;
case "D_StaminaActionCosts.json":
foreach (var r in job["Rows"])
if (AxeList.Contains(r["Name"].ToString()))
{
if(ActionList.Contains(r["Name"].ToString()))
int index = Array.IndexOf(AxeList, r["Name"].ToString());
r["Felling_Efficiency"] = AxeEfficiencyList[index];
}
}
break;
case "D_ProcessorRecipes.json":
JArray itemDB = JArray.Parse(File.ReadAllText(@"Data\itemDB.json"));
foreach (var r in job["Rows"])
{
//JToken entry = itemDB.FirstOrDefault(t => (bool)(t["name"]?.ToString().Contains(r["Name"]?.ToString())));
if (r["Inputs"].Count() > 0)
{
if (RecipeListOre.Contains(r["Name"].ToString()))
{
if (r["PerSecondCost"] != null)
if (r["RequiredMillijoules"] != null)
{
r["PerSecondCost"] = r["PerSecondCost"].ToObject<int>() / DivideCostPer;
r["RequiredMillijoules"] = RequiredMillijoules;
}
if (r["BeginActionCost"] != null)
foreach (var i in r["Inputs"])
{
r["BeginActionCost"] = r["BeginActionCost"].ToObject<int>() / DivideCostPer;
i["Count"] = RequiredAmount;
}
r["Outputs"][0]["Count"] = CraftedAmount;
}
if (RecipeList.Contains(r["Name"].ToString()))
{
foreach (var i in r["Inputs"])
{
i["Count"] = RequiredAmount;
}
r["Outputs"][0]["Count"] = 1;
}
if (RecipeListStack.Contains(r["Name"].ToString()))
{
foreach (var i in r["Inputs"])
{
i["Count"] = RequiredAmount;
}
r["Outputs"][0]["Count"] = CraftedAmount;
}
}
break;
case "D_ToolDamage.json":
foreach (var r in job["Rows"])
}
break;
case "D_InventoryInfo.json":
foreach (var r in job["Rows"])
{
if (InventoryList.Contains(r["Name"].ToString()))
{
if (PickList.Contains(r["Name"].ToString()))
{
int index = Array.IndexOf(PickList, r["Name"].ToString());
r["Mining_Efficiency"] = PickEfficiencyList[index];
}
if (AxeList.Contains(r["Name"].ToString()))
{
int index = Array.IndexOf(AxeList, r["Name"].ToString());
r["Felling_Efficiency"] = AxeEfficiencyList[index];
}
r["StartingSlots"] = InventorySize;
}
break;
}
break;
case "D_ProcessorRecipes.json":
foreach (var r in job["Rows"])
case "D_Generator.json":
foreach (var r in job["Rows"])
{
if (GeneratorList.Contains(r["Name"].ToString()))
{
if (r["Inputs"].Count() > 0)
r["GenerationRate"] = GenerationRate;
if (r["GenerationRatio"] != null)
{
if (RecipeListOre.Contains(r["Name"].ToString()))
{
if (r["RequiredMillijoules"] != null)
{
r["RequiredMillijoules"] = RequiredMillijoules;
}
foreach (var i in r["Inputs"])
{
i["Count"] = RequiredAmount;
}
r["Outputs"][0]["Count"] = CraftedAmount;
}
if (RecipeList.Contains(r["Name"].ToString()))
{
foreach (var i in r["Inputs"])
{
i["Count"] = RequiredAmount;
}
r["Outputs"][0]["Count"] = 1;
}
if (RecipeListStack.Contains(r["Name"].ToString()))
{
foreach (var i in r["Inputs"])
{
i["Count"] = RequiredAmount;
}
r["Outputs"][0]["Count"] = CraftedAmount;
}
r["GenerationRatio"] = GenerationRatio;
}
}
break;
case "D_InventoryInfo.json":
foreach (var r in job["Rows"])
{
if (InventoryList.Contains(r["Name"].ToString()))
{
r["StartingSlots"] = InventorySize;
}
}
break;
}
Message.CMW($"Saving {f}...", true, 1);
var raw = JsonConvert.SerializeObject(job, Formatting.Indented);
if (!Directory.Exists($@"{cd}\Data\Modded\data\{Path.GetFileName(d)}")) { Directory.CreateDirectory($@"{cd}\Data\Modded\data\{Path.GetFileName(d)}"); }
File.WriteAllText($@"Data/Modded/data/{Path.GetFileName(d)}/{f}", raw);
}
break;
}
Message.CMW($"Saving {f}...", true, 1);
var raw = JsonConvert.SerializeObject(job, Formatting.Indented);
if (!Directory.Exists($@"{cd}\Data\Modded\data\{Path.GetFileName(d)}")) { Directory.CreateDirectory($@"{cd}\Data\Modded\data\{Path.GetFileName(d)}"); }
File.WriteAllText($@"Data/Modded/data/{Path.GetFileName(d)}/{f}", raw);
}
}
if (File.Exists($@"{cd}\Paks\{ModName}.txt")) { File.Delete($@"{cd}\Paks\{ModName}.txt"); }
File.WriteAllText($@"{cd}\Paks\{ModName}.txt", $@"""{cd}\Data\Modded\*.*"" ""..\..\..\Icarus\Content\*.*""");

View File

@@ -17,14 +17,15 @@ Official MxIcarus Modding Tool for Icarus.
- Reduce all required mats of a recipe to 1, using a list. (Edited in settings.json)
- Set output of all stacking recipes to a specified value. (Edited in settings.json)
- Adjust the size of all inventory specified in a list. (Edited in settings.json)
- Adjust the energy produced and the biofuel consumed by all specified generator in a list. (Edited in settings.json)
## How-To
1. Download the latest [release](https://mxgit.ovh/Icarus/Jsarus/releases).
2. Copy the archive content in an empty folder on your disk.
3. Open "settings.json" and edit the "ModName" and "GameContentPath".
4. IMPORTANT: Escape "\" in your path with "/". Ex.: "C:\/SteamLibrary\/steamapps\/common\/Icarus\/Icarus\/Content"
4. IMPORTANT: Escape "\\" in your path with "\\\\". Ex.: "C:\\\\SteamLibrary\\\\steamapps\\\\common\\\\Icarus\\\\Icarus\\\\Content"
5. Save the "settings.json" file and run "Jsarus.exe".
6. Jsarus will extract your game data, press "y" when asked to mod it and generate a mod pak.
6. Jsarus will extract your game data and mod it.
7. Copy the created pak file from the "Paks" folder to your game "mods" folder.
8. "mods" location exemple: "C:\SteamLibrary\steamapps\common\Icarus\Icarus\Content\Paks\mods"
9. If you don't have a "mods" folder, create one first.