#making-mods-general
1 messages ยท Page 24 of 1
the price is just bc you cant afford it isnt it
ah right forgot its new save 
hm, no, that's not what I told you to do game
ExperienceCurve = new int[10] { 100, 338, 783, 1504, 2570, 4050, 6013, 8528, 11664, 15490 };
update on my poop adventures: made them not fly in the air, but also learned that debris objects are not serialized, so if they aren't collected they'd disappear after exiting the game. oh well, I'll file that under 'intended'
If you really wanted to do otherwise, you'd have to hold the debris "precursors" in mod data and generate the actual debris just before warp.
(or just after warp, but presumably that's why they were flying)
yeah if you just walk in and exit then you'd lose if after exiting the game (not after saving though, if you sleep and go in the next day they'd still be there)
tabbing in to see poop adventures and wondering what the hell i've been missing
maybe the building has mod data
so u can increment until player walks in
or autograbber ig
Sure, but the player's seen them at that point so WAI?
I figured you just wanted to make sure they were seen.
resisting the poop joke, for how long...
the actual main consequence is probably with my 'machine multiple produce' feature integration with Automate, which dumps the excess produce on the ground if the chest is full, so inattentive farmers may lose some of the output if they don't check their sheds regularly
Has anyone tried writing a transpiler for a compiler-generated class/method? I know how to search the code instructions to find out what the generated name is, but only know how to do that from a transpiler, which seems too late to be registering an entirely different transpiler.
(I used to spawn non-object forage as debris, but on top of that issue, mobile had its own DebrisManager that deleted them on warp in 1.4
)
no idea if that'll keep being true, but debris was notably slow and needed reworking at the time
hm you need to access method info basically, what kind of compiler generated thing is it?
if SMAPI 1.6 mobile ends up being a thing I think I'd just respond to every mobile compat request/bug reports with a shrug emoji
Specifically it's part of an orderby clause. I can find it in ILSpy. But I don't feel like I should trust it to always have the same class/method symbol.
The signature itself does not really communicate enough; there are multiple methods with that signature.
I guess I have to use GetMethodBody().GetILAsByteArray(), don't I? Maybe Harmony has a public parser for that or something...
SpaceCore just assumes it's always the same: https://github.com/spacechase0/StardewValleyMods/blob/develop/SpaceCore/Patches/Game1Patcher.cs#L106
(Mac+Linux variant was from .net framework+Windows / Mono+Mac_Linux days)
The type probably won't change, but I'm far less confident about the method name.
Talking about junk like <GetFishFromLocationData>b__495_1 no idea what 495 is.
I know it's in patch processor, I know original instructions is part of it
Ah, that looks like it.
I found the MethodBodyReader and related stuff but they were all internal to Harmony.
Oh look, it has a ReadMethodBody too. Wonder why it didn't show up in GitHub's search.
I'm going to take a wild uneducated guess that 495 is line number
I don't think Harmony for SMAPI is up to date, maybe it's not in most recent version?
See, that's what it looks like, but the source is definitely not on line 495. Or maybe that's just the decompilation.
In the decompilation it's all the way down on line 13739.
Oh, hmm
Whatever it is, the numeric suffixes on those methods seem arbitrary, they are not sequential.
Let me test something
For all I know it's some internal compiler counter that just increments by one every time it generates a new method (for any class).
In any case, Atra has come through again so I should be able to use that to spin up a codematcher and find the real class/method name. Or hopefully, if this is coming from Harmony, the operand will be an already resolved method.
Think I figured it out - it seems to be based on the method index in the type
ie. I did this:
And got:
That makes sense (and confirms it's not exactly stable).
I wonder if you could iterate through the typeof(GameLocation).Methods (or whatever the getter is for all methods) and do it that way
Doesn't sound very reliable though
Iterate through all methods and do what with them?
Like, get the index of the method you want to patch in the "all methods" list
If they're even in the same order
Ah, gotcha. It might work unless C# literally changes the compiler behavior, which is less likely than having new methods inserted. But not really necessary given the ability to read the method body.
Once I get the CodeInstructions then I just write a CodeMatcher on it like any other transpiler (except using it to read rather than patch).
Doubly not reliable since the compiler may chose to emit a holder class
(My guess is that it has to do with whether or not there are captures)
Hm, I thought <c> was the holder, there can be another nesting level?
<>c__DisplayClass is the holder yeah
I think the displayclass is used when any part of any method in the class captures, not necessarily the particular method being generated.
This one is an "instance" method but doesn't access any instance data.
Yeah, never sure
I think captures force a nested holder class but sometimes the compiler just wants one I guess
Actually yeah, there are some without the display class. So... who knows.
Whatever it is, it is considered like
Implementation detail of the compiler
And MS may want to change it at any time
That is true of course, but my more immediate concern was having things break with minor patch versions of Stardew. Even though Harmony mods are "caveat emptor", I'd still prefer not to have everything blow up with 1.6.9 and then again with 1.6.10.
Even if MS doesn't change the implementation, and CA doesn't change that particular method, these signatures might change.
No. But there's no problem, we've figured it out already.
Well, assuming I can wrangle a decent code matcher for the orderby itself, but that's a smaller problem.
Took about 15 tries but I think I got it. Yeesh, Linq is nice to write but sure is a pain to IL-weave. Ironic that I was just advising against attempting exactly this type of transpiler the other day.
how bad can harmony mess up your stuff? Just crashing the game, or can it actually damage your computer?
i doubt you can accidentally damage computer by being bad at harmony
it'll die with PAL_SEHException before that
i don't know about damage the computer, but it is possible to bring it completely to its knees and force you to hard shutoff by eating all available memory (speaking from experience. dispose your textures!)
you can do that without harmony 
fair play 
usually Linux just kills the process when I make an recursive infinite loop, thank goodness
oh, recursion sure. max stack size and so on
yeah I clarified lol, infinite loops I need to kill, but it doesn't eat memory, just staying there spinning CPU cycles
I guess one could write malware in a C# mod 
Would hope that nexus virus scan can catch most of that
i need to throw together a 1.6.9 pack to test that new i18n/default folder 
Yeah, I did that earlier. Apparently when using CodeMatcher.Repeat, you need to call Advance. Who knew.
But damage your computer? That's just silly Hollywood nonsense, no software can physically damage your computer unless you've already compromised the physical hardware in some way (like ripping out the cooling).
you dont actually need to call Advance for CodeMatcher repeat, just need to make sure whatever match action you're repeating isn't gonna re-match on what you just added, presumably
Ah. Well it actually happened twice, the first was doing Advance(-1) and actually modifying the instruction at that position, and the second was read-only. So yeah, both cases just looped. "Why isn't my breakpoint being hit? Wait, why isn't the game doing anything at all?"
for some reason I cant get my custom recipe in the mail I dont know whats wrong with it
this is what I wrote in the mail
!json please upload your relevant json files and send the links here
JSON is a standard format for machine-readable text files that's used by Stardew Valley mods.
If you need help with a JSON file, you can upload it to smapi.io/json to see automatic validation and share the link here.
When making mods, it's recommended to edit your files in a text editor with JSON support, such as VS Code, Notepad++, or Sublime Text. These programs will check for syntax errors.
gonna need to see the content.json that you define the recipe in too, as well as whatever you're using to actually send the mail. is the problem that you can't get the letter at all, or that the letter does not have your recipe in it?
the letter doesnt have the recipe when received
in that case then if your trigger action (i presume) you're sending the mail with is in a different file i dont think you need to upload that one, but it sounds like the ID of your recipe might be wrong in one location or another
okok Ill try to check again
And for a silly question, I'm wanting to modify some dialogue in questable tractor so it will match my gender swap mods:
would the dialogue file I need to edit be mods>Questabletractor>i18n>default
Then just change the names and gendered words to match what I have?
If I make an asset Seasonal by using Content Patcher, will it trigger a Content.AssetsInvalidated event? the asset is data, so I have to cache some of it in my mod to avoid having to parse it every time I need info, I want to parse it only when it changes.
Seasonal would be either by having the path be "my_data_{Season}.json" or "When": {"Season": "Summer"}
thanks, that should be enough. Modders can change the update rate if they want to update it more often
is this just for a personal mod? if so you can just edit the i18n of the other mod, yeah. you can also figure out where that mod is loading its dialogue into and edit it from your own content patcher mod too
do you have something along these lines
private static void OnAssetRequested(object? sender, AssetRequestedEventArgs e)
{
// load the custom asset
if (e.Name.IsEquivalentTo(MyAsset))
{
_data = null;
e.LoadFrom(() => new Dictionary<string, MyModel>(), AssetLoadPriority.Exclusive);
}
}
private static void OnAssetInvalidated(object? sender, AssetsInvalidatedEventArgs e)
{
if (e.NamesWithoutLocale.Any(an => an.IsEquivalentTo(MyAsset)))
{
_data = RebuildCachedData();
}
}
Seems like the null and Rebuild should be reversed there, no?
No cus we have to wait for content packs to apply all their changes
First event is equiv of blank json
no? the rebuild call triggers the asset requested event
Well, it's more like _data = RebuildCachedData() should actually be part of a lazy loader, but setting to null should happen on invalidate. I don't know why you'd set it to null on asset requested in any case.
I think I actually left the loading part to a getter tho
Cus I didn't care to parse data beyond putting it in model
yeah come to think of it you don't need setting null there.
if the _data variable is not touched anywhere else but these two events then I think you need to remove the null assignment
I think so, my "cache" objects call GameContent.Load<JObject>(path_to_data) to parse the data and store its values, then it should clear the values and reload the data on invalidation
Oh this one is for use with Game1.content
Safest strategy would, I believe, be to clear your cache on asset invalidated, and load/cache it on demand, when it is actually accessed. Which is pretty much what SMAPI itself does.
I need to reload it as soon as it's invalidated, because it's the data that defines Furniture
Game1.content.Load<Dictionary<string, MyModel>>(MyAsset);
I don't think you do; you just need to invalidate it on invalidated so that the next time it is requested, it is retrieved fresh.
Rather than directly get from file
That's what invalidation means; putting a "don't use this anymore" tag on it but waiting until you actually need it again before reloading it.
Since this is not for a mod that's a target of content pack for
It doesn't know what files other mods have
Rely on them load/edit a target instead
Having it load the data "when it is needed" is kind of a pain in my case, I load it "once" so that I can access it anytime without having to parse it again, then I want to parse this data again if it was edited with CP
Why is it a pain exactly?
Just make a lazy load property
Whatever field you store the data in, make it a property and attach it to a load-and-cache method, that's all.
Then it's invisible 
because I have hundreds of lines already written and changing the design would be a waste of time
can you elaborate?
Haiiiii question
say I wanna pull off a dialogue in an event and wanna do two alternatives: one is that they're married with kids and one where they're married but without kids. Would I only need to set the When condition for that?
yeah I don't really know how to do this cleanly
I was dum and did it manually (with a field + a property with getter)
Fix eventually
public Data Data => GetData();
private Data? data;
private Data GetData()
{
if (data is null)
{
data = Game1.Content.Load(...);
}
return data;
}
I was thinking of simply using a public getter that checks a private cached field, and reloads it if the cached field is null
Or you could use Lazy although that's normally meant for lazy initialization and not for repeated invalidation.
In my example above, you can add an InvalidateData() method that just sets data = null.
Whatever hundreds of lines of code are written for the loading/parsing/etc. shouldn't need to change.
(Chu is going to say that you can have a mutable Lazy field and write a new value to it, which you totally can; it's just not really the intent of Lazy)
u can do transformation into Data/Furniture in the getter I think
Or hm maybe u do it in AssetRequested too
But have the getter for data invalidate data furniture
So it cascades
I'm sorry, I can't get to wrap my head around a new concept right now... I have difficulty seeing how to apply this stuff, I can't even make sense of the code snippets you're sending...
Loading in AssetRequested is definitely the easiest way to have SMAPI handling the caching and invalidation for you. But there might be reasons for keeping it private.
If you're going to be doing caching at all, then this is a pretty important concept to understand. Otherwise, you are basically doing caching wrong.
Yeah it's a bit different from the content pack for way
Since u r not handling any loading details, just letting CP do it
Forcing a reload on invalidate really isn't a nice thing to do; invalidation happens when SMAPI is trying to clean up after itself.
Yeah, I know about that, I just changed how FF handles textures to let SMAPI handles all texture caching
my current situation is that I have the info about all custom Furniture from Furniture Packs in classes (including "included files"), because I have A LOT of transformation to do on the data to make it easier to compute player interactions, collisions and rendering when the game runs. This parsed data is also used when the game loads "Data/Furniture" and "Data/Shops" to populate them with the custom Furniture.
And lazy loading/load-on-demand changes none of that.
"I load it "once" so that I can access it anytime without having to parse it again"
i think the concept theyre explaining is just to move your rebuild step to the point that you're accessing it, not when you're loading it, if its null when you try to access it (which can be easily done by turning the method you're using to access it into a method that returns the data, instead of accessing the list/array/whatever directly)
assuming im understanding correctly
if you need to access it right away (for example if you want to update furniture in the world thats already placed, i suppose) then it ends up the same, but if you dont need to access it right away, then it saves some work
well, my issue is that there are A TON of demands in the "on-demand" part of "load-on-demand"
Currently you have some Data field that you load into and are referencing everywhere; you merely change that to a property as per the snippet above.
It doesn't matter. The load only happens once.
if you never access the data after the invalidation, then you dont need to rebuild it right away, bc you're not going to access it
if you end up accessing it later, then the method that gets you that access will rebuild if necessary
So the api we r suggest is dependent on there being a custom asset in the content pipeline that u create (the Exclusive load in my asset requested example)
You can have 1 reader or 1000 readers, the lazy-loading code is the same either way.
whats the difference between id and an itemid???
But I don't think that is a given for the content pack for stuff which just knows what files exist in dependent mods and can use em directly 
ItemId is just for items, ID is how to identify a specific entry in a data asset
(Technically there are exceptions in case of concurrency, which you generally don't need to worry about in any SDV loops unless you've deliberately written it that way)
ok thanks
I originally thought you are move stuff to CP custom asset so that is why I brought this up
(this convo makes me feel like there should be a formal guide for adding a custom asset, since that's basically the intended way for 1.6 frameworks. And the guide at https://stardewvalleywiki.com/Modding:Modder_Guide/APIs/Content#Let_other_mods_edit_your_internal_assets is very incomplete e.g. doesn't deal with invalidation)
Or there could be a utility class that handles all of that for you
I do understand what Leroy is saying, that there's a lot of data derived from the custom asset that isn't in the custom asset. The point I'm making is just, have the lazy loader run that entire pipeline, including both the loading and the derivations.
I feel like the issue comes from how I have the mod setup: there's no Data field, I have a class representing a Furniture Pack, containing a list of Furniture Types, loading data instantiates a Furniture Type and sets all its attributes
I think you check the ChildNames token
https://github.com/Pathoschild/StardewMods/blob/develop/ContentPatcher/docs/author-guide/tokens.md#valueat
You must be referencing the data somehow, though; through one field/property, or multiple fields/properties.
If I clear the Furniture Type there's nobody to ask for the data
Thank you, chu/e 
if nothing checks that class after setting it to null, though, then there doesnt need to be anyone to ask for the data anyway. but something must be checking that class, right?
You only have to invalidate the relevant vanilla data though
When game wants furniture data it'll get it
yeah, that I do, but I have a lot of data that doesn't fit in the vanilla Furniture data definition
My custom FurnitureType has all these fields (and the one with a custom class for type have some fucked-up parsing to do):
public readonly string mod_id;
public readonly string id;
string display_name;
string type;
public readonly int price;
bool exclude_from_random_sales;
List<string> context_tags = new();
int placement_rules;
int rotations;
bool can_be_toggled = false;
bool time_based = false;
DynaTexture texture;
List<Rectangle> source_rects = new();
public readonly Rectangle icon_rect = Rectangle.Empty;
Layers layers;
int frame_count = 0;
int frame_length = 0;
Point anim_offset = Point.Zero;
bool is_animated = false;
Collisions collisions;
Seats seats;
Slots slots;
public readonly bool is_table = false;
Sounds sounds;
Particles particles;
LightSources light_sources;
PlacementType p_type = PlacementType.Normal;
public readonly string? shop_id = null;
public readonly List<string> shops = new();
public readonly SpecialType s_type = SpecialType.None;
Vector2 screen_position = Vector2.Zero;
float screen_scale = 4;
Point bed_spot = new(1);
public readonly BedType bed_type = BedType.Double;
Rectangle bed_area;
Rectangle? fish_area = null;
public readonly bool disable_fishtank_light = false;
public readonly string? description;
These fields are all part of a class, though, are they not?
yeah
This is basically the MyModel class in example
You only need to lazy-load/cache the class that contains them. Not every single field individually.
Are u loading to JObject and then assigning these by hand 
If the field names match u can just load right into the model class
I'm guessing stuff like Collisions have to be derived after loading the core data.
and the class handles all the updates: every harmony patch on Furniture will ask the list of FurnitureType if there's a custom Furniture matching the current Furniture ID and the FurnitureType will apply the changes. If the FurnitureType isn't loaded, nobody will know it's missing, I don't understand how to do it other than reload all FurnitureTypes when their data is invalidated
yep, because there's a lot of fucked up parsing to convert user-friendly json field into engine friendly data structures
You cache and invalidate the list of furniture types.
Set the entire list to null on invalidate and put the entire list behind a lazy loader.
instead of having the patch ask the list, have the patch ask a GetList() method to give it the list
GetList will load it if it doesnt exist
(along with what focustense said of nulling the list itself and not the types)
What I'm calling Data could be:
public class FurnitureData
{
public List<FurnitureType> FurnitureTypes { get; set; } = [];
}
And then you clear the entire FurnitureData.
well, it will load it in the next frame after the invalidation then, what's the point of not loading it right after the invalidation?
How do you know it would be the next frame?
does your harmony patch run every frame?
fair enough
You will have it by the time you draw tho, because you called GetList()
the point is not that it will help significantly really, bc you are correct that it will happen basically right away if there is a furniture, if it happens in the draw method
but its free cpu cycles to save when it doesnt happen right away
and nice practice besides
(FWIW, I wouldn't harp on this for any old mod, but since this is a framework mod that many other authors are expected to use, performance, timing and memory usage should be tight.)
ok, I think I get it know, I'll look into it. Since I'm doing a huge revamp update I'll probably do this too
(nice practice bc ofc there are a lot of situations where it actually can be significant, even if this specific one isnt always one of them)
I hate my FurniturePack loading system so much, I don't want to touch it again...
i think unless you're a true savant i feel like everyones been there, having stuff they wrote initially and hated later
You can always ping/ask for additional help. What we're all saying is that switching to a lazy loader isn't actually a big change as long as you have one "loader" right now (vs. a big pile of spaghetti code, which hopefully is not the case).
The approach I took for the trinket thing I am make is to make the data class a field on the behavior class
If you find that this seems to amount to a major rewrite, then either we've misunderstood the problem or we didn't explain the solution well enough, because it shouldn't be too big a deal.
Fancier parsing of data can happen in constructor of the behavior class instead of the data class
Tho I'm not doing anything particularly fancy 
Yeah, I still need to understand how the lazy loader stuff works, but there's doc for it.
Yeah, the amount to rewrite should be fine now that I understand, but I remember some systems I wrote that are a bit scary, I'll have to make sure they're not breaking everything
As a rule of thumb, you should try to avoid doing expensive or error-prone work in a constructor. (Stardew breaks this all the time, but despite that, you should still avoid it.)
(Stardew breaks all conventions everywhere)

It's mostly checking whether a buff id exists
Unsure what is best way to abort constructor actually
Validation of arguments is fine of course, and expected.
just take a page from the collections menu constructor. do literally almost fuckin everything in there.
I assumed "fancier parsing" meant like, deserializing a JSON in a constructor or something. That should be done outside the ctor.
Unfortunately this is a fundamental problem with the IClickableMenu API, all you're allowed to do is set Game1.activeClickableMenu and then you sort of lose control. So you have to do a bunch of junk in the ctor.
i mean you can at least separate it out to different functions
You can; but in terms of where the functions are actually called from, you typically have two choices: the constructor, or draw.
And you don't want to do a lot of work in draw...
2000 lines function FTW
might also help to not have to call DataLoader for Mail and SecretNotes every single time you construct it too, but c'est la vie
I got scammed by AssetReady here
Should probably put AssetInvalidated
DataLoader is cached though, despite its name.
dont forget hover!
Yes, the clickable menu's "interesting" hover API.
Not sure when we would use AssetReady, it only seems to go once around game launch
What's missing are basic lifecycle methods like OnShown and OnLayout.
But Stardew has no layout system, or really any visibility system, so...
I think it happens after the first Load that happens after a cache invalidation?
but yeah the wiki example is misleading, since you really only get the ready event firing after you start a Load call
Would make sense that "ready" = "loaded".
It doesn't seem to trigger on invalidate though 
wait i forgot AssetReady was a thing does that mean i dont actually have to manually wait like 4 ticks for content patcher to load content packs in order to load my asset
Does it trigger when the asset is loaded again, after an invalidate?
I vaguely remember no, but that was many commits ago and perhaps I was just doing it wrong
I don't think you have to wait?
oh AssetReady doesnt do what i thought it did
"Raised after an asset is loaded by the content pipeline, after any mod edits specified via AssetRequested have been applied.
This event is only raised if something requested the asset from the content pipeline. Invalidating an asset from the content cache won't necessarily reload it automatically. "
/shrug if i dont wait, my data load returns an empty list
I would assume an event like that is for when you have some data or behavior that is dependent on the loaded asset, and it's expensive to compute.
yeah, but then nulling it after invalidation should take care of it?
my old asset handler code used to log something in AssetReady, and I can confirm the logged line shows up after every invalidation
Technically anything you implement with AssetReady could also be done with a lazy loader, but you might be incurring the cost at an awkward time.
im not invalidating it though, im just loading data from it right when the game launches
I mean like after CP patches your assets, it should invalidate it, and you should start a fresh load
Erf... yeah, loading data on game launch sounds like it could lead to consistency issues.
is that not the same as waiting, just with an event instead?
i know i have to wait for CP to patch my assets, i was sayin i thought AssetReady would be a better way to do it than manually waiting a number of ticks
That is exactly what AssetReady is for, AFAICT
AssetReady is only when something is requested by the pipeline
if its not requested (which it wouldnt be for my custom asset besides from myself) it wont fire
maybe just do it on save loaded
well, in this case, the asset im loading is my CP harmony patches.... which you might want before a save is loaded
hence, the quickness to load them
Oh, this is your freaky harmony thing, haha

Yeah, there may not be a good answer to that
But now you can prank people by having patches that only apply if farm name = selph
yeah, if you're doing work before a save load then I see why you need to wait for CP

The problem is that on Entry/GameLaunched, SMAPI/CP may not have actually finished setting up the pipeline.
You might be able to fiddle with priorities.
I wonder if we can beg ask for a "CP done its thing" event
private void OnUpdateTicked(object sender, UpdateTickedEventArgs e)
{
if (e.IsMultipleOf(6) && !DynamicPatcher.IsInitialized)
{
DynamicPatcher.Initialize(ModManifest);
Helper.Events.GameLoop.UpdateTicked -= OnUpdateTicked;
}
}
this is how im doing it right now. i only chose 6 cause i had vague memories of reading about CP being ready on the 4th tick but i went with 6 just to be safe or something
but then some other C# mods might modify your assets or smth
i sincerely hope no other C# mod is modifying my CP harmony patches asset
Pathos has mentioned it's basically ready at second tick or so ^
Maybe this is a case for content pack 
If you never want 2 mods editing the same patch anyways
What happens if some other mod Harmony-patches the DynamicPatcher itself?
then to them ill say good luck
you can harmony patch DynamicPatcher with DynamicPatcher via CP if you really want, too
Yes, but it's probably too late by then.
does GameLaunched happen in the same tick that the first UpdateTicked happens in?
until the asset is invalidated and the patches reapplied!
I think so, but it's been a while since I checked
if you harmony patch the function that unpatches the harmony patch... hm
forget shotguns, this feels like discussing nuclear warheads
ill be honest as long as it works for any reasonable use case im just gonna consider any potentially weird fucky cases that cause issues to be "look, just do something else, please, i might get to this eventually but why" in terms of priority
I take some perverse pleasure in imagining how people can screw everything up.
how many megatons is using CP to harmony patch SMAPI itself
Are you going to make a white list of things ppl r allowed to touch
if you harmony patch AssetInvalidated then you guarantee no one will mess with your CP harmony patches, right
In the fishing mod, I've encoded every hardcoded rule as a NoInlining property getter so that just in case some other mod is doing obnoxious things like changing the start/end of the day, I can say "welp, you write the compat patch, just Harmony this here method".
(Also, doesn't SMAPI forbid reflection or Harmony patching on itself?)
truth be told the implementation of the more advanced kinds of patches is taking me long enough that its not gonna be released for a while anywya (if at all, assuming i dont get bored before then) so to start all you'll be able to do is change results (assuming they are simple types like ints or bools) and run trigger action actions anyway, which you cant really do much damage with
i mean, you can obviously do a lot of damage if you change the result of a critical function, but again, reasonable use case
Reflection using the helper, thatโs it
i wasnt aware you could forbid reflection?
Array.Length is now Array.Length + 1
oh, with SMAPIs t hing, that makes sense
Should be fine. No problems.
Iโve definitely patched and reflected into SMAPI before (using normal reflection for the latter)
Yeah, come to think of it, I have too in the radial menu
The patching SMAPI was for my 3D mod if I remember correctly
Reflection Iโve done for multiple mods
I had to yank at the input helper because of the trigger inconsistencies.
Though I did it with just normal reflection, not Harmony.
this is actually like the main sort of thing thats taking up most of my "hm, how do i wanna implement this" time, is trying to figure out how to easily get the property of an object like that. like, loading up just Game1 is fine, but its not exactly easy to come up with a CP-author-friendly way to access Game1.player.LuckLevel for instance. the drilling down into different properties, turns out, is kinda difficult when you need to turn a string into IL
like, not impossible, obviously, but defnitely a "why am i spending effort on this again?" kind of tedious task to figure out
Yes, and doubly so once you realize that most content authors are not programmers and won't understand anything that even remotely resembles code.
But I meant like, actually patching Array.Length to return the real length + 1, which I imagine would instantly break everything.
Lookup Anything can help with some things, since you can see a lot of properties on things when you inspect em
oh i thought you were using Array as like a variable name placeholder. yeah what you said is much much worse lmao
Or someone transpiles StringBuilder.Append to reload a map asset.
(ps re CP being ready, all of its APIs also have this, which should confirm the timing)
/// <summary>Whether the conditions API is initialized and ready for use.</summary>
/// <remarks>Due to the Content Patcher lifecycle, the conditions API becomes available roughly two ticks after the <see cref="IGameLoopEvents.GameLaunched"/> event.</remarks>
bool IsConditionsApiReady { get; }```
i could limit it to the Stardew Valley namespace if i wanted to, but wheres the fun in that?
fun fact - back when I was thinking about making various artisan goods mods compatible with each other, this is what I legitimately considered: somehow patching the qualified item ID field of every item to return a different value
this i was aware of at least! i just didnt wanna have to include its API tbh
I'm not entirely sure when the API helper becomes ready either 
Games launched
when IsConditionsApiReadyApiReady is true, obviously
Even if you could patch the ID property of an Item, it wouldn't be consistent with the ID-to-item dictionary (ItemRegistry and related assets) so... I hope you didn't actually do that.
makes sense but it's been ages since I added a new one
thankfully I didn't, I went with a vastly simpler (and safer) method - just add a button to toggle the item between various forms
so I can use the 4 butters and 3 olive oils interchangably
We can always use moar buttons.
me when i try to cook
Olive oil's a dressing, I wouldn't be caught dead cooking with it. /ot
smoke point's a myth, I sear all my steak with extra virgin olive oil
this just brings back to my mind my firm belief that SDV really needs a Cooking Mama style culinary mod
Haha. Not that there aren't like, ten million recipes on the internet saying "throw a bunch of olive oil on/around this thing and then bake it at 400ยฐ".
"HOW ABOUT NO" - Dr. Evil
Which shall of course be called "Immersive Cooking".
i think Better Cooking would align more with SDV mod names personally
way too much art 
Immersive in the sense that you must actually wait 45 minutes for that cheesy broccoli, and check in on it every 15 minutes.
and a feature that if you're waiting on something to boil, in game time moves slower
I was sure there was already a "better cooking" but apparently I was wrong.
Gourmet Overhaul flashbacks
theres Love of Cooking and one other one i cant remember the name of i think
well Better Crafting includes Cooking...
if anyone cares to test some mods i've got some alpha updates going atm
love of cooking: #modded-stardew message
raised garden beds: #modded-stardew message
Blueberryโs back!
Hiiiiii (canโt recall if my name change was before or after you disappeared)
Cooking Skill, which is kinda/sorta succeeded by Yet Another Cooking Skill
Perfect example of how good gameplay can be the opposite of realistic. Hoping that my plan to make time massively speed up while waiting for a catch doesn't break a bunch of other stuff.
If it were realistic, you'd catch 2 fish in 12 hours. Realistic, just not fun.
the same magic that makes crops grow super fast in the valley probably also makes fish swarm its rivers and oceans
All can be explained with Junimo Magic.
I should start using that as an explanation for every questionable mod feature. "It's not cheating, it's Junimo Magic."
Junimo Magic got rid of my crows! thanks, Junimo Magic!
Diamonds grow on trees. Fish gift you pizzas. Why not?
I mean, that would be hilarious as a fish pond output item. however, because the Fish have a sick sense of humor, every pizza is topped with Anchovies.
just tested with your example pack and it still good as it should be
guys please help. i want to install smapi for steamdeck and this happening ๐ญ
Please wait for a volunteer to assist you at #1272025932932055121. This channel is for making mods 
perfect, thanks! I'll add a link to Market Town to tell people about the compatibility!
does anyone know where I can find the artwork for trees in the game files?
wild or fruit?
wild
content/terrainfeatures
the one you plant from seeds. The ones on map are on their map tilesheet
awesome, thank you so much!
(turns out this stops working when i do it in BETAS instead of Special Power Utilities. why? i dunno! but doing e.Ticks >= 4 works so whateverโ)
sudo before the command to install?
Not too happy with how the bundle name is presented quite yet.
It could use a name plaque of some sorts
Yeah it is a bit hard to make out properly. The rest of it looks really good though.
guythu, how do i add a condition where the mail is received by the player once it reaches a certain friendship level with an npc?? Im trying to do it with cp.
"phfood.Adobo": "[letterbg 0]{{i18n:nova.adoborecipeLewis.text}} %item cookingRecipe {{ModId}}Adobo %%[#]{{i18n:nova.adoborecipeLewis.name}}",
Use a trigger action (AddMail) with a condition of PLAYER_HEARTS. You can copy the example on the trigger actions page to get the syntax correct and get the format for the PLAYER_HEARTS game state query for the condition from the GSQ wiki page.
https://stardewvalleywiki.com/Modding:Trigger_actions
https://stardewvalleywiki.com/Modding:Game_state_queries#Player_relationships
(there's also a way to set the recipe to have a friendship level as requirement, which will then send it BUT it'll use the default mail for this character)
thank you! @vernal crest @hallow prism
btw does it matter which one i load first?
i went for : loading sprite, recipe data/object, adding recipe in data/CookingRecipe, data/shops, data/trigger actions, data/mail?
do any of the C# people know-- would there be any significant downgrade in performance if I used Content Patcher to apply 200 different patches to a data model at the same time as opposed to grouping them into a few patches? For example, adding 200 objects separately each with its own When conditions (typically a combo of config+HasMod) vs sorting all the object entries into ~5-8 patches only, with each patch adding the objects grouped under it in entries.
Morning everybody, I'm hoping someone will have an answer to a problem I'm having! I added a map patch for this area but something is programmed in to make it so you can't walk on these tiles and the NPC can't move on the water, even though they're all Back layer. I thought maybe it was Passable as a tile property that was the problem but I'm not sure how to turn that off if that's what's causing it. Is it something I would program into the tile properties on the sheet itself in Tiled? or in content patcher?
passable on back makes it non passable
not sure i would want to have my npc walk on water however, sounds like it could cause issue
I need some way to do it or a mermaid doesn't work ๐ฆ
But in this case you can't even walk onto the shore
which is why I think they used Passable
I'm asking if there's a way to turn that off
using tiles without the passable property
would I be able to see that property here if it's the problem:
i believe so
then that's not the issue
ok!
Better 
cool! if you feel like giving details i'm curious. I am also able to wait (or so i heard) if you prefer ๐
The idea is to have bundle books that are collections of bundle pages
only when all pages are completed will the book be completed
that way you can have more demanding (and fun) bundles without having to worry about rewards for every single page
it'd also be a neat way to organise a lot of smaller bundles
i see! would page have their own reward still (optionally)?
hmm, maybe i'll consider "merging" VMV bundles
that'd work
okay, so, im not sure what's going on but the i dont receive the mails even when the condition has been met.
//mail trigger
{
"Action": "EditData",
"Target": "Data/Mail",
"Entries": {
"phfood.Adobo_Lewis": "[letterbg 0]{{i18n:nova.Adobo_Lewis.text}} %item cookingRecipe {{ModId}}.Adobo %%[#]{{i18n:nova.Adobo_Lewis.name}}"
}
},
{
"Action": "EditData",
"Target": "Data/TriggerActions",
"Entries": {
"{{ModId}}.AdoboMail": {
"Id": "{{ModId}}.AdoboMail",
"Trigger": "DayStarted",
"Action": "AddMail Current phfood.Adobo_Lewis now",
"Condition": "PLAYER_HEARTS Current Lewis 5"
}
}
},
``` no errors in the console as well. tried to debug action remove mail and the recipe as well (even when it's not been registered in my kitchen) but mail still didnt trigger.
to make it unapplied, i did debug action MarkActionApplied Current Novaphene.PHFoodies.AdoboMail false then it said
[game] Trigger action 'Novaphene.PHFoodies.AdoboMail' has action string 'AddMail' which couldn't be applied: required index 1 not found (list has a single value at index 0).
other than that, i tried to AddMail for it to appear only to have the mail icon appear but it doesnt trigger any actual mail/letter.
on it :'> thanks tho!
I'm trying to convert my mod into the new format, and probably found out how to add the new items as gift tastes: Example
"Operation": "Append",
"Target": ["Fields", "Elliott", 1 ],
"Value": "Quirinea.JADistillery_Long_Drink",
"Delimiter": " "
},```
(putting an example of my attempts here so maybe they help someone else; maybe it should rather be ``` {{ModId}}_Long_Drink``` , but that seems to work neither). I tried to put tastes as a long list (with whitespace as delimitor, and that did not work, only the **last** one was picked.
But now I'd like to have some unique responses for certain gifts (originally changed Kent's loved gift response "My mom used to give me this when I was little" or the like, very unsuitable for booze!) but this doesn't work. Neither the format I used in the piece above:
```{
"Action": "EditData",
"Target": "Characters/Dialogue/Kent",
"Entries": {
"AcceptGift_{{ModId}}_Aged_Snow_Gin" :
"{{i18n: Quirinea.KentLove}}"
}
},```
This works, so it is not an obscure syntax error
``` {
"Action": "EditData",
"Target": "Characters/Dialogue/Kent",
"Entries": {
"AcceptGift_category_fish" :
"{{i18n: Quirinea.KentLove}}"
}
},```
What is wrong?
hey try flanking your code with ``` on either end to prevent the italics and missing characters
in the discord message i mean
i cant help with unique gift responses since i havent done it but if you show me what you were trying to do for the long list of gift tastes i can correct it, since that should have worked
Should they be all on the same virtual line? I saw someone else's mod with added gift tastes and they had used separate entries; I thought it should work with combined ones and got no error messages, but only the last entry taken. I had them each in a line. Actually if they cannot be like that, I rather make separate entries! having umpteen entries on a single line messy list is horrible to check and edit. I had them like this:
"Operation": "Append",
"Target": ["Fields", "Elliott", 5 ],
"Value": "Quirinea.JADistillery_Aged_Bourbon_Whiskey
Quirinea.JADistillery_Bourbon_Whiskey
Quirinea.JADistillery_Rice_Vodka",
"Delimiter": " "
},```
This gets quickly unreadable:
```{
"Operation": "Append",
"Target": ["Fields", "Elliott", 5 ],
"Value": "Quirinea.JADistillery_Aged_Bourbon_Whiskey Quirinea.JADistillery_Bourbon_Whiskey Quirinea.JADistillery_Rice_Vodka",
"Delimiter": " "
},```
I tried putting "Values" instead of "Value" and that wasn't correct.
it may be because you're separating them on separate lines instead of only separating with a space
and please do use the ``` symbols around your code
https://github.com/MizuJakkaru/Cornucopia/blob/main/[CP] Cornucopia More Crops/data/gifttastes.json
So here's a working example of adding multiple gift tastes in one entry
As for some other thing you commented on earlier, it doesnt matter if you write Quirinea.JADistillery or {{ModId}} since it will be the same outcome eithe way
!embedcode
You can embed code in Discord using a series of three ` :
```
Your code can go here
Even if not a haiku
Just an example
```
For syntax highlighting, add the language code on the same line as the first
``` (with no space, like ```json).
The usual codes are cs (C#) and json.
Sorry for technical mess. It is three backquotes, isn't it? Seemed to work after I copied them from your message, @drowsy pewter
i need help locating a file. im looking for the traveling merchant's portrait but i cant seem to find it. i looked for it several times in the portraits folder but havent found it. is it else where?
oohhh okay.
if i want to make a portrait for a character that doesnt have one, how would i go about that?
i just hope its not too complex to do
ty. i will check this out
oh these are so cute ;o;
now i want to make some for them all too lol
I think this mod does have C# component
my heart. i cant.. these are too precious. the mouses
yeah i just need to see the json stuff
ugh its prob gonna need some complex coding. rip
In c# is there a way to change the color of the placement indicator from red to green (like when holding tree fertilizer)?
I think that's a sprite in cursors
You would need to make your mod dependent on this mod I believe
the c# is only for edge cases
most of it is achievable with cp
depends on the npc
A fresh #SteamDeck modding intro for #StardewValley. Since my original guide was outdated with unnecessary tweaks.
Buy from Humble Store with my partner link to support the channel: https://www.humblebundle.com/store?partner=gamingonlinux
Follow me in these places:
Mastodon: https://mastodon.social/@gamingonlinux
Twitter: https://www.twitter.c...
iam using this method bro and this happening permission denied
please post in #1272025932932055121
this is for making mods
sorry for that man
Content patcher uses several different dictionaries and SortedSets to preserve its performance even under non-ideal conditions like patches being frequently added/removed, so I'd be inclined to say performance won't be much different as long as the two patches are actually doing the same total amount of work (adding same entries to same lists, etc.). It does this caching both at the asset level and at the token level from what I can tell. By "total work" I mean "difference between original game data and data after all patches are applied" regardless of the exact distribution of the work.
There's going to be some added cost because even hash lookups are not free and you're doing more of them, but this is likely not significant enough to worry about; what matters more is (a) update frequency and (b) which assets are patched in each update.
Quick question, are there any popular known mods that use this little area (the cliffs next to the playground) for any warps? Thinking of editing it so I can put my npc home here
Aren't there vanilla NPCs who path through there, like Jas/Vincent/Penny? Are you going to edit their schedules?
i remember a mod having plan, no idea if it's still a planned mod. You may get better answer in #modded-stardew
i would also suggest, if you do it, prepare backup plans in your mind
lot of modders try to find way to be in the valley and there's definitively situations of two modders wanting warp in same area
i decided to not be in the valley at all, to avoid most conflict, but for people doing it, i think it's good to keep in mind that you may never hear of a project before it's released RIGHT where you'd like to be
I was gonna try and be as out of the way as possible, but I might edit their schedules a tiny bit if it's not too much work (or I'll just choose a different spot lol)
that's totally fair.... i was thinking of just using bus locations for that reason. Still mulling it over actually
it has pro and con, so it's about seeing which ones matter the most
damn, guess theres suddenly so many people wanting to use that spot too, huh stares at my warp edit in that area for the nun oh wwell
Omg, I guess real estate in the valley is starting to get a little harder to manage
I might just stick with going the bus route then, seems a little easier LOL
tbh originally i went with a lil pseudo way in the cliff like this but i will probs just add the sign and make it so you warp when you touch it or w/e cuz thats way easier lmao
with just a sign that would make it even easier to slap anywhere on a cliff or something lol
but i think i saw someone else wanting that spot too idk who it was tho
OOOOO i didn't think of that that's smart
if that's the case i can probably just stick it somewhere in the forest or something ...
yeee, tbh i tried this sliff thing since i wanted to have the illusion people walk past there but ehhhh
but itll be a good while till i work on the nun more anyway since I am doing my big Fishmonger update first
That said, ealier I had though about version numbers again and ive been wondering....I basically turn my npc mod into a lil expansion with 4 more npcs, new locations etc...so would it make sense to go from 1.3.8 to 1.4.0 or actually 2.0? I know at the end of the day i can decide that for myself but, hm
aka would this update count as mayor or still just minor 
that def sounds major omg..... so much stuff
2.0.0
technically the update convention thing has a whole reasonning about the numbers
for frameworks it matters more
for content packs you basically do whatever feels right, and marketingly speaking, a big change like that is definitively worth being labeled as 2.0.0
yeah, makes sense. I always like to ask first cuz i usually eyeball with my stuff xD
(spotted this while searching messages for something else, those tilesheets are in fact just .pngs. Do with them what you will, they're uploaded like that because someone else wanted them. It was supposed to be a temporary solution, but you know how that goes. Eventually I will replace them with a proper tilesheets mod with a manifest, but I'm extremely busy and barely active)
I know you were looking about five million years ago, but that's the timeline I'm on these days ๐
I did end up just including them in my farm map, but please do let me know if you ever make them into a mod and I'll switch it to a dependency instead! ๐ I want you to get them points โค๏ธ Thank you for responding btw, no worries about timeline
They're up there to be freely used! I'm glad you got some use out of them! I work full time and study, so my activity here and nexus is sporadic at best. I mostly just hang out in a smaller stardew server and get nothing done lol
They've been up for a long time now, I think you're the first person I've seen get use out of them!
I'm off to go check out your farm map 
๐ค why is only one of my professions selectable?
I don't see any meaningful difference between my code and that of Archaeology or Cooking skills
That's probably going to be hard for anyone to answer unless you post the code.
is it a spacecore skill?
I'm using SpaceCore, I don't know what could be affecting this
is only one highlighted?
yep
or does clicking to nothing either?
Rain Dish is selectable
I'm adding all the professions correctly afai can tell ```cs
private void AddProfessions() {
Professions.Add(ProfCache.prof5a);
Professions.Add(ProfCache.prof10aa);
Professions.Add(ProfCache.prof10ab);
Professions.Add(ProfCache.prof5b);
Professions.Add(ProfCache.prof10ba);
Professions.Add(ProfCache.prof10bb);
ProfessionsForLevels.Add(new(5, ProfCache.prof5a, ProfCache.prof5b));
ProfessionsForLevels.Add(new(10, ProfCache.prof10aa, ProfCache.prof10ab, ProfCache.prof5a));
ProfessionsForLevels.Add(new(10, ProfCache.prof10ba, ProfCache.prof10bb, ProfCache.prof5b));
}```
Little Red Schoolhouse uses that area. For popularity, 72k unique DLs.
https://www.nexusmods.com/stardewvalley/mods/9695
ProfCache, fwiw: ```cs
public static class ChildIDs {
public static readonly string name = $"{ID}-name";
public static readonly string short_name = $"{ID}-name-short";
public static readonly string per_level = $"{ID}-per-level";
public static readonly string prof5a = $"{ID}-5a";
public static readonly string prof5b = $"{ID}-5b";
public static readonly string prof10aa = $"{ID}-10aa";
public static readonly string prof10ab = $"{ID}-10ab";
public static readonly string prof10ba = $"{ID}-10ba";
public static readonly string prof10bb = $"{ID}-10bb";
}
public static class ProfCache {
public static bool initialized = false;
public static BaseProfession prof5a;
public static BaseProfession prof10aa;
public static BaseProfession prof10ab;
public static BaseProfession prof5b;
public static BaseProfession prof10ba;
public static BaseProfession prof10bb;
public static void InitProfessions(Skills.Skill skill) {
prof5a = new BaseProfession(skill, ChildIDs.prof5a, "5a"); // Rain Dish
prof10aa = new BaseProfession(skill, ChildIDs.prof10aa, "10aa"); // Free Rain
prof10ab = new BaseProfession(skill, ChildIDs.prof10ab, "10ab"); // Rain Meal
prof5b = new BaseProfession(skill, ChildIDs.prof5b, "5b"); // Tailwind
prof10ba = new BaseProfession(skill, ChildIDs.prof10ba, "10ba"); // Tail Hurricane
prof10bb = new BaseProfession(skill, ChildIDs.prof10bb, "10bb"); // Wind Turbine
initialized = true;
}
}```
Definitely California. Real estate in the valley may be scarce, but it is cheap. Like, 100,000g to put in a cellar might sound like a lot, but that's only the cost of 1000 apples or 2 cookbooks. Imagine being able to buy a house for that in San Francisco.
What class is BaseProfession above? I don't see that in SpaceCore.
just a smol wrapper ```cs
public class BaseProfession : Skills.Skill.Profession {
public BaseProfession(Skills.Skill skill, string id, string name) : base(skill, id) {
Icon = helper.ModContent.Load<Texture2D>($"assets/skills/{name}.png");
}
public override string GetName() {
return helper.Translation.Get($"{Id}-name").Default($"{Id}-name").ToString();
}
public override string GetDescription() {
return helper.Translation.Get($"{Id}-desc").Default($"{Id}-desc").ToString();
}
public Action OnAdded = () => {};
public Action OnRemoved = () => {};
public override void DoImmediateProfessionPerk() {
OnAdded();
}
public override void UndoImmediateProfessionPerk() {
OnRemoved();
}
}```
basically just standardizing the i18n and icon names
the OnAdded/OnRemoved isn't even used ๐
Here's the actual constructor fwiw ```cs
public WeatherWitchSkill() : base(ID) {
if (!ProfCache.initialized) ProfCache.InitProfessions(this);
AddProfessions();
Icon = helper.ModContent.Load<Texture2D>($"assets/skills/icon.png");
SkillsPageIcon = helper.ModContent.Load<Texture2D>($"assets/skills/icon-page.png");
ExperienceCurve = new int[10] { 100, 338, 783, 1504, 2570, 4050, 6013, 8528, 11664, 15490 };
ExperienceBarColor = new Color(159, 151, 179); // Experience Bars mod support
}```
The ExperienceCurve is unfortunately ignored by the game afai can tell, but that's a separate issue
mhhh no idea. I'd try to debug the menu and see why it works in other skills and not yours
SpaceCore's version of this is kind of greek to me and MoonSlime's skill mods all have a lot of indirection in their wrappers making them a bit hard to follow, but... I didn't see any reference to RegisterSkill in what you've posted, are you calling that?
That's in Entry, yes
So it shows up but isn't selectable. What does not selectable mean in this instance? Is anything showing up in the SMAPI log?
Maybe your DoImmediateProfessionPerk or something in that path is throwing.
clicking it does nothing, hovering over it doesn't highlight green
clicking Rain Dish selects it and hovering over it highlights it green
DoImmediateProfessionPerk should be running the same code as RainDish since OnAdded isn't actually changed anywhere from the default no-op
Nothing in the log
10aa and 10ab are both selectable just fine
Pretty strange. AFAICT SpaceCore completely redoes the whole level-up menu, so whatever is going wrong is happening in here: https://github.com/spacechase0/StardewValleyMods/blob/c9f69c4e19c2bf0ef05693694b02d01e1b888fdd/SpaceCore/Interface/SkillLevelUpMenu.cs#L628
It makes sense that the color and click both fail since they're part of the same conditional branch.
Me, I'd pull the SpaceCore repo and put a breakpoint in there to see exactly what's going on.
๐ gonna try doing that later I suppose
I don't want to dive right into pulling other mods for debugging lol
Also I haven't even managed to breakpoint into my own method so far, so that's fun :D /sarcasm
That's the reason to put the breakpoint in SpaceCore, it's the code that runs before your own breakpoint would get hit.
Oh I meant in a completely unrelated method
I understand not wanting to debug SpaceCore though. Could try pinging Casey or just waiting.
short story shorter, my double-buff-length-in-rain profession was not working so I tried breakpointing, which didn't work, so I tried pulling the code out into a method and breakpointing that, which also didn't work: ```cs
[HarmonyPatch(typeof(Buff), nameof(Buff.OnAdded))]
class DoProf10ab {
static void Prefix(Buff __instance) {
TryDoubleBuff(__instance);
}
}
private static void TryDoubleBuff(Buff buff) {
if (Game1.player.HasCustomProfession(ProfCache.prof10ab) && Game1.isRaining && buff.millisecondsDuration != Buff.ENDLESS) {
buff.totalMillisecondsDuration = buff.millisecondsDuration *= 2;
}
}```
Also I forgot to check whether the buff is from food but besides the point lol
(I'm well aware most of my code is probably horribly unconventional/jank)
Just adding HarmonyPatch doesn't apply the patch, if that's what you were expecting; you have to register them in your Mod. (It's also not recommended to patch this way, you should use Harmony.Patch directly.)
[HarmonyPatch] attribute is just metadata for harmony.PatchAll (which, again, you shouldn't use). It doesn't have any magic by itself.
Why shouldn't I use it?
I guess. It's near zero extra effort to do direct patching though. Either way you still need to create the Harmony instance and call some variant of Patch.
I heard it used to be worse bc different platforms had different assembly names
Atm it's mainly risk of patch versions breaking your stuff
(You also really shouldn't do prefixes if you can avoid it; I don't think this needs a prefix, you can easily do it as a postfix)
I also fail to understand why postfixes are in any way more compatbile or safer than prefixes? Just some C#/Harmony jank?
Prefixes can fight each other and some might not run. Postfixes always run.
You have a void prefix tho, according harmony docs that always runs
Not sure if I trust that doc, but could be the case. Even so, it's still safer to run postfix because prefixes run before transpilers as well.
This particular Harmony patch is trying to manipulate the final outcome, which really should run very late in the process.
Yeah I personally like postfix more just as a style thing 
Like, what if some other mod or even vanilla logic slightly modifies the buff duration? It might overwrite your double-buff completely.
With postfix if I happen to want to know how the func I am patching changed state b4 and after, I can easily add a prefix to track that
So it's convenient to start with postfix by default
Random unrelated question popped into my head, is Game1.random instanced (e.g. in splitscreen)? Does anyone know?
Yeah
All statics are instanced in classes that have [InstanceStatics], except ones marked with [NonInstancedStatic]
(I believe, unless it was changed more after I finished with it)
Good thing I asked, this could have led to super-broken split-screen fishing.

(smol wrappers involved, nothing major) ```cs
internal static class Hooks {
private static Harmony h = new(ModEntry.ID);
private static void qpre(Type orig_type, string orig_name, Type pre_type, string pre_name) {
h.Patch(
original: Method(orig_type, orig_name),
prefix: new(pre_type, pre_name)
);
}
private static void qpost(Type orig_type, string orig_name, Type post_type, string post_name) {
h.Patch(
original: Method(orig_type, orig_name),
postfix: new(post_type, post_name)
);
}
private static void qtrans(Type orig_type, string orig_name, Type trans_type, string trans_name) {
h.Patch(
original: Method(orig_type, orig_name),
transpiler: new(trans_type, trans_name)
);
}
public static void hook() {
Type skill = typeof(WeatherWitchSkill);
qtrans(typeof(FarmAnimal), nameof(FarmAnimal.updateWhenNotCurrentLocation), skill, nameof(WeatherWitchSkill.DoProf10aa));
qpost(typeof(Buff), nameof(Buff.OnAdded), skill, nameof(WeatherWitchSkill.DoProf10ab));
}
}```
It's the transpiler itself that's crashing, which this code doesn't tell us anything about.
Whatever the problem is is in WeatherWitchSkill.DoProf10aa
// Transpiler FarmAnimal::updateWhenNotCurrentLocation
public static IEnumerable<CodeInstruction> Prof10aaTranspiler(IEnumerable<CodeInstruction> insts) {
MethodInfo is_raining_here = typeof(GameLocation).GetMethod("IsRainingHere");
if (is_raining_here is null) {
throw new Exception("GameLocation::IsRainingHere could not be found.");
}
bool found = false;
// look for environment.IsRainingHere() call
foreach (var inst in insts) {
if (inst.Calls(is_raining_here)) {
yield return new CodeInstruction(OpCodes.Callvirt, DoProf10aa);
found = true;
}
yield return inst;
}
if (!found)
monitor.Log($"Failed in {nameof(Prof10aaTranspiler)}\nWhoops", LogLevel.Error);
}
public static bool DoProf10aa(GameLocation env) {
return !env.IsLightningHere() && (
Game1.getAllFarmers().Any(farmer => farmer.HasCustomProfession(ProfCache.prof10aa))
|| !env.IsRainingHere()
);
}```
I just added the is_raining_here null check just in case lol
it's not getting hit
I don't understand, you've set your transpiler to DoProf10aa, but that's not the transpiler method.
Also, the transpiler seems to completely overwrite the entire method, so I'm guessing it won't work anyway...
does it??
No, never mind, I was skimming and missed yield return inst.
Ah
Just a weird way of writing transpilers, we generally use CodeMatcher
I was going off of Harmony's tutorial lol
In this case it's readable to me so w/e, I'll look into CodeMatcher if I ever need to make another
Yeah it's a whole side discussion but I think a lot of people would agree that Harmony's documentation/tutorials are actually the worst docs/tuts available for Harmony.
lol
I mean this is yielding your method and then also environment.IsRainingHere
Which is probably why it is invalid IL
Anyways
Callvirt is also wrong, etc... but one step at a time haha
It was Call at first
I'm also going to say the method naming is giving me a minor headache
Call is correct for static methods
And I must be off. Cherrio!
Both result in InvalidOperationException: Unexpected unemittable operand type lol
Have a nice day!
Yeah, the naming definitely makes things confusing too, but I don't get paid to pick nits.
...actually I do, just not here.
Mh, smol mod, learning how to make custom skills, haven't exactly figured out any conventions for myself yet
Anyway, "unemittable operand type" is because the operand needs to be a MethodInfo, and it looks like you're just passing the method group itself (surprised it even compiles).
Ah, method groups are implicitly convertible to object (something I've never attempted once in... many years) and VS gives a warning: "Converting method group '...' to non-delegate type 'object'. Did you intend to invoke the method?"
So yes, watch those warnings.
The green underline might be wrong. But usually it's right.
I saw the warning but the suggestion ("Did you intend to invoke") was wrong so ignored it lol
For anyone trying to figure out how to make a mod to use the rocky beach in the forest, there's clear tiles on the buildings layer that keep you from being able to walk on it, not any tile properties. You can delete those if you're patching a map area based on the vanilla map or modifying the vanilla map directly ๐
Yeah, there's quite a lot of maps with invisible Buildings tiles
oh, well, i guess this was too obvious for me to suggest, something in the wording made me think you did already
glad it's solved then
Check it out - still a few bells and whistles to go, but it is actually working.
omg is that a mermaid,,,,
yeah I'm making a One Piece mod haha
swapping all the storylines and characters and adding a bunch of OP related assets
there's boar and turkey you can hunt so Luffy doesn't get sad ๐คฃ
BOOOAR
THIS IS GLORIOUS
that's so cool what
It's been fun but it's going to take ages because we're adding so much content
I have a couple people helping me
Huh, the game really struggles drawing finer detail images in splitscreen.
Can't say I've ever noticed that before though
very neat
great to see you got the RNG prediction going with it, the overlays look quite nice too!
@velvet narwhal: fix the event wiki addins (48h ago)
Oh, the overlay's just a translucent item sprite. This is a different thing vs. the distribution prediction you were discussing in #programmers-off-topic, it's the real fish.
...at least, some of the time. It's misbehaving in MineShaft for as-yet unknown reasons.
whats the floating book from? ๐
Looks like the magic book sprite from unlockable bundles
are you only patching the base getFish or are you patching MineShaft's getFish as well?
I'm patching GetFishFromLocationData as well as MineShaft.getFish, but I found one call that's leaking through, via ItemQueryResolver (but I don't know why, because ItemQueryContext.Random is set to the replayable instance and works fine on outdoor maps).
(This probably isn't going to make any sense to anyone who hasn't seen the code - and even many who have, lol)
it's an edit of a commission for UB made by an artist on fiverr by the name of Ley
And I'm finding that if I emit a stack trace from the code, it seems to have the original lines and not the decompilation, which makes sense but is unfortunate for me.
At least you can see the original lines in C#+IL view in ILspy
I can?
the getfish in mineshaft seems to just use Game1.random directly?
Oh, there's a "show line numbers" buried in the options.
I know. They all do. They've been transpiled not to.
got it, since you mentioned ItemQueryContext.random
Yes, that would normally be invoked from GetFishFromLocationData
Which normally creates an ItemQueryContext using Game1.random and has also been transpiled not to. So it's curious.
Is it possible for the random instance on an ItemQueryContext to get overwritten?
Ohh, I see it... it only creates the new ItemQueryContext if it doesn't receive one in the method args.
Although I can never find any instance of it being called with any value other than null, so... hm.
idk if this is the right place to ask this, but does anyone know somewhere (website, youtube video, etc) that has information on how to make your own mod?
i'm so inspired by everyone here i just wanna try and see if i can make my own!
!startmodding
Making mods can be broadly divided into two categories:
- Content packs are formatted text files, and don't need any programming knowledge. They can add/edit NPCs, maps, new items, shops, and more. To get started, see the list of framework mods, the wiki tutorial for Content Patcher, and there might be relevant guides on the tutorial wiki.
- C# mods use programming code to change fundamental game mechanics. See getting started with C# modding.
Usually itโs easier to start with making content packs, since you don't need to learn programming.
and welcome! what kind of mods are you looking to make?
as mentioned in the link, you either only need to use write JSON files with content patcher, or diving a little deeper with C# coding
thank you, and a custom npc!!
NPC modding definitely needs a bit of effort, though not overall difficult. There's a great guide here to get started: https://stardewmodding.wiki.gg/wiki/Tutorial:_Making_a_Custom_NPC
I don't think these ILSpy line numbers are accurate per the stack trace lines.
that's my experience as well, though I generally assumed it was a Linux thing. you definitely need to read the IL and do the mapping yourself
Oh, I can map IL to the decompiled C# well enough, but the line in the stack trace is something else altogether (it's the real actual line number in the real source code).
Even shows the original file path to D:\Gitlabrunner\...\ConcernedApe\stardewvalley
thank you!!!!
This would be a real nice time to be able to step through the decompilation. @ivory plume, can I get access to that private repo? It's supposed to be debuggable, right?
!npc we got this updated one now
Keep in mind that making NPCs is a complex process that requires learning many different aspects of Stardew modding.
Here are a few links that can help get you started on all that you need to know:
-
Tiakall has a great tutorial on making a custom NPC for 1.6:
https://stardewmodding.wiki.gg/wiki/Tutorial:_Making_a_Custom_NPC -
Custom NPCs received many improvements with 1.6. For changes made, see the migration guide:
https://stardewvalleywiki.com/Modding:Migrate_to_Stardew_Valley_1.6#Custom_NPCs -
Some information on the NPC wiki page is still relevant:
https://stardewvalleywiki.com/Modding:NPC_data
Just make sure you're checking the migration page and tutorial first as this page still has outdated information on it as well. -
Aviroen has put together a template that will allow you to easily create a romanceable NPC:
https://stardewmodding.wiki.gg/wiki/Npc_template
The decompile repo does build and run, yeah. If I recall, line numbers won't be identical between your own build and the build on Steam, but that shouldn't matter too much if you just need it for debugging.
If I can step through it then I won't need the line numbers.
Yup!
The leak is baffling to me. I can clearly see where Game1.random is coming from, and I can also clearly see via [HarmonyDebug] that the method's been patched correctly not to use it. The only explanation is that something is calling GetFishFromLocationData with an existing ItemQueryContext, except that it doesn't, because I'd be able to see that in the stack trace too!
thank you so much!!
Hey guys, I want to make my own first mod, I want to be able to assign inventory slots to d pad on controller or any button player wants, does something like this already exist? I dont want to j ust recreate something thats already out there.
so like row 2 slot 10 to right on dpad, etc
im a python architect and a c# lead so i think i can hang , just wondering if
A. THis already exists (couldnt find it if it does)
B. If this is even possible
I think I may have found the culprit.
public static ItemQueryResult[] TryResolve(
case ItemQuerySearchMode.RandomOfTypeItem:
{
ItemQueryResult result2 = Game1.random.ChooseFrom(results.Where((ItemQueryResult p) => p.Item is Item).ToArray());
results = ((result2 == null) ? LegacyShims.EmptyArray<ItemQueryResult>() : new ItemQueryResult[1] { result2 });
break;
}
}
This implementation does not check ItemQueryContext.Random, it just goes straight to Game1.random. Is this a bug in ItemQueryResolver? (Any of the 1.6 devs happen to be online?)
The other overload of TryResolve does check the context which is why I think this is a bug: Random random = context?.Random ?? Game1.random;
thats amazing
definitely worths pinging Pathos I think
Yeah... I already pinged him once for the repo access 5 minutes ago, hate to spam pings.
For now I'm going to patch in my "bug fix"
It appears there's an issue with #$action trigger actions where using it at the start of dialogue causes text to act weird. I'm not too sure about the specifics of this issue (I do know that it ends dialogue instantly if there's a #$b# textbox right after) as I'm reporting it on behalf of a friend, but does anyone know if it's a known issue Pathos is hopefully aware of?
1.6.9 patchnotes has this:
Fixed $action dialogue command not working after a #$b# break.
Fixed empty dialogue box shown if a command is between #$b# breaks.
Good to hear, thank you.
don't think anything like this exists, no. the getting started with C# guide is useful: https://stardewvalleywiki.com/Modding:Modder_Guide/Get_Started
but disclaimer, I don't know if remapping the dpad to not be movement keys is easy or possible
thanks
if you're on steam it might be easier to just use Steam Input's remapping
im ok with it being like... button combos too, ima have to think about it
well i want it to go to specfic inventory index
glad to see that the index doesnt change based on selected row
and remap the dpad to be any macros you want
so you can bind the dpad to be keyboard buttons and bind those instead
Hi, quick question! For the life of me I can't get my schedule to work for my npc, once she spawns she stays at her spawn point. I'm probably being stupid and my syntax is wrong or something, but can anyone help me with this?
{
"Changes":
[
{
"Logname": "Nemona Schedule",
"Action": "EditData",
"Target": "Characters/schedules/NemonaWolf",
"Entries": {
"Mon": "610 Custom_Nemona_Attic 3 3 3/0900 Custom_Nemona_Room 9 8 2/1800 Custom_Nemona_Room 5 7 2",
"Tue": "610 Custom_Nemona_Attic 3 3 3/0900 Custom_Nemona_Room 9 8 2/1800 Custom_Nemona_Room 5 7 2",
"Wed": "610 Custom_Nemona_Attic 3 3 3/0900 Custom_Nemona_Room 9 8 2/1800 Custom_Nemona_Room 5 7 2",
"Thu": "610 Custom_Nemona_Attic 3 3 3/0900 Custom_Nemona_Room 9 8 2/1800 Custom_Nemona_Room 5 7 2",
"Fri": "610 Custom_Nemona_Attic 3 3 3/0900 Custom_Nemona_Room 9 8 2/1800 Custom_Nemona_Room 5 7 2",
"Sat": "610 Custom_Nemona_Attic 3 3 3/0900 Custom_Nemona_Room 9 8 2/1800 Custom_Nemona_Room 5 7 2",
"Sun": "610 Custom_Nemona_Attic 3 3 3/0900 Custom_Nemona_Room 9 8 2/1800 Custom_Nemona_Room 5 7 2"
}
}
]
}```
And part of my content.json, just in case
``` {
"LogName": "Nemona Schedule",
"Action": "Include",
"FromFile": "assets/data/schedule.json"
},```
I don't think it's a pathing problem, as I'm pretty sure she should be able to access all the coords I've put down? But I'll check again if it isnt a syntax issue
schedules req a blank load, iirc
a blank.json loaded ihnto characters/schedules/name -> then editdata
(once its done, sleep a day or two. You don't need all week schedules but you kinda need a spring one. You can use goto for schedules that are duplicate of another)
I do have a blank load (I think it works?), so should I remove this part of my content.json then?
Used to crash if you didn't have a spring
ohhhh interesting...
Spring is like the default if all else fails, so you need it, but also it's what the game uses to send NPC's home at the end of the day
spring is used by default by some game things
for festivals and such
.net core 8.0 is only choice i have, do i have to download the 6.0 SDK?
Yep
You can throw a <LangVersion> in your PropertyGroup for the project settings, if you need something from a later version than 6 provides
But your project needs to target 6 as the TargetFramework
im ok with 6 just trying to get it to showup in the available versions when making proj
nice ye3ah just needed SDK
how is it that I first unpacked the content files like 2 years and I ONLY JUST realized that the order of the objects in springobjects.png and the object IDs are related....... so much time searching.... 
(me too, just last week)
had to get up from my desk and walk that one off lol
when the feeling of "bruh" is so strong you need to take a lap
what made it click? for me it was counting the sprite index for the mermaid pendant
I was grabbing sprites so I stop procrastinating on making Nexus images for when I finally upload the thing I'm working on and I went "oh that's neat, items 414 and 416 are right next... to... each other..........."
and then I was like ".....those are the 414th and 416th sprites on this sheet aren't they."
Just have to avoid working with anything from 1.6 to keep that true
aren't 1.6 items strings?
Well they're all strings, but yes I know what you mean
words my bad
it was more clear up until 1.6: the object ids are/were named Parent Sheet Index, which is very self-explanatory lol
Well, as long as you have context for what that is lol
SpaceCore extended tilesheets flashbacks
(i swear we say anything pre 1.6 and casey gets war flashbacks)
what the heck, i cant find the pathoschild nuget package
Flattened pufferchick. Oh dear
ahh im trying torublehsooting now
Casey really did jump into the thick of it with this game
does casey have the highest count of frameworks?
the thickest of it was pre-1.3 from the sounds of it haha
Probably aedenthorn
The MP mod was fun to make back in 1.07
That was before we had Harmony
nice adding the source did it
earlier than i thought ..
I've been modding since the year of release!
It's how I know so much about the code ๐
i knew so much about the code, and then they changed what the code was. and it'll happen to you, too
Does that mean your hobby was the PS Vita before
max is gonna get into the knitting scene
What the hell is a ps vita
- Sony (probably)
Ok, discord, that's what I wanted
is ItemRegistry.AddTypeDefinition something we can use to have custom subclass items created without patching everywhere?
Yes
But custom subclasses still have to be registered with SpaceCore for the serializer
like if i make some RGBItemDataDefinition for raised garden beds
well that's just job security
I used it for necklaces in the initial 1.6 Moon Misadventures port
(That is now dead because MMR is gonna be a thing that works pretty differently)
me, too forgeful for my own good: "why the hell is this patch im applying to the dailyluck getter seemingly not doing anything. why is my luck stuck when im not doing anything with the patch at all??"
Cool modders use debug commands and console code instead of CJB Cheats
(I'm joking)
i'm too lazy to do debug speed 10 10000 every morning
easier for me to give myself inventory rows and maximum speed with the cheats menu
Oh I did that too but with gift limits
(Though I legitimately don't use CJB mods)
(You are a cool modder though!)
i think i also did this with gift limits when i first made my book mod too
do we extend baseitemdatadefinition or implement iitemdatadefinition?
thanks, i'm pretty clueless about most of the new stuff still
No worries
Here's what I did for the necklaces: https://github.com/spacechase0/StardewValleyMods/blob/develop/MoonMisadventures/Game/Items/NecklaceDataDefinition.cs
I did 80% of my mod updates and then was like "fuck this shit I'm gonna go design knitwear now"
So I still remember
(That code was during the alpha, so a few things might have changed since then)
i was hoping i could make all the interconnecting object stuff from garden beds into something more generic/inheritable so i could have swimming pools in the same mod, but i couldnt figure out how to have OutdoorPot : SDV.IndoorPot & InterconnectingThing as well as SwimmingPool : SDV.Object & InterconnectingThing
i did 1 mod update and didnt post it
Could interconnectingthing be an interface with default methods?
i tried interfacing it, but it was too coupled. it was awful
even after unchecking the max daily luck thing this patch still doesnt wanna actually add to the luck it seems... but it can set it just fine. im so over all this IL stuff
i think giving up is more accessible & future proof than mixins
Have you considered learning Rust instead
im waiting for Oxidization personally
I don't know
i read a whole lot about people learning rust and not a lot about people using rust
The Carbon fan might show up
rust mentioned, activating proselytization mode
Anyways
oh no
See y'all!
ciao, nice seeing you
Carbon's only purpose is to write new C++ interopable code without wanting to shoot yourself. It's only made out of necessity, I doubt there are actual Carbon fans
Nyah nyah I beat the MineShaft. And can now see with heightened senses just how horrifically punishing the mine fishing luck really is.
searching making-mods just doesnt give the same emotions
But it works. I'm not sure if I want to massage the random distribution a bit (there is literally no difference which tile you fish, 9 times out of 10) or just let this be a targeted-bait-saver.
I'm thinking of giving the RNG a little nudge away from trash in some scenarios like targeted bait or repeated prior trashes. Ironically, level 100 of the mines is way more forgiving; not sure why, but the bizarre way the RNG is set up between MineShaft and GameLocation means that between the Lava Eels and Cave Jellies, you can get both very consistently and get 10+ of each in a day.
(I know that L100 has intentionally more forgiving logic for jellies, but that doesn't explain why Lava Eels are more common than Ice Pips other than "freaky math stuff")
Lore reason: Ice Pips has to fight the Ghostfish for resources, while the Lava Eels reigh supreme in their realm
Re this carbon thing, the joke may have gone over my head, but I'm pretty sure Carbon is for Rust, the game, and not Rust, the language?
Oh, when I searched I found https://carbonmod.gg/ which seemed the most on topic.
It is made to be the TypeScript to C++'s Javascript basically
Same with this Oxide thing, it seems to refer to a Rust that is definitely not the Rust language.
Rust the game
over in the rust server, they're having a discussion over something that was made for stardew valley the game, not stardew valley the programming language
cs note: sdv is short for std::vector 
please no, my brain was so addled with >> << when i re-attempted my goose meme mod that i had to take a walk
I have no clue how I got that original screenshot. Somehow it worked, but it must have been a fluke, because it seems that the tile position/distance from land actually makes no difference whatsoever to what fish will be hooked except for legendary catches and a couple of one-off scenarios like the submarine.
So I accidentally created a real repeatable tile distribution, and now that I've fixed all the bugs, have no idea how to recreate it.
How do I make a c# mod read the data set in a content patcher config schema?
Depends on the data
Do I need to look into API?
For instance if it's an object you just get ParsedItemData with ItemRegistry
(and of course, mere minutes after I say this, I run into a situation where they really are different again closer to shore... maybe it's something in the GSQs that I don't understand)
The config schema It's enabling/disabling a trigger action from working but I wanted my C# mod to detect it
Hm it might be better to make the config menu in C#
Yeah ok
And expose tokens with CP api
I'll do it that way
checking for the trigger action ID (or whatever else is affected by the toggle) might be the easiest route
So this isn't the end of the world, but I'm finding these overlays draw over the fishing minigame, as in this example.
Is there some way to get them to draw underneath in the RenderedWorld event or is that simply too late? I've tried playing around with layer depths but doesn't seem to matter how low or high I set that.
Hmm well I have these rings I added. they work with trigger actions when unequipped using context tags but I also want them to work When equipped.
I was only able to add my custom buffs with C# due to the custom companions mod incompatibility with the feature
So far it works I have a config that the player can set if they want the rings to work when equipped or unequipped but when it's set to unequipped id still like the buffs to work when the unequipped config value is enabled
Cus when I set it only one works at a time ๐ค๐
Starting to 
could use RenderingStep maybe? #making-mods-general message
or RenderedStep
Yep, that's what I ended up doing; World_Background step seems to work well. SMAPI says no, but my eyes (the goggles do nothing) say yes.
Iโm trying to figure out how make a content pack to edit Krobusโ sprites and Dialogue. Does anyone have any guides on how?
Just need content patcher
!startmodding
Making mods can be broadly divided into two categories:
- Content packs are formatted text files, and don't need any programming knowledge. They can add/edit NPCs, maps, new items, shops, and more. To get started, see the list of framework mods, the wiki tutorial for Content Patcher, and there might be relevant guides on the tutorial wiki.
- C# mods use programming code to change fundamental game mechanics. See getting started with C# modding.
Usually itโs easier to start with making content packs, since you don't need to learn programming.
Downloading an existing mod that edits Krobus is a good way to start as well
I got this error on XNBhacker thing.
Unhandled exception: System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types.
Could not load type 'StardewModdingAPI.IManifestPrivateAssembly' from assembly 'SMAPI.Toolkit.CoreInterfaces, Version=4.0.8.0, Culture=neutral, PublicKeyToken=null'.
at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
at System.Reflection.Assembly.GetTypes()
at StardewValley.LocalMultiplayer.GetStaticFieldsAndDefaults() in D:\GitlabRunner\builds\Gq5qA5P4\0\ConcernedApe\stardewvalley\Farmer\Farmer\LocalMultiplayer.cs:line 121
at StardewValley.LocalMultiplayer.Initialize() in D:\GitlabRunner\builds\Gq5qA5P4\0\ConcernedApe\stardewvalley\Farmer\Farmer\LocalMultiplayer.cs:line 92
at StardewValley.GameRunner..ctor() in D:\GitlabRunner\builds\Gq5qA5P4\0\ConcernedApe\stardewvalley\Farmer\Farmer\LocalMultiplayer.cs:line 440
at StardewXnbHack.Program.CreateTemporaryGameInstance(PlatformContext platform, String contentPath) in /home/pathoschild/git/StardewXnbHack/StardewXnbHack/Program.cs:line 327
at StardewXnbHack.Program.Run(String[] args, GameRunner game, String gamePath, Func`3 getLogger, Boolean showPressAnyKeyToExit) in /home/pathoschild/git/StardewXnbHack/StardewXnbHack/Program.cs:line 149
System.TypeLoadException: Could not load type 'StardewModdingAPI.IManifestPrivateAssembly' from assembly 'SMAPI.Toolkit.CoreInterfaces, Version=4.0.8.0, Culture=neutral, PublicKeyToken=null'.
Which version of XnbHack did you download?
1.1.1 for windows
You want 1.1.0
Invite sent! See the repo readme for more info when you get access, and feel free to ask if anything is unclear.
so my mod works, does anyone mind helping me with the icon that shows in my popup dialogue
also i hjave one other issue, when i try to check for key COMBOS it doesnt seem to pick it up
like if i set it to trigger for F1 , no problem
if i set it to trigger for F1+F2, problem
but thats ok with me becausae F1 is definitely deliberate enough, just when it comes to console i wanted to make it like idk, R1+Back or smth
are you using KeybindList like what's detailed here? https://stardewvalleywiki.com/Modding:Modder_Guide/APIs/Input#KeybindList
yeah i tried IsDown
part im having trouble understanding is this
private void OnButtonsChanged(object sender, ButtonsChangedEventArgs e)
{
if (this.Config.ToggleKey.JustPressed())
{
// perform desired action
}
}
why is thtere no if (e.Button) or whatever
JustPressed checks if the buttons are pressed in the current tick, presumably the same tick OnButtonsChanged was raised
yeah, there is the equivalent of if (e.Button), but not in this example. JustPressed is most likely what you want to use, which is why it's given here
yeah im just not familiar with using this sort of thing, but am familiar with stuff like e.Button with WinForms projects
vuz i was trying the JustPressed way and wasnt working
Maybe you can post your code so ppl can take a look?
yea ima do that
{
if (!Context.IsWorldReady || Game1.activeClickableMenu != null)
return;
// Debugging: Output which button was pressed
Monitor.Log($"Button Pressed: {e.Button.ToString()}", LogLevel.Debug);
// Identify the current player (works for split-screen)
Farmer currentPlayer = GetCurrentPlayer();
if (currentPlayer == null) return;
// Handle the key binding if we're in binding mode
if (isBindingMode)
{
BindSlotToButton(e.Button);
return;
}
// Ensure the current player has key bindings
if (!playerSlotBindings.ContainsKey(currentPlayer.UniqueMultiplayerID))
{
playerSlotBindings[currentPlayer.UniqueMultiplayerID] = new Dictionary<SButton, int>();
}
var bindings = playerSlotBindings[currentPlayer.UniqueMultiplayerID];
bool suppressed = this.Helper.Input.IsSuppressed(SButton.LeftShift);
if (suppressed) {
Monitor.Log("Shift is pressed", LogLevel.Debug);
if (this.Helper.Input.IsSuppressed(SButton.S))
{
Monitor.Log("Shift + S is pressed.", LogLevel.Debug);
}
}
if (this.Helper.Input.IsSuppressed(SButton.S))
{
Monitor.Log("Just S is pressed", LogLevel.Debug);
}
// Check if F1 or ControllerBack is pressed to enter binding mode
if (e.Button == SButton.F1 || e.Button == SButton.ControllerBack)
{
EnterBindingMode(currentPlayer);
return;
}
// Handle the inventory slot selection for the player if not in binding mode
if (bindings.ContainsKey(e.Button))
{
int slot = bindings[e.Button];
SelectInventorySlot(currentPlayer, slot);
}
}```
me hthat looks crappy hold on ill use my sharex backend
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
ook so , itos working on the Monitor.Log($"Button Pressed: {e.Button.ToString()}", LogLevel.Debug); linoe
and the F1 to go into changing the setting works too
but the IsSuppressed bollean does not
do i maybe need a special event listener somewheres?
this is what i have up above
iheres what i think is happening
i think its getting sent into that code every button press
so its not sending in both presses
you should use ButtonsChanged
is this correct?
note: you want to use Helper.Input.IsDown ("Get whether a button is pressed"), not Helper.Input.IsSuppressed ("Get whether a button is suppressed, so the game won't see it")
oh
oof
i did have IsDown before
i think the issue, however, with IsDown not working too, is that its a key combo im trying to get
it works on single key
did you try KeybindList.JustPressed as suggested before?
KeybindList oh i missed that part im sorry
Oh i see the KeybBidndList.Parse
Ahh so i can do KeybindList.JustPressed
consider using SButtonState, e.g.:
bool isComboHeld = this.Helper.Input.GetState(SButton.F1) is SButtonState.Held && this.Helper.Input.GetState(SButton.Enter) is SButtonState.Held;
my hero
not a hero yet haha, i haven't tested it at all and i don't know where you'd put it, but i've seen button state around
if you ctrl-click on any SButtonState in visual studio you'll go to the definition, which has the following info on each state:
/// <summary>The input state for a button during an update frame.</summary>
public enum SButtonState
{
/// <summary>The button was neither pressed, held, nor released.</summary>
None,
/// <summary>The button was pressed in this frame.</summary>
Pressed,
/// <summary>The button has been held since the last frame.</summary>
Held,
/// <summary>The button was released in this frame.</summary>
Released
}
you might have to check for pressed OR held on both keys if you check from OnButtonPressed, otherwise should be fine to check held on both keys from OnButtonsChanged
yeah my VS was acting a fool earlier and ctrl click died on m,e
but now it is working good point
so change the even t to OnButtons CHange
i think so
do you need it? you can check any buttons you like
e.Pressed used to be e.BUtton
yeah to bind that to the slot
when they come thru in that context
OnButtonPressed is reacting to a specific button changing to SButtonState.Pressed, while OnButtonsChanged will give you a place to check any buttons when any of them change state
if you're only interested in whether your combo is active or inactive, just check those buttons
yeah but i dot know which button to check
so i need both
i need both on button pressed
and on button changed
on buttons changed*
what's your overall task?
i think i do need both]
ok so , user has slot 7 highlighted, they press L1 + R1, it says ok now binding slot 7, choose button
and then they press like, dpad right
and then wheneever they press dpad right from then on, itll take them to that exact slot
no matter what row youre on
it works already too which, since i spend a lot of time in the mines for my gf, and i hate getting flustered over where my damn sword is, im so stoked
if u r use controller try this https://www.nexusmods.com/stardewvalley/mods/25257
Thanks! It's pretty clear and I was able to run it. Is it normal that the generated IL is a bit different from the released game? I noticed one of my transpilers failing and saw that it's because the IL's different even though that part of the source looks pretty much the same as a local decompile.
da,mm., we use both tho
thats os nice tho haha
and pretttyyyy much what i was setting out to do, but at least ion mine i can set any slot to anything, so im ok with it
what is bopt
i want quick sword button, kinda like how in fortnite i have Q set to shotgun
excuse my sloppy typing
the StardewValleyAPI is soooOoO good ,
Yep, due to two issues:
- Decompiling the IL will produce an approximation of the original C#, which may then get recompiled into slightly different IL.
- And the released game is compiled in release mode, so compiling in debug mode will produce unoptimized IL.
Ah, I'll bet it's the debug mode more than the other thing. But thanks, that clears it up.
Pathoschild youre literally a legend to me. Thanks for your dedication bro.
(As far as this controller convo - the D-pad is already used for actual character movement? But hey, two cakes and all that, maybe it'll be what some players want.)
there's the analog stick
i dont mind, so like, even if it moves me up AND pulls out my sowrd, if it only moves me up an inch, idc
if you mean like not making it move the player, then yeah there's no good answer for it
but i think next step, which would actually be WAY cooler, would be to allow user to set button combos
Right, and I use the stick, though hijacking the d-pad still seems a little more opinionated than hijacking the triggers.
(other than Steam Input)
so like imagine, i have it so they hold back button and hit face button
hold back hit x, assigned slot 1
No, if you really want to disable player movement using the d-pad then that's totally possible to do.
really?
how
id love to do that just so i can use it for my quick slots
or maybe for my mod id have it only disable if they set something to it
thatd be clever
does anyone happen to know where this behaviour is handled in the game code? specifically, left-clicking a placed bigcraftable with any other held object causing it to pop-out and be picked-up
Just a matter of intercepting the game's responses to it. Might be able to do with SMAPI's input suppression, if not then you have to reflect on the internal XNA input state.
it doesn't seem to be in checkForAction, placementAction, performUseAction, performDropDownAction, performRemoveAction, performToolAction, or performObjectDropInAction on object/item
that doesn't look like base game behavior?
Only place I've seen that in base game is placing a big chest over a chest (or vice versa) and that's probably hardcoded on the chest.
idk what oyu guys are talking about but ima just say "shots fired"
huh
do a harmony summary maybe
ahh so yeah yall goin deep as f with these mods
gotcha
kubernetes for stardew mods lmao
maybe it's my own code from years ago in here somewhere
^^^^
no this is just extra fancy reflection
was going to say it, but didnt want to
it's ok, i didn't want to either
its always old code
Input suppression should work for disabling player movement using DPad, no need for Harmony.
hmmmmmmmmmmm so i would i catch my event then supress?
Yep.
so sick
Button sure has been real quiet since we started talking about suppressing buttons
(i just spent far too long trying to debug why my dynamic harmony postfix was concatening the result string twice before realizing i was testing it on GameLocation.DisplayName... which gets the displayname from the parent location first if its null. which obviously gets its own postfix concatenation before being concatenated again in the actual location
)
ive been in IL hell
I thought I distracted you from your IL hell. Couldn't stay away, huh?
which is a kind of suppression i think
so i CAN make it situational. All i have to do is if (DPadDirectionsList.Contains(e.Button)) { supress thing }
i can be distracted away from the more advanced patches but i wanted to finish at least letting you change the result in a postfix since i thought that would be easy
and technically it was easy, i figured it out hours ago but thought i didnt bc of that aforementioned hell
IL (intermediate language) is C# bytecode
its like one layer above assembly code
u can read about it on microsoft's docs prob
intermediate language, i forgot those words
(maybe a couple layers idk)
Uh, ok... IL is not "binary" any more than everything on a computer is "binary".
IL is sometimes the only (good, respectable) way to make a mod do something you want it to do
