Jump to content

The Insanity God

Vintarian
  • Posts

    55
  • Joined

  • Last visited

Everything posted by The Insanity God

  1. The efficiency is used to calculate the conversion to charcoal yes, idk if it's a 1 to 1 ratio though. (note: GetFireWoodQuantity collects the efficiency of the actual item, in this case sticks) NatFloat is a vintage story data type for generating random numbers https://wiki.vintagestory.at/Modding:NatFloat
  2. You have this invisible face because by default the game will try to cull any faces that are not visible (because they are touching a neighboring block) and your model does not cover the faces. You'd want to change the sideopaue and probably also sidesolid in the blocktype json file: "sidesolid": { "all": false }, "sideopaque": { "all": false }, As for not being able to place a block in the center position, well.. that makes sense as there already is a block there (your tent block that is). If using code you could probably use a BlockEntity or the Fluid Layer to somewhat make the space usable but it won't be easy.
  3. The attribute patch should be "addmerge" to prevent deleting other attributes The behavior properties path is incorrect should have a number indicating which item in the behavior list to edit, so "/behaviors/0/properties" for the first behavior (the game is made in a 0 indexed language so we start at 0) The behavior properties should also change "upSolid" to true, because otherwise you cannot place a campfire on it (which is required for a charcoal pit) All in all this would be the minimum changes you'd need for it to work: [ { "op": "add", "path": "/class", "value": "ItemFirewood", //Only firewood is valid for charcoal pit (hard coded requirement) "file": "game:itemtypes/resource/stick.json", "side": "Server" }, { "op": "addmerge", //Has to be addmerge to prevent deleting other attributes "path": "/attributes", "value": { "firepitConstructable": true }, "file": "game:itemtypes/resource/stick.json", "side": "Server" }, { "op": "addmerge", "path": "/behaviors/0/properties", // need to select the first behavior through "/0" "value": { "stackingCapacity": 32, "bulkTransferQuantity": 8, "burnHoursPerItem": 0.1, "upSolid": true // this is required to make it so you can put a firepit ontop of it and stack it more then 1 high }, "file": "game:itemtypes/resource/stick.json", "side": "Server" } ] Though you will likely also want to change the stacking model and it's ratio's (default one will look weird) and possibly also change the "efficiency" attribute (NatFloat) to change the conversion ratio to charcoal.
  4. Well I mean it's not really a limitation for code mods, but yeah still quite a lot of this stuff that needs to be refactored to be less hard coded.
  5. No the shape is fine, from the looks of it `ItemShield` has a lot of logic for rendering shields through attributes. The "construction" variant group states are used in a hard coded ways so a lot of the logic in `ItemShield` is not working because your item does not have one of the expected [ "crude", "woodmetal", "woodmetalleather", "metal", "blackguard" ] states variantgroups: [ { code: "construction", states: [ "scutum" ] } ], Relevant code: https://github.com/anegostudios/vssurvivalmod/blob/84c80e85f36e31d3b6454021da0fbbba4cba71a3/Item/ItemShield.cs#L53
  6. the command you are thinking of is ".tfedit" (used while holding the item to bring up an interface for live editing these position transforms)
  7. I normally just check the actual game files, but in this case it's a bit hard because the thing you are trying to patch is a value that's patched in. The `%appdata%\Vintagestory\assets\survival\blocktypes\soil\soil.json` file already contains 1 behavior (index 0, because the language is 0 indexed) and then a patch later adds the unstable behavior so I would assume it's at least index 1.
  8. I can't help but notice the following: Your patch is a text file and not a json file. It's also missing comma's in between the different patches. The index is wrong on some of them (soil would be index 1 I believe not 0), you'd also have to ensure it runs after the base game patch (not sure if that's even a thing for patches but you could try dependson in the patches) I'll be honest though... this kinda thing is a lot easier and less prone to break with game updates and other mods when done from code.
  9. So remember how earlier I said "this is normally done either through a BlockEntity with custom logic for it or through variants" well the `GenericTypedContainer` would be one of the base game BlockEntities with rotation logic... meaning you now have 2 rotation systems trying to interfere with each other. I know the base game chest also has this but in their case it's to provide legacy support (you can only place down the `east` variant now and it fully uses the BlockEntity rotation) the reason why the textures don't work is because `GenericTypedContainer` is designed for creating variants through attributes instead of the standard variants system and to achieve this they altered the way textures are defined. { "code": "workbench", "class": "BlockGenericTypedContainer", "entityclass": "GenericTypedContainer", "behaviors": [ { "name": "Lockable" }, { "name": "Container" }, { "name": "BoatableGenericTypedContainer" } ], "creativeinventory": { "general": [ "workbench" ], "decorative": [ "workbench" ] }, "attributes": { "inventoryClassName": "chest", "defaultType": "normal-generic", "types": [ "normal-generic" ], "handbook": { "groupBy": [ "workbench" ] }, "rotatatableInterval": { "normal-generic": "22.5degnot45deg" }, "storageType": { "normal-generic": 189 }, "retrieveOnly": { "normal-generic": false }, "shape": { "normal-generic": "workbench" }, "typedOpenSound": { "normal-generic": "game:sounds/block/largechestopen" }, "typedCloseSound": { "normal-generic": "game:sounds/block/largechestclose" }, "variantByGroup": "side", "variantByGroupInventory": null }, "shapeInventory": { "base": "workbench", "rotateY": 270 }, //Texture identifiers are prefixed with the type "textures": { "normal-generic-top": { "base": "game:block/wood/workbench/top" }, "normal-generic-bottom": { "base": "game:block/wood/workbench/bottom" }, "normal-generic-fdoor": { "base": "game:block/wood/workbench/bottom" }, "normal-generic-back": { "base": "game:block/wood/workbench/back" }, "normal-generic-sideleft": { "base": "game:block/wood/workbench/left" }, "normal-generic-sideright": { "base": "game:block/wood/workbench/right" } }, "replaceable": 500, "resistance": 1.5, "lightAbsorption": 99, "sidesolid": { "all": false }, "sideopaque": { "all": false }, "heldTpIdleAnimation": "holdbothhandslarge", "heldRightReadyAnimation": "heldblockready", "heldTpUseAnimation": "twohandplaceblock", "tpHandTransform": { "translation": { "x": -1.23, "y": -0.91, "z": -0.8 }, "rotation": { "x": -2, "y": 25, "z": -78 }, "scale": 0.4 } }
  10. You'd need code for this. but should be fairly straight forward as the game triggers an event whenever this happens. (from `ItemSlotCraftingOutput` class)
  11. If you want it to be rotatable with a wrench then you need to add the "WrenchOrientable" behavior: { code: "workbench", behaviors: [ {name: "HorizontalOrientable"}, { name: "WrenchOrientable", properties: { basecode: "yourmoddomain:workbench" } } ], variantgroups: [ { code:"side", loadFromProperties: "game:abstract/horizontalorientation" } ], creativeinventory: { "general": ["workbench-north"], "decorative": ["workbench-north"] }, shapeByType: { "*-north": { base: "workbench", rotateY:0 }, "*-east": { base: "workbench", rotateY:270 }, "*-south": { base: "workbench", rotateY:180 }, "*-west": { base: "workbench", rotateY:90 } }, replaceable: 500, resistance: 1.5, lightAbsorption: 99, sidesolid: { all: false }, sideopaque: { all: false }, textures: { "top": { base: "game:block/wood/workbench/top" }, "bottom": { base: "game:block/wood/workbench/bottom" }, "fdoor": { base: "game:block/wood/workbench/bottom" }, "back": { base: "game:block/wood/workbench/back" }, "sideleft": { base: "game:block/wood/workbench/left" }, "sideright": { base: "game:block/wood/workbench/right" } }, heldTpIdleAnimation: "holdbothhandslarge", heldRightReadyAnimation: "heldblockready", heldTpUseAnimation: "twohandplaceblock", tpHandTransform: { translation: { x: -1.23, y: -0.91, z: -0.8 }, rotation: { x: -2, y: 25, z: -78 }, scale: 0.4 } } note: the content of "basecode" doesn't actually matter it just needs to be unique. (the game uses it as a key/identifier to group the blocks by)
  12. Huh, maybe this kinda patch just somehow doesn't work when run client side and because you added the "side" line it now enforces the patch happen during client side logic (instead of happening earlier) it stopped working It's case insensitive, in the code It's actually capitalized so if it wasn't then lowercase would likely fail
  13. The game uses `IntArrayAttribute` for this, would look like this: ITreeAttribute treeAttribute = new TreeAttribute(); int[] myIntArray = [1, 2, 3, 4]; treeAttribute["myIntArray"] = new IntArrayAttribute(myIntArray);
  14. It's bleeding through the sides because you didn't define `sidesolid` and `sideopaque` and you can't rotate it because you didn't add any logic for rotation... this is normally done either through a BlockEntity with custom logic for it or through variants (the latter means it creates a separate block for each orientation) So you'd end up with something like this: { "code": "workbench", "class": "Block", "maxstacksize": 64, "variantgroups": [ { "code": "type", "states": [ "fired" ] }, //Add the extra orientations { "code": "side", "loadFromProperties": "game:abstract/horizontalorientation" } ], //Add behavior to handle logic for selecting the correct orientation to place "behaviors": [ { "name": "HorizontalOrientable" } ], "attributes": { "mapColorCode": "settlement" }, "shape": { "base": "workbench", //Set orientation on shape for each orientation variant "rotateYByType": { "*-north": 180, "*-east": 90, "*-south": 0, "*-west": 270 } }, //drawtype: "Cube", "blockmaterial": "Soil", "creativeinventory": { "general": [ "*-fired-north" ], "decorative": [ "*-fired-north" ] }, "replaceable": 700, "resistance": 3, "lightAbsorption": 99, // Must declare textures so they get added to the block texture atlas "textures": { "back": { "base": "game:block/wood/workbench/back" }, "sideleft": { "base": "game:block/wood/workbench/left" }, "sideright": { "base": "game:block/wood/workbench/right" }, "bottom": { "base": "game:block/wood/workbench/bottom" }, "top": { "base": "game:block/wood/workbench/top" }, "fdoor": { "base": "game:block/wood/workbench/bottom" } }, "drops": [ { "type": "block", "code": "workbench-fired-north", "quantity": { "avg": 0.85, "var": 0 } } ], "sounds": { "place": "game:block/dirt", "break": "game:block/dirt", "hit": "game:block/dirt" }, //These should be defined to prevent it from assuming the sides are solid and thereby not render the sides of blocks next to it. (aka the bleeding through) "sidesolid": { "all": false }, "sideopaque": { "all": false }, "fertility": 3, "heldTpIdleAnimation": "holdbothhandslarge", "heldRightReadyAnimation": "heldblockready", "heldTpUseAnimation": "twohandplaceblock", "tpHandTransform": { "translation": { "x": -1.23, "y": -0.91, "z": -0.8 }, "rotation": { "x": -2, "y": 25, "z": -78 }, "scale": 0.4 } }
  15. Essentially the same way as you'd do in the ModInfo, though if the mod is already marked as client side then this will only enforce that the patch happens during the client side code and not during the server side code when possible. [ { "file": "game:blocktypes/stone/cobble/cobbleslab.json", "op": "replace", "path": "/textures", "value": { "horizontals": { "base": "block/stone/cobblestoneslab/{rock}" }, "up": { "base": "block/stone/cobblestoneslabtop/{rock}*" }, "down": { "base": "block/stone/cobblestone/{rock}*" } }, "side": "Client" } ]
  16. The `Side` should be set to `Client` inside the modinfo.json (and possibly also in the patch itself) and well if the server is using fairplay guardian (mod for restricting client mods on a server) you might need to get it whitelisted
  17. I think you might have understood, but I'm not entirely sure so I'll give my take anyway: The error is actually unrelated to the grid recipe it's crashing because of the combustible props: In the case of your "storagevessel-ashforest-raw" this will resolve into "storagevessel-ashforest-fired", but your file for fired vessels does not have a "ashforest" variant: As a result, when you open up the handbook page and it tries to display that it can smelt into "storagevessel-ashforest-fired" it crashes because it doesn't exist.
  18. You might want to try Rubberbandaid (https://mods.vintagestory.at/show/mod/28325) and see if that helps. Vanilla has an issue where if too many player attributes are updated at the same time it can seems like you are lagging/glitching/rubberbanding but it's actually just due to some hard coded limit which when surpassed triggers a full resync of attributes including position. If you are using mods you can hit this limit especially easily as merely taking damage alone already gets you halfway to that hard coded limit.
  19. 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)
  20. `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.
  21. 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)
  22. 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.
  23. 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(); }
  24. ModInfo file looks just fine, if it's not found you might want to check the `csproj` file to ensure it's actually including your ModInfo file Might want to also manually delete the content of the `bin` folder (folder is normally hidden inside visual studio) to do a fresh rebuild.
  25. 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(); }
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.