Compare commits

..

3 Commits
1.1.1 ... 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
mikx
5fefe8eba9 1.2.0 (Added inventory list + Recipe modding tweaks) 2025-10-13 22:54:52 -04:00
2 changed files with 243 additions and 154 deletions

View File

@ -6,54 +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.1.1";
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>();
int ÞlayerInventorySize = settings["D_InventoryInfo"]["ÞlayerInventorySize"].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");
@ -74,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 (r["Name"].ToObject<string>() == "Backpack")
{
r["StartingSlots"] = ÞlayerInventorySize;
}
}
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\*.*""");
@ -237,7 +316,7 @@ namespace Jsarus
{
File.Copy($@"{cd}\Paks\{ModName}_P.pak", $@"{p}\{ModName}_P.pak", true);
}
}
}
}
}
}
}

View File

@ -4,19 +4,29 @@
Official MxIcarus Modding Tool for Icarus.
## Features
* Extract json data from your client.
* Mod your extracted json data according to the settings.json config.
* Create a pak file, ready to use on your client/server.
* Can copy the created pak file to a user specified list of path.
1. Extract json data from your client.
2. Mod your extracted json data according to the settings.json config.
3. Create a pak file, ready to use on your client/server.
4. Can copy the created pak file to a user specified list of path.
- Set all stackable item stack size and weight. (Edited in settings.json)
- Set all non-stackable item weight. (Edited in settings.json)
- Multiply all experience gain. (Edited in settings.json)
- Divide stamina cost of listed action list. (Edited in settings.json)
- Set efficiency of listed pickaxe and axe from a list. (Edited in settings.json)
- Set ore recipe crafting speed. (Edited in settings.json)
- 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"
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.
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.
10. Voila!
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"
5. Save the "settings.json" file and run "Jsarus.exe".
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.
10. Voila!