-
Posts
62 -
Joined
-
Last visited
Content Type
Profiles
Forums
Blogs
News
Store
Everything posted by The Insanity God
-
You sure about that? base game doesn't list the entries separately either.... creativeinventoryStacks: [ { tabs: [ "general", "decorative" ], stacks: [ { type: "block", code: "storagevessel-{color}-fired", attributes: { type: "normal" } }, ] } ] (from base game `assets\survival\blocktypes\clay\fired\storagevessel.json` file) EDIT: Maybe you are confused with the attribute based variant system the chests use? Where they do indeed need to be listed separately because it's not an actual variant but an "attribute based variant" creativeinventoryStacksByType: { "*-east": [ { tabs: [ "general", "decorative" ], stacks: [ { type: "block", code: "chest-east", attributes: { type: "normal-generic" } }, { type: "block", code: "chest-east", attributes: { type: "golden" } }, { type: "block", code: "chest-east", attributes: { type: "owl" } }, ] }, { tabs: [ "general", "clutter" ], stacks: [ { type: "block", code: "chest-east", attributes: { type: "normal-aged" } }, { type: "block", code: "chest-east", attributes: { type: "golden-aged" } }, { type: "block", code: "chest-east", attributes: { type: "owl-aged" } }, { type: "block", code: "chest-east", attributes: { type: "collapsed1" } }, { type: "block", code: "chest-east", attributes: { type: "collapsed2" } }, { type: "block", code: "chest-east", attributes: { type: "collapsed3" } }, ] } ] }, (from base game `assets\survival\blocktypes\wood\chest.json` file)
-
`BlockGenericTypedContainer.OnPickBlock` (used by the game to find the name of your placed block) appears to be unable to find your block. public override ItemStack OnPickBlock(IWorldAccessor world, BlockPos pos) { ItemStack stack = new ItemStack(world.GetBlock(base.CodeWithVariant("side", "east")), 1); BlockEntityGenericTypedContainer be = world.BlockAccessor.GetBlockEntity(pos) as BlockEntityGenericTypedContainer; if (be != null) { stack.Attributes.SetString("type", be.type); } else { stack.Attributes.SetString("type", this.defaultType); } return stack; } To be specific it's failing on the `world.GetBlock(base.CodeWithVariant("side", "east"))` part, I can think of 2 reasons why this might fail: 1. The "side" variant might be wrong: You don't actually need "side" variant but if you do have it, ensure that "east" is a valid state for it. (`CodeWithVariant` reconstructs the code but where the "side" is normally present will be replaced with "east") 2. The Code might be wrong: This could happen if you put a `-` in the code, quite a few people who do this... but this what the game uses as the separator for variants and using it in the code (or variant states) tends to mess up variant mutation. For instance if your code looks like this: code: "storagevessel-custom" The `CodeWithVariant` will actually only use `storagevessel` (because it searched for the first `-` to remove all variants) which would result in an incorrect code being generated. Don't think I can figure out anything more without seeing the actual block file.
-
is the modding api language agnostic?
The Insanity God replied to hstone32's topic in [Legacy] Mods & Mod Development
Short answer: No it's not agnostic. Long answer: First of all there are 2 types of mods: 1. Content mods: these only contain stuff like JSON and PNG files. You can do a surprising amount of things with these (like custom entities, blocks, items, etc) but if you need real custom logic/behavior then this likely won't be enough. 2. Code mods: these actually contain a DLL file (don't ask why but the game also accepts uncompiled cs files, which it compiles itself) containing custom logic/behavior. The DLL is loaded through `Assembly.UnsafeLoadFrom` so it has to be a managed .NET assembly (meaning native C++ won't work) but you should be able to write it in C#, F#, VB.NET or even C++/CLI, though I doubt many (if any) have tried using stuff other then C#. (Technically speaking you could also create a bridge from .NET to lots of other stuff but it's not standard) -
Looking at the provided stacktrace, it's failing while appending the crushing props info to the tooltip: Tested the patch with "game:stick" instead of "kaoliniteyay:copperpowder" (because I don't have the mod this item is from) and it worked just fine, meaning it most likely failed to find your item. So would recommend double checking the code and that it is indeed an Item and not a Block.
-
Wait you had the main project inside of the mods folder? well that does explain why it was showing up twice, since pressing play normally launches the game with your bin folder as an additional mod path. Meaning it will attempt to load both your actual compiled mod and the non compiled project because it's in the mods folder (which fails because folder structure doesn't match) But yeah in the case of farmland the IL code looks a bit different: So would end up looking more like this: [HarmonyTranspiler] [HarmonyPatch(typeof(BlockEntityFarmland), "Update")] internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { var matcher = new CodeMatcher(instructions); var temperatureField = AccessTools.Field(typeof(ClimateCondition), nameof(ClimateCondition.Temperature)); matcher.MatchStartForward( CodeMatch.LoadsLocal(), //match the loading of a local variable (ClimateCondition) new CodeMatch(OpCodes.Dup), //duplicate climate condition (cause it needs to both retrieve and store field CodeMatch.LoadsField(temperatureField), //match the retrieval of the field CodeMatch.LoadsConstant(5f), //match the static 5 new CodeMatch(OpCodes.Add), //match the addition CodeMatch.StoresField(temperatureField) // match the storing of the field ); if (matcher.IsInvalid) { throw new Exception("Farmland transpiler could not find a match, either base game code has changed or another mod has changed this logic"); } matcher.Advance(1); //Still need to load the ClimateCondition matcher.RemoveInstruction(); //But don't duplicate (we only need it once) matcher.RemoveInstruction(); //Also don't try to load the field matcher.Instruction.operand = 20f; matcher.Advance(1); matcher.RemoveInstruction(); //No addition is needed anymore return matcher.InstructionEnumeration(); }
-
The `[HarmonyPatch]` attribute does not need to be on the `SteadyGreenHouses` class (it doesn't contain any patches) The class containing patches (for instance `BerryBush`) does not need to inherit `ModSystem` and might as well be a static classes (since it only contains static methods) I'd recommend using the `CodeMatcher`, makes patches a lot more readable You replaced the `Add` operation with a `Nop` this will result in invalid code as you never removed the variable that was loaded so it's still on the stack (should be putting a big error about this in your log file). Berry patch would end up looking like this using CodeMatcher and after fixing number 4: [HarmonyTranspiler] [HarmonyPatch(typeof(BlockEntityBerryBush), "CheckGrow")] internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { var matcher = new CodeMatcher(instructions); matcher.MatchStartForward( CodeMatch.LoadsLocal(), //match the loading of a local variable CodeMatch.LoadsConstant(5f), //match the static 5 new CodeMatch(OpCodes.Add), //match the addition CodeMatch.StoresLocal() // match the storing of a local variable ); if (matcher.IsInvalid) { throw new Exception("BerryBush transpiler could not find a match, either base game code has changed or another mod has changed this logic"); } matcher.RemoveInstruction(); //We don't need the original temperature (so don't push the value onto the stack) matcher.Instruction.operand = 20f; matcher.Advance(1); matcher.RemoveInstruction(); //No addition is needed anymore return matcher.InstructionEnumeration(); }
-
I can't say much about the actual code without seeing it but when you say "compile" do you mean: Build and manually create mod zip Use CakeBuild and grab the mod zip from the "Release" folder Just pressing the play button in visual studio (All of those are viable though I wouldn't recommend the first) In regards to the mod showing up twice, this is something that commonly happens if you install the mod (by putting it in mod folder) and then run from visual studio or if you just have multiple versions of the same mod installed. Usually not an issue as it will just load the one with the latest version number. The folder structure of the code is irrelevant btw, it's compiled into a single .DLL file. Game searches for `ModSystem` classes and uses those as entry point (assuming "type": "code" in modinfo, but that should be standard with the template) in your case the mod system would look somewhat like this: public class MyModSystem : ModSystem { public override void Start(ICoreAPI api) { base.Start(api); //Prevent duplicate patching in single player (because it creates 2 instances of the ModSystem, 1 for server side and 1 for client side) if (!Harmony.HasAnyPatches(Mod.Info.ModID)) { var harmony = new Harmony(Mod.Info.ModID); harmony.PatchAllUncategorized(); //and possibly some category patches based on config } } public override void Dispose() { new Harmony(Mod.Info.ModID).UnpatchAll(Mod.Info.ModID); } }
-
@Vexxvididu You probably missed the documentation due to the way it's named https://wiki.vintagestory.at/Modding:Monkey_patching If you need examples there are some other mods out there that change greenhouse buff like: https://github.com/Kaktur/VS-Mod-GreenhouseBuff/tree/master/GreenhouseBuff/GreenhouseBuff/ModPatches (makes the buff +20 C instead of +5 C)
-
Mod request(s)
The Insanity God replied to Avintagekindapainting's topic in [Legacy] Mods & Mod Development
@Avintagekindapaintingthere actually is a mod that adds more firestarters (no ornamental lighters though) which I created a "reforge" of for newer game version: Extreme Firestarters Reforged -
The new "outdated" tag on mods.
The Insanity God replied to Wondiws98's topic in [Legacy] Mods & Mod Development
Personally I have mixed feelings about this change as well: I like how it's far more noticeable that the author has not confirmed that this mod is supposed to work on a given version... I don't like the phrasing "for outdated Vintage Story ..." as I feel this will be easily misunderstood as "this mod is only for outdated game versions" while in reality mods often survive game versions (especially when we talk about minor versions) I'd opt for something along the lines of: "Warning: Author has not confirmed this mod is supposed to work for game versions beyond ...." -
Anybody using AI to create mods?
The Insanity God replied to Zero_'s topic in [Legacy] Mods & Mod Development
I use it to for the following purposes: Generating mod image (cause I'm no artist and I don't enjoy creating these myself) When other people send me a translation of my mod I use it to backwards translate (just to make sure it's somewhat okay) When I really can't understand an exception I sometimes ask it to take a look and see if I just made some dumb mistake