#Leaf (forked from FabricMC/fabric)
1 messages ยท Page 2 of 1
I don't even think I can put this in a lib lol
actually I could but it'd have to be adding mixins to every enum
ill get it working and send something
I can see it in the debugger, however in Lua it just returns nil ๐ญ
hmm
I am not sure how the code there fully works, because iirc enums need a field, object in the $VALUES, and code in the clinit, or thats how I did it in the bytecode patch for the DebugLogType
I mean you are adding the field too, this should work
probably another oversight with kahlua maybe?
you are exposing the class too right?
LinkedFluidContainer.class is exposed yes, I can access it in Lua
i don't get how kahlua could possibly miss it if it's being injected during class compilation
if the enum member is inserted properly i don't get how it could ever be filtered out, even accidentally
I think I've found a workaround for this.
I can now access it via ComponentType.FromClass(LinkedFluidContainer.class) in Lua. To do that I recreated ComponentType.<cinit> code in a mixin and called it manually before returning from addVariant constructor.
It's a bit of a mess, but at least it works - now I can proceed, instantiate the component and add it to the entity
hmm shouldnt need to manually call clinit though
since addVariant is calling the enum's constructor from static, this should basically emulate what is normally done
Without that, I just get Undefined component, which means the new component class isn't in the internal arrays that are updated in clinit
hmm true, its probably getting inserted at a later point or something, im doing some testing rn as well because why not
hey, just a note that you can hotswap regular classes of yours by just recompiling the project (would recommend this plugin for that https://plugins.jetbrains.com/plugin/14832-single-hotswap)
AND hotswap mixins live (a bit jank over normal classes but it works): https://wiki.fabricmc.net/tutorial:mixin_hotswaps
should probably get that pinned aswell ๐
I really wish there was a better solution for having to put the run configs workingDir to the gradle cache in C:\Users\user\.gradle\caches\leaf-loom\<version>\extracted It's actually really really annoying
because for example, steam workshop mods get downloaded to that
anything that relies on workingDir (aka the relative path of the java) will do this, I needed to set it here because otherwise the game wouldn't start since the dlls and jars required for the game are in that folder. on top of that, I couldn't even change the user.dir after the fact because JVM caches it
Anyway, you can see here this is whats actually happening
It's kind of fooling the enum, since it's not actually a type ACC_ENUM but it's just a regular field with its value in $VALUES
oh my god lol @tropic stirrup make sure your enum field isnt private...
thats why I couldnt access mine personally from lua, you might have a different issue still
It's private
otherwise, I get a ton of errors
hmm yeah, bc you cant have a public static member in mixin class,....
but it needs to be public for the exposer to expose it
normal enum fields are public static final, but we can only have private static final
surely there's some way around this
the only way I can think of is by getting the field via indexing values with the ordinal from lua, but this is not ideal
you know what, can you try
private static final EnumClass ENUM_NAME_INTERNAL = addVariant(/*...*/);
@Unique
public final EnumClass ENUM_NAME = ENUM_NAME_INTERNAL;
im hoping, kahlua will see ENUM_NAME and go "yippeee let me expose that for you" and then you construct the enum with the internal name behind the scenes, but you can still access the enum through the public name if you want
though also you should make all your fields (except $VALUES) in that enum mixin unique so they cant ever overwrite
Do you guys are trying to create new components like fluid components ?
thats what gigawatte is trying to do
Yeah
Trying to preserve TIS way of implementing it to maintain overall compatibility
i see, as i guessed it's not 'really' adding to the enum properly
yea, but does actually work as intended, and I believe in older java versions this was how it was done internally in Enum
maybe possibly dont take my word on that tho im not old enough to know for sure ๐
so long as it's in values array it should be ok
Sadly, it's still nil
hmm, if removing @Unique doesn't help then its certainly a Kahlua issue
make sure that ComponentType is exposed, and not your mixin class
because your mixin class gets placed in ComponentType
but other than that I have no idea
@full mountain does kahlua require static fields to be exposed??
yes
thats nice i guess ๐ญ
ok so the only way then is either to make that not true by modifying kahlua, or do ComponentType.values()[ordinal] from lua I guess
how would you expect a non-static field to work here anyway?
we're not accessing it through an instance
it can be worth noting that the 'exposed' field does not really have a relationship to the field and is just the value at time of exposure, changing the lua value doesn't change the java value and vice versa
when kahlua exposes a class it just loops through public static members and puts them in a table
well I dont think values() is static either... so this means cant use that
Ther is something strange in Lua
it doesn't expose non-static fields whatsoever, probably because that limitation is much more obvious there, but it's still occasionally irritating for statics
Second entry is definitely related to my changes
It is ComponentType table
using a static method already in that class like you were doing previously or creating a static accessor function for $VALUES somehow is the only way probably
probably is your invokeInit function public?
can you share that snippet
Ah yeah it is..
thats why, probably cant make it private either right?
I can
it doesn't break anything
nice
Alright gigawatte, you've convinced me to make an api...
Anyone, please let me know if there's any mixins or concepts you think would be worth putting in there, this also applies to Lua (although less so).
Currently I've only got some events in there.
And I will also add the ComponentType mixin stuff, but unfortunately I don't think there's a way to create a generic enum appender, so this will be done boilerplate-style for every class mixin
Also this will be nice ๐
its the simple things
you know what isn't nice, discord's really annoying image photo album feature
Wait you're not going to print these in the console ?
Dear god please don't do that
Not the "Calling onLuaInitialize for class ...", that was just there so I knew it was working
The right side is to show how you would use it in a mod as an example
in this case, I am doing stuff as extensions, maybe I should name it LuaExtension but I am torn on the naming scheme. Anyway, it's just adding the interface to the main mod entrypoint and you can override the method. This is basically just a helper so that people don't need to mixin LuaManager just to execute code when lua state is initialised
But that's Java on the right screenshot ?
LLLib for LeafLuaLibrary
Idk ๐
That would help a lot for others who might consider adding their own components, I think
Thank you
I found this project recently. Since you're more experienced with this kind of thing, it might be helpful for dealing with enums
https://github.com/Chocohead/Fabric-ASM
yes, it is meant to exist so people can run code when lua environment is ready. if you run code that requires lua to be active when lua isn't active, it will break
and the boilerplate for mixin in the end of init is too annoying imo over a simple function override
fyi, im gonna start working on server stuff specifically, because I've neglected it a lot mainly due to the fact that since they have the same java code, I only need to write for one specific side
the only thing I need to do is just adding custom scripts to servers via the installer, which is a PITA on anything but windows since I don't know how servers are run on other OS.
Updated loader to 1.3.0 which mainly merges a few commits from upstream fabric-loader and also adds a jvm arg leaf.dryRunModDiscovery=true which you can set to make the loader exit before mods are loaded and executed. Useful for seeing which mods are going to be loaded before they are. The log output will exist in cachedir/leafloader.log which is the log file fallback when the game's logging system isn't accessible. In this case, the loader is exited before the game is loaded.
Though, maybe in a future update I should include absolute file paths in the log file, because currently it just displays the modid and version (eg epicmod 1.2.3). Something like epicmod 1.2.3 (C:\\Program Files (x86)\\Steam\\steamapps\\workshop\\content\\108600\\...\\somemod.jar) would be ideal.
development going to slow down for a little while, because I have yet again more uni stuff (yay) and on the side im working on reverse engineering chrome engine file formats (which wont take very long) so dont expect a commit every day like I was doing for the early parts of leaf ๐ญ
and not only that, but I think i've burnt myself out on PZ (yet again (yet again)) so give it a few weeks and ill probably be back on it
Though please still ping me here when a new game version drops, i'll literally drop everything to upload the manifests ;-;
Hii @floral sluice
B42.11 has already been released. Could you please update the manifests when you have some time? Thx!
Give them the manifest number
I think it's needed
42.11.0-unstable.30715
I already did it!
funnily enough I was looking at the steam page and just saw it there
thanks for the ping though
also when I update them myself, I figured I can just read the class files anyway, so it's not needed for anyone to give me the revision number
Hi, sorry for not reaching out sooner.
I saw your comments regarding Leaf on the workshop page of my mod, but they got completely drowned out because of a new major release I did, so I kind of forgot about this.
I've managed to find time to try out Leaf, but I couldn't get it to work. I can send you more details once I'm back from work.
Anything helps, those details would be nice, especially if it's a bug/edge case
currently stuff I still need testers for are Mac/Linux, and stuff I need to work on is server-side stuff in general (in my case it's the installer and some small loom stuff)
I suppose I could try it for some old obnoxious zombie stuff and provide a solution to it
Mostly adding new events related to zombie interactions
I'm on Linux. The installation path suggested by the installer is wrong for Linux, so I had to adjust it manually. It will default to installing inside of ~/.steam/steam/steamapps/common/ProjectZomboid/, whereas ProjectZomboid64.json etc. is inside of ~/.steam/steam/steamapps/common/ProjectZomboid/projectzomboid
After this slight adjustment and installing, the game simply doesn't start at all after adding the -pzexeconfig argument in Steam.
leafloader.log contains this:
[19:40:51] [INFO] [LeafLoader/GameProvider]: Loading Project Zomboid 42.11.0-unstable.30715 with Leaf Loader 1.3.0
[19:40:51] [INFO] [LeafLoader/Mappings]: Mappings not present!
I tried modifying the json file, so that the leaf jar files are still loaded, but the main class is instead: zombie/gameStates/MainScreenState
The game starts with this. For reference, the jar files added to the json file are:
".leaf/libraries/asm-analysis-9.8.jar",
".leaf/libraries/loader-1.3.0.jar",
".leaf/libraries/sponge-mixin-0.16.1+mixin.0.8.7.jar",
".leaf/libraries/asm-util-9.8.jar",
".leaf/libraries/asm-9.8.jar",
".leaf/libraries/asm-commons-9.8.jar",
".leaf/libraries/asm-tree-9.8.jar"
The game doesn't start with the mainClass added by the installer: dev/aoqia/leaf/loader/impl/launch/knot/KnotClient
Not sure if this helps or means anything, but that's all I've got for now. Let me know if you can think of something I should try.
This helps a ton. So its downloading the libraries fine and editing the configuration fine, but for some reason its expecting mappings in prod environment. This probably has something to do with the mapping changes I merged from upstream a week or so ago. I'll look into this when I can
The fact that you see a leafloader.log means everything is where it should be, but the loader just exited before it loaded the game entrypoint
When you get a chance, add this arg -Dleaf.log.level=trace to the jvm args of the game
for example in steam, it might look like -Dleaf.log.level=trace -Xmx8192m -- -pzexeconfig bleh.json
[23:37:04] [INFO] [LeafLoader/GameProvider]: Loading Project Zomboid 42.11.0-unstable.30715 with Leaf Loader 1.3.0
[23:37:04] [INFO] [LeafLoader/Mappings]: Mappings not present!
[23:37:04] [DEBUG] [LeafLoader/Mappings]: Loading mappings (meta only) took 5.05 ms
[23:37:04] [DEBUG] [LeafLoader/GamePatch]: Patching main function main([Ljava/lang/String;)V
[23:37:04] [DEBUG] [LeafLoader/GamePatch]: Applying brand name hook to zombie/GameWindow#InitDisplay
[23:37:04] [DEBUG] [LeafLoader/GamePatch]: Patched 3 classs
thanks, I believe I know somewhat what is going on, just have to do some more testing
also, if you dont have an already built mod, I'd recommend playing around with it in the ide, because you dont have to use the semi-broken installer
and the ide is completely separate from the game in Steam
back to square one, no clue why it doesnt work in prod environment, probably going to take a little longer to figure out lol
ok its driving me fucking insane and im pretty busy right now so I'll come back to it when I can
Hey, anybody got similar issue while building example mod (it is fresh git clone no changes)?
It usually means it expected a certain game version located there but found a different one. Set the correct version in the gradle/libs.versions.toml file
If it is the correct version and its pointing at the correct path, verify game files and try again
woops i've missed that, now it works like a charm, thanks ๐ซถ
I still have no idea why this issue is happening to you (or what the issue is). Since it's getting past the game provider init stage (seen by the game patches being correctly applied), it's confusing me the most. Launching the game inside of IDEA via an example mod would be the best way to debug any issues currently.
I'm still figuring out how to get the exception error window that the loader has to properly show, because for some reason it hasn't been showing at all.
loader version 1.4.0 will be published to maven shortly. It's mainly merging upstream changes since 1.3.0, and fixes the bug where if you use an argument with an equals sign delimiter like -cachedir=C:\path it would crash before the game initialised
I still don't think that the argument issue was sneijk's actual issue though, because they would've gotten the loader log file otherwise (at least I think so, anyway)
@floral sluice Just wanted to say thanks for starting this and that I'm interested in helping out.
Question: Why does the Leaf Installer have Client and Server tabs?
When I try to load Project Zomboid with the loader:
.\ProjectZomboid64.exe -cachedir="E:\zomboidb42\saves" -debug -pzexeconfig .\leaf-1.4.0-42.11.0-unstable.30715.json
The leaf log says:
[19:16:42] [INFO] [LeafLoader/GameProvider]: Loading Project Zomboid 42.11.0-unstable.30715 with Leaf Loader 1.4.0
[19:16:42] [INFO] [LeafLoader/Mappings]: Mappings not present!
But then no PZ window, and the process ends. What am I missing?
I'm so confused! lol someone help me...
Is the gradle configuration supposed to copy stuff to .leaf in the game folder or something? I'm not sure what it means by "Mappings not present!"
When I do the gradle sync, I get:
The mappings (dev.aoqia.leaf๐งถ41.78.16+build.1) were not built for Zomboid version 42.11.0-unstable.30715, proceed with caution.
But leaf-yarn doesn't seem to be built for 42 yet?
I guess I should just stop bashing my head against a wall and see if any of yall have some tips.
@floral sluice I think I'm running into the same issue as @dull stirrup -- if I enable the debug logging I get:
[20:08:24] [INFO] [LeafLoader/GameProvider]: Loading Project Zomboid 42.11.0-unstable.30715 with Leaf Loader 1.4.0
[20:08:24] [INFO] [LeafLoader/Mappings]: Mappings not present!
[20:08:24] [DEBUG] [LeafLoader/Mappings]: Loading mappings (meta only) took 5.46 ms
[20:08:24] [DEBUG] [LeafLoader/GamePatch]: Patching main function main([Ljava/lang/String;)V
[20:08:24] [DEBUG] [LeafLoader/GamePatch]: Applying brand name hook to zombie/GameWindow#InitDisplay
[20:08:24] [DEBUG] [LeafLoader/GamePatch]: Patched 3 classes
I knew I could follow instructions... XD
@floral sluice I can also confirm that launching via IDEA works!
hmmmmmmmm
Its meant for game client and dedicated server, since servers don't have the launcher, so I instead have to create new launch scripts
gotcha
The game gets copied to the gradle cache directory. By default its in your home directory .gradle/caches/leaf-loom
And the "The mappings x were not built for Zomboid version x" is completely normal. The mappings that exist are only for 41.78.16 and currently its just a few parameters. This is because it takes a while to map everything, especially for each version. I've stated that I will not be creating mappings for unstable releases due to how frequently they release. The Leaf unlike Fabric does not need mappings to run the game, and this is why in prod it will say no mappings found but will continue anyway.
Ok I'm convinced this issue definitely has to do with one of the latest releases of unstable, so I'll look into that more. Its weird how it works in the IDE just fine...
I should probably create a FAQ on the example mod for this
@floral sluice If I can get to the point of understanding how to get running with Leaf, I can setup a nice Docusaurus for that and other info on Leaf.
I hate doing documentation so if anyone is willing to edit readmes or stuff it would help a lot
Od say just stick to the IDE right now and read the example mod readme if it has anything useful in it
@floral sluice The problem I'm facing with the IDE is that no matter what I do, it seems to barf on trying to set the cache directory
In the Zomboid Client run configuration I have -cachedir=E:\zomboid42\saves -debug in the program arguments but it says:
you probably need to update the loader version in the libs.versions.toml
I haven't changed it in the example mod repository yet
I did that, and now it boots but it doesn't seem to actually use the provided cache directory. For example, it doesn't find the example mod, or my own actual mod.
The version number isn't changed on boot, etc.
My lua mod doesn't show up in the modlist.
๐ค
Just for clarity's sake:
leaf-loader = "1.4.0"
leaf-loom = "0.5.1"
leaf-yarn = "41.78.16+build.1"
zomboid = "42.11.0-unstable.30715"
Usually I wouldn't change the cachedir in the IDE as it gets set to the projectFolder/run instead of your userprofile anyway
But this is still a bug I think
If you look in the run configuration, you will see -Dleaf.runDir=somepath you want to change that to the cachedir too, having to change these is the main reason why I dont recommend anyone change rundir in the IDE
Oh, ok that's fine then. Lemme see if the example mod loads if I remove it
Hmm, when I launch via the IDE, the version still says 42
do I need to install the built mod into the run/ directory myself?
Ah it looks like you do, ok lemme try
The example mod gets applied at runtime, you shouldn't need to
hmm, if its working correctly, the version number should say 43 right?
Unless you're running in prod then you need to either install a mod from the workshop or manually put the mods
yeah from ide, get the no mappings thing in prod
Do you get any mixin errors in the console? It's possible they changed the way versions are done or something, im checking myself
LOG : Leaf f:0, t:1755143430609> Loading Project Zomboid 42.11.0-unstable.30715 with Leaf Loader 1.4.0
LOG : Leaf f:0, t:1755143430675> Loading 4 mods:
- java 17
- leafloader 1.4.0
\-- mixinextras 0.5.0
- zomboid 42.11.0-unstable.30715
no mention of the example mod
huh wtf is going on
But it works if you don't change the cachedir?
or still the same problem
The only errors are related to some fluid container script.
I'm not changing the cachedir, happy to use run/. But when I launch via IDE, no mention of the example mod in the logs, and the version is 42.
oh
in the leafloader.log
[20:18:41] [ERROR] [LeafLoader/]: Uncaught exception in thread "main"
java.nio.file.InvalidPathException: Illegal char <"> at index 0: "E:\zomboidb42\saves"
at java.base/sun.nio.fs.WindowsPathParser.normalize(WindowsPathParser.java:182)
at java.base/sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:153)
at java.base/sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:77)
at java.base/sun.nio.fs.WindowsPath.parse(WindowsPath.java:92)
at java.base/sun.nio.fs.WindowsFileSystem.getPath(WindowsFileSystem.java:232)
at java.base/java.nio.file.Path.of(Path.java:147)
at java.base/java.nio.file.Paths.get(Paths.java:69)
at dev.aoqia.leaf.loader.impl.game.zomboid.ZomboidGameProvider.getLaunchDirectory(ZomboidGameProvider.java:89)
at dev.aoqia.leaf.loader.impl.game.zomboid.ZomboidGameProvider.processArgumentMap(ZomboidGameProvider.java:83)
at dev.aoqia.leaf.loader.impl.game.zomboid.ZomboidGameProvider.locateGame(ZomboidGameProvider.java:247)
at dev.aoqia.leaf.loader.impl.launch.knot.Knot.createGameProvider(Knot.java:247)
at dev.aoqia.leaf.loader.impl.launch.knot.Knot.init(Knot.java:199)
at dev.aoqia.leaf.loader.impl.launch.knot.Knot.launch(Knot.java:66)
at dev.aoqia.leaf.loader.impl.launch.knot.KnotClient.main(KnotClient.java:22)
at net.fabricmc.devlaunchinjector.Main.main(Main.java:86)
But that must be from before
Since I removed the cache param
though that may be why the cache dir don't work
hehe
Yes that would've been from before, don't put quotes in the cachedir in the ide
I need to strip them when parsing arguments
so yeah without the cachedir, no example mod
10:55:59 PM: Executing ':net.fabricmc.devlaunchinjector.Main.main()'โฆ
> Configure project :
Leaf Loom: 0.5.1
The mappings (dev.aoqia.leaf:yarn:41.78.16+build.1) were not built for Zomboid version 42.11.0-unstable.30715, proceed with caution.
> Task :compileJava UP-TO-DATE
> Task :processResources UP-TO-DATE
> Task :classes UP-TO-DATE
> Task :net.fabricmc.devlaunchinjector.Main.main()
LOG : Leaf f:0, t:1755143763435> Loading Project Zomboid 42.11.0-unstable.30715 with Leaf Loader 1.4.0
LOG : Leaf f:0, t:1755143763503> Loading 4 mods:
- java 17
- leafloader 1.4.0
\-- mixinextras 0.5.0
- zomboid 42.11.0-unstable.30715
LOG : Leaf f:0, t:1755143763503> SpongePowered MIXIN Subsystem Version=0.8.7 Source=file:/C:/Users/dustin/.gradle/caches/modules-2/files-2.1/net.fabricmc/sponge-mixin/0.16.3+mixin.0.8.7/3e535042688d1265447e52ad86950b7d9678a5fa/sponge-mixin-0.16.3+mixin.0.8.7.jar Service=Knot/Leaf Env=CLIENT
This is super odd. I am doing some testing of my own rn
cool
Even the example test in the loader is broken (which is basically an example mod to test the loader)
im definitely going to have to go back through my commits, it could've been something I merged from upstream
classic
FWIW, in run/ there is no .jar of the example mod or anything like that. I take you to be saying that the ide run config somehow sets it up to be used automatically, I just wanted to be clear.
Yes, it doesn't get copied over into run/ at all, it's applied from build/libs when you run the game in IDE
Ok going back to loader 1.2.0 lets the mods load, im going to fix this and then push an update very soon
Cool, I'm excited to try this all out. ๐
yeah I figured it out
turns out I forgot to return a variable in a function when I was merging from upstream
literally one variable, instead of doing return IS_DEVELOPMENT I returned false so it would never be a dev environment
I feel so stupid ๐ญ but I was sleep deprived so I'll chalk it up to that
at least it was an easy fix ๐
If you find any more issues, please post them as an issue on the github if you can, because it helps me track issues
@floral sluice how can I pull in 1.4.1
It's being published to maven right now
ah I see
Usually takes a minute or three to replicate. Also I was delayed to start the release action because my friend's power supply is sparking and stuff so I'm sidetracked, but yes it's uploading rn
๐ฎ
It is published, you should be able to use it now
Version says 43 \o/
is that good or bad
good it means that the example mod loaded, right?
yippeeeeeeee
๐ฅณ
You can always check in the mod list at the top of the console, but yeah it means the mod loaded
now to remember how to write java and to learn how mixins work
This is another reason why I want more people using leaf, so I can get bugs fixed faster ๐
I guarantee if you didnt come along and try to use it, I wouldn've found that in like 5 updates
after i've played around a little, i'll look into booting up a new docusaurus site and writing some info on how to get to where i did
The example version should be 43.420.69 ๐
@floral sluice is this right? doesn't seem to do anything:
@Mixin(BodyDamage.class)
public class BodyDamageMixin {
@Inject(method = "AddRandomDamageFromZombie(Lzombie/characters/IsoZombie;Ljava/lang/String;)Z", at = @At("HEAD"))
private void onAddRandomDamageFromZombie(IsoZombie zombie, String hitReaction, CallbackInfoReturnable<Boolean> cir) {
LOGGER.println("AddRandomDamageFromZombie called with zombie: " + zombie + ", hitReaction: " + hitReaction);
}
}
should probably do something
check the log to make sure the mixins are being applied correctly
at the top of the log it should say if there are any errors when applying mixins
I actually remember mixining this exact function and it did work
I don't see any errors in the log ๐ค
I guess if I run it in debug mode I ought to be able to break point it?
I always keep the name of the function the same as the one I am mixining, but I don't think it matters
Is it possible that the function is just not being executed?
you can put breakpoints on the actual function if yo uwant
Am I able to breakpoint game code? Do I need to run the decomp gradle task first?
run the genSources task and then in the sources you can set breakpoints
pretty sure it's executed anytime a zombie chomps ya
yea, I am mixining it to add an event, and it did work for me
they show up as any other java class source. If you CTRL+click a class like BodyDamage it will show the sources
Also you can view them via the file search thing, but I don't remember the default keybind for IDEA. I think it's CTRL+N or something
when i did that IDEA claimed to be doing the decompilation itself
maybe that's expected, i'm not super java-aware
Yea if you dont run the genSources task, IDEA will decompile using fernflower, but it doesn't do special line remapping that is needed for breakpoints and some other small things
I did run the genSources task, and then when I ctrl-clicked, IDEA made me agree to a TOS regarding their own decompiler
So the breakpoint was hit.
weird, it shouldn't be using IDEA's decompiler
If it says up the top in blue that it was decompiled via IDEA then it's not using the generated sources
It's possible using Fernflower you need to read their TOS anyway, though im unsure
I put a breakpoint on the version number mixin, the random damage mixin, and the game's actual random damage function.
The only breakpoint I hit was the game's actual random damage function
The version does say 43, so I'm confused
yea that makes sense, i'm not entirely sure if breakpoints work in mixins you create, I'll ask fabricmc team anyway
I've only used breakpoints for game code myself
Can you show the code where you mixed in on random damage?
Oh you have to manually register new mixins don't you
Do you have the IDEA plugin installed? (Look in pinned messages)
I installed it -- how does it work? The docs website is not clear.
I see.
Pretty cool, breakpoint in the version mixin.
It mainly just autocompletes mixin functions like intellisense (super helpful) and lets you use breakpoints, im not sure of any other features it has
But I do know that it should basically be a requirement for anyone considering how helpful it is
I'm stumped. My second mixin for random damage just doesn't seem to work.
I do see
DEBUG: Leaf f:0, t:1755153820364> NativeMethodAccessorImpl.invoke0 (Native Method)> Mixing BodyDamageMixin from modid.mixins.json into zombie.characters.BodyDamage.BodyDamage
TRACE: Leaf f:0, t:1755153820367> NativeMethodAccessorImpl.invoke0 (Native Method)> Added class metadata for java/lang/invoke/StringConcatFactory to metadata cache
TRACE: Leaf f:0, t:1755153820375> NativeMethodAccessorImpl.invoke0 (Native Method)> Added class metadata for zombie/characters/IsoZombie to metadata cache
DEBUG: Leaf f:0, t:1755153820377> NativeMethodAccessorImpl.invoke0 (Native Method)> modid.mixins.json:BodyDamageMixin from mod modid->@Inject::onAddRandomDamageFromZombie(Lzombie/characters/IsoZombie;Ljava/lang/String;Lorg/spongepowered/asm/mixin/injection/callback/CallbackInfoReturnable;)V doesn't use it's CallbackInfoReturnable
package com.example.mixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import zombie.characters.BodyDamage.BodyDamage;
import zombie.characters.IsoZombie;
import static com.example.ExampleMod.LOGGER;
@Mixin(BodyDamage.class)
public class BodyDamageMixin {
@Inject(method = "AddRandomDamageFromZombie", at = @At("HEAD"))
private void onAddRandomDamageFromZombie(IsoZombie zombie, String hitReaction, CallbackInfoReturnable<Boolean> cir) {
LOGGER.println("AddRandomDamageFromZombie called with zombie: " + zombie + ", hitReaction: " + hitReaction);
}
}
modid.mixins.json
{
"required": true,
"package": "com.example.mixin",
"compatibilityLevel": "JAVA_17",
"mixins": [
"ExampleMixin",
"BodyDamageMixin"
],
"injectors": {
"defaultRequire": 1
},
"overwrites": {
"requireAnnotations": true
}
}
aha, you have to use the cir value
\o/
we're in business
@floral sluice fwiw, when I try the hotswap thing I get:
mappings.jar: The process cannot access the file because it is being used by another process
so it fails
2:06:33 AM: Executing ':classes :testClasses'โฆ
> Configure project :
Leaf Loom: 0.5.1
Previous process has disowned the lock due to abrupt termination.
Found existing cache lock file (ACQUIRED_PREVIOUS_OWNER_DISOWNED), rebuilding loom cache. This may have been caused by a failed or canceled build.
The mappings (dev.aoqia.leaf:yarn:41.78.16+build.1) were not built for Zomboid version 42.11.0-unstable.30715, proceed with caution.
java.nio.file.FileSystemException: C:\Users\dustin\.gradle\caches\leaf-loom\42.11.0-unstable.30715\dev.aoqia.leaf.yarn.42_11_0_unstable_30715.41.78.16+build.1-v2\mappings.jar: The process cannot access the file because it is being used by another process
at java.base/java.lang.Thread.run(Thread.java:840)
The following process has a lock on the file 'C:\Users\dustin\.gradle\caches\leaf-loom\42.11.0-unstable.30715\dev.aoqia.leaf.yarn.42_11_0_unstable_30715.41.78.16+build.1-v2\mappings.jar':
Run with --info or --debug to show arguments, may reveal sensitive info
- title: 'Project Zomboid (leaf)'
- pid: 14928
- command: C:\Users\dustin\.jdks\ms-17.0.16\bin\java.exe
- started at: 2025-08-14T07:04:03.667Z
- user: DESKTOP-JS17575\dustin
- parent:
- pid: 32624
- command: C:\Users\dustin\.jdks\ms-17.0.16\bin\java.exe
- started at: 2025-08-14T06:59:31.540Z
- user: DESKTOP-JS17575\dustin
- parent:
- title: 'modid โ ExampleMixin.java [modid.main]', 'output โ BodyDamage.java'
- pid: 14808
- command: B:\installs\JetBrains\IntelliJ IDEA Community Edition 2025.2\bin\idea64.exe
- started at: 2025-08-14T06:58:32.346Z
- user: DESKTOP-JS17575\dustin
BUILD FAILED in 4s
2:06:37 AM: Execution finished ':classes :testClasses'.
Have you gotten that to work?
Yes, sorry for not responding quicker
Hmm I might have to look into that as well, I never fully got it to work but I chalked it up to my issue
Yeah it seems like PZ has locks on the files so they can't be replaced
darn, I switched to JetbrainsRuntime 17 cuz I heard its their fork with DCEVM that makes it work
Unfortunately, same issue
@floral sluice Maybe something has mixinextras explicitly open or something?
I even added -XX:+AllowEnhancedClassRedefinition VM flag, no luck.
I'm sort of out of my element so maybe you'll have better luck when you get around to taking another look
Options I tried:
-javaagent:"C:\Users\dustin\.gradle\caches\modules-2\files-2.1\net.fabricmc\sponge-mixin\0.16.3+mixin.0.8.7\3e535042688d1265447e52ad86950b7d9678a5fa\sponge-mixin-0.16.3+mixin.0.8.7.jar"=autoHotswap=true
-XX:+AllowEnhancedClassRedefinition
-XX:HotswapAgent=external
JetbrainsRuntime 17
HotSwapHelper plugin
Maybe something to do with:
// We JiJ this into the launcher jar directly! (thanks llamalad7 for the help)
"development"(project(":mixinextras", "shadow"))
Alright I need to resolve to put this down or I wont get anything done! XD
I tried a hack to delete the handles to the files to see if I could get it to work but it gets stuck on:
RmRegisterResources failed: The system cannot write to the specified device., Failed to query processes holding a lock on C:\Users\dustin.gradle\caches\leaf-loom\zomboidMaven\com\theindiestone\zomboid-client\42.11.0-unstable.30715-dev.aoqia.leaf.yarn.42_11_0_unstable_30715.41.78.16+build.1-v2\zomboid-client-42.11.0-unstable.30715-dev.aoqia.leaf.yarn.42_11_0_unstable_30715.41.78.16+build.1-v2.jar
My hack doesn't work on this file. Odd I wonder what yarn has to do with anything.
Actually, it looks like there might be a typo somewhere:
C:\Users\dustin.gradle\
Should be
C:\Users\dustin\.gradle\
I'm guessing. @floral sluice is that a hint or red-herring you think
Oh redherring, that's discord eating a backslash
argggh
the temptation of hotswap is too strong for me ๐
That's for mixinextras so you can use it in your projects
I was just guessing in the dark
My lasting guess is something in the loader is doing something
lol not worth much
but i tinkered randomly for like 2 hours
ยฏ_(ใ)_/ยฏ
Fixing the lock issue rn
holy hell that will be something
Also spoke to some people at fabricmc, they dont generally recommend mixin class reloading because it's jank. But they said normal class reloading is epic, so my recommendation(?) to pass on was to abstract mixin code to some other class of yours and reload that
i believe them, but my intuition would be the opposite
And llama also told me about a plugin which is faster for hotswapping than a full project recompile (see https://plugins.jetbrains.com/plugin/14832-single-hotswap)
since mixins are using instrumented detours, a form of indirection, seems it should be clean to update the mixin implementation since nothing directly references it
but that's just intuition i'm sure fabric peeps know their shit
It does work, it's just jank and unsupported fully
Especially since you basically need the special JVM from jetbrains to use it
that was easy so hopefully that's most of the jank
it's mostly for dev velocity/tedium so probably not big deal if it breaks under certain scenarios
What was it anyhow
Loader trying to extract mixinextras while the game was running (the loader and mixinextras had a lock because it was running the game)
I'm also bundling any upstream changes I forgot from a few months ago, just going through them all right now
im mega tired, so im going to finish it all tmr
I got it working.
The problem was in getZomboidWorkshopPath and getZomboidGamePath.
GAME_INSTALL_PATH translates to leaf.gameInstallPath
GAME_WORKSHOP_PATH translates to leaf.gameWorkshopPath
If none of these are set and I try to run this in Eclipse, it fails the patching steps I get with extra debug.
If I set leaf.gameInstallPath manually, I get to the same point as my previous logs.
If I set leaf.gameWorkshopPath, the game starts.
I haven't tried to figure out how leaf.gameInstallPath becomes set, but simply by adding:
-Dleaf.gameWorkshopPath=../../../
to the leaf json file under vmArgs, the game starts.
So to fix this for Linux, you can either add the -Dleaf.gameWorkshopPath="../../../" into the json file automatically.
Or consider this patch:
diff --git a/src/main/java/dev/aoqia/leaf/loader/impl/LeafLoaderImpl.java b/src/main/java/dev/aoqia/leaf/loader/impl/LeafLoaderImpl.java
index e8f8445..9f1187e 100644
--- a/src/main/java/dev/aoqia/leaf/loader/impl/LeafLoaderImpl.java
+++ b/src/main/java/dev/aoqia/leaf/loader/impl/LeafLoaderImpl.java
@@ -370,7 +370,14 @@ public final class LeafLoaderImpl extends LeafLoader {
}
try {
- return Paths.get("C:\\Program Files (x86)\\Steam\\steamapps\\common\\ProjectZomboid");
+ if (System.getProperty("os.name").contains("Win")) {
+ return Paths.get("C:\\Program Files (x86)\\Steam\\steamapps\\common\\ProjectZomboid");
+ } else if (System.getProperty("os.name").contains("OS X")) {
+ return Paths.get("~/Library/Application Support/Steam/steamapps/common/ProjectZomboid/Project Zomboid.app/Contents");
+ } else {
+ // Not sure if ~ is properly expanded to the user's home directory
+ return Paths.get("~/.steam/steam/steamapps/common/ProjectZomboid/projectzomboid");
+ }
} catch (InvalidPathException e) {
throw new RuntimeException(
"Failed to find the game directory for Project Zomboid. This could happen if " +
@@ -387,7 +394,13 @@ public final class LeafLoaderImpl extends LeafLoader {
}
try {
- return getZomboidGamePath().getParent().getParent().resolve("workshop/content/108600");
+ if (System.getProperty("os.name").contains("Win")) {
+ return getZomboidGamePath().getParent().getParent().resolve("workshop/content/108600");
+ } else if (System.getProperty("os.name").contains("OS X")) {
+ return getZomboidGamePath().getParent().getParent().getParent().getParent().resolve("workshop/content/108600");
+ } else {
+ return getZomboidGamePath().getParent().getParent().getParent().resolve("workshop/content/108600");
+ }
} catch (InvalidPathException e) {
throw new RuntimeException(
"Failed to find Steam workshop directory for Project Zomboid. This could happen " +
I haven't tested this myself, since I'm not at the point where I'm building the loader from scratch, so I apologize if maybe it doesn't build.
Also, I'm not 100% sure about the Mac path. The path is largely based on information I've gotten through helping users of my mod to install it on Mac, so I've never actually done it myself.
This makes a lot of sense in hindsight. I believe I made the default workshop path ../../content/... because on Windows that is where the path is, but on Linux there is that extra inner projectzomboid folder.
And yes the lack of an error message really screwed us over. I am in the process of converting all of the runtime exceptions I used to exceptions that get showed in the gui
@floral sluice any luck with the file lock stuff?
im getting around to it now since im done my study for today
I've already fixed the issue, just quickly getting in upstream changes while im at it
ah cool
Hello, feels like im asking stupid question, but is there an instruction how to define structure of java mod?
I've build example leaf mod, structured it like on screenshot and put into my mods folder
My other personal lua mod loads just fine, however i don't see java mod in the game mods list
I'm running the game with -debug -pzexeconfig leaf-1.3.0-42.11.0-unstable.30715.json flag which, version maches the game i'm running
Also in the logs seems like leaf loader is there, but in logs there is no word about the java mod
That's not where the JAR goes. Download the example mod from the workshop.
Example mod installed from workshop, still didn't show up ingame
Adding .jar to leaf/mods folder didn't worked out as well
Maybe i am missing something? Leaf loader is installed via git repo instructions, versions seems to be matching
Tried both .leaf or leaf folders
Leaf mods don't show up in the in-game mod list
The log will say what leaf mods were loaded
Exactly what idlework said. The game technically doesn't even know it's modded, and there's not really a viable way to do an interactive modlist in the game currently. I have a few ideas now that I've gotten more in-depth about how stuff works, but it'll take time to add. Probably will be a part of the leaf api
I could be interested in helping with that kind of thing
Also sorry for taking so long with this release. I've been going through and double checking each upstream commit since november last year to make sure I have the most recent changes because I noticed that some upstream changes I forgot to add
pfffffffff no worries XD
polish that thang
what do you mean by upstream changes btw? fabric stuff you gotta merge in?
Yes, stuff from FabricMC's repositories
makes sense
Sadly I can't just rebase or merge 1:1 these changes because of the amount of code Ive changed, and git is being annoying with rename detection as well. So it's me doing it manually right now
do you have to like do wacky / tedious stuff to do that, or have we maintained git ancestry with the original projects making it a simple merge
mmm
unfortunately so
I don't think it would be good to auto merge everything anyway, because there have been some situations where code can double up
I am lucky that changes on fabric's side usually take a while to develop and once they're pushed they dont change it too much
improving the maintainability of projects is something i enjoy but i don't understand leaf enough quite yet to help with that stuff
I do follow (I think) standard git practice of push to dev, merge into main, rebase dev/main changes onto feature branches, but thats just me
but helping with leaf api and building some mod listing / option stuff i could probably at least help with
Currently all the fabric toolchain (and thus leaf) is a big gradle clusterfuck and I've had to do some rather sketchy things to get stuff working. For example, there's currently no automated testing at all on any of the projects because of how PZ is on Steam, and I don't currently have set up a 24/7 self hosted actions runner to rely on to get testing to work
It might be a kind of middle ground for any kind of test suite to at least be runnable locally. Can be part of the release process at least to run it manually before getting on with the CI.
true that
I figure that once I get leaf to a more stable state I will add at least some of the unit tests back and edit them for Zomboid where needed
as ironic as that sounds...
Ok I am up to 7th april 2025 commits in upstream. I'm going to stop here and test, then I will release what I've already got right now so you can actually use the fix ๐
I wont be doing any commits over the weekend unless really necessary, so this is actually good timing
it seems it still doesn't load ๐ค
LOG : Leaf f:0, t:1755244479256> Loading 4 mods:
- java 17
- leafloader 1.3.0
\-- mixinextras 0.4.1
- zomboid 42.11.0-unstable.30715
That's the logs from the very beginning
Launched new game, there should be Hello Leaf World!!! >w< in the logs but its not there
show a tree of your mod
This is example mod downloaded from workshop that doesn't load
you can use "tree"
my guess is that the example mod is for 41
alright going to bed, excited to try the new version tomorrow
Reinstalled the game, leaf-loader and example leaf mod to run under v41, still no mentioning in longs
By the way, not sure if that is reproduceable, but after downgrading pz to v41, there was leaf-loader for v42 (.leaf folder), after running installer for v41 and adding pzexeconfig the game wasn't starting (logs were empty). I had to rm -rf .leaf and install loader again to have it working
I believe it was yes
I noticed youre also still using leaf 1.3.0. I did fix some stuff in 1.4.1
But probably not anything to do with this issue
The .leaf folder should probably use a subdir also of the version of leaf being used
mods already specify the version of leaf and game they are compatible with via the mod json
it's not .leaf anymore it is leaf folder. The reason why is it was being hidden on Linux by default
I did change that, but I havent updated the example mod on the workshop in a while
oh and I forgot to mention @rare mural loom 0.6.0 is released which has the fix you've been wanting with the files being locked
Iโm saying store the files is a subdir so you can have multiple versions installed at the same time
I agree it could be a good idea for the future to allow for multiple versions of Leaf yea
As of now idk if it's necessary but maybe for the future in cases where users need to use specific versions of Leaf ?
maybe, but in this case wouldn't you just use steam workshop collections?
You can already install multiple leaf versions btw jvla
But what about mods having different versions of the mod specific for different Leaf versions
switching between them is done via changing the pzexeconfig param. This doesn't apply to servers though.
From my understanding of it, mods are fixed to a version ?
hmm good point
That's what he meant with the subfolders
yeah since steam only keeps the latest for download
Bcs yes you can specify the version for THAT mod, but you can't have a mod with multiple versions
Basically introduce the versioning folder of B42
But for Leaf specifically
And maybe for both the game version too ? Idk here tbf, getting a tiny more in depth on it, I'm not fully aware of how Leaf works
ok I could do that as an optional feature
Have something where it loads the closest Leaf version basically
create an issue for it on the github for loader. it doesn't need to be fancy just explaination for future me
I'll let @rare mural handle it since it was his idea in the first place and he can probably explain better what he expected for it
true
@floral sluice Just checking, did you forget to push the new version?
Or still tinkering on it?
Oh it's a different component
hotswapping ?
Oh nice
Didn't knew Leaf could do that tho I guess I'm not too surprised considering how (I understood) it works
Since it links to the memory or some shit if I remember correctly ?
It's not really Leaf per-se, it's the Mixin library that underpins Fabric
Mixin + a custom javaagent from the fabric team
It's a pretty crazy library, https://github.com/SpongePowered/Mixin
Yea that's probably where I read about that
@floral sluice does Leaf come with mixinextras
wait, it must, that was the jar that was being locked yesterday
It does I think yea, I remember something with this name
@floral sluice I notice that in the decompilation, there's a lot of var1 var2, etc. Is that because the mappings are only for 41? Or is it because the mappings are incomplete? Is there an easy way for me to rename a variable and have it added to the mapping? Using the normal variable rename doesn't work as there's no actual source files, it's just the decompiled JAR.
i think she mentioned the other day that she wasn't using our mappings
so probably no parameter names until then
These are locals.
I don't really understand what the genSources gradle task does.
Why does it produce a jar, rather than a folder of code? ๐ค
in that case, nobody has ever made mappings for local variables
@full mountain Where can I read about how mappings work? I'm not a java developer by trade. If possible, I'd like to get to the point where I can right click a variable and rename it, is that a possible workflow?
i'm not really sure why you can't do that, it probably is because leaf decides to jar the sources for whatever reason
I should probably just go a normal route and decompile 42 myself yeah? Then I'd be able to rename symbols. But how can I contribute that work back somewhere? Is that a thing?
we don't have any kind of local variable mappings to contribute to currently
our mapping stuff is original, and its original purpose is for mapping out the lua api so it doesn't cover local variables as they weren't relevant to us (but there's some general interest in changing that at some point)
Oh the mappings are for lua, I see.
it primarily covers the java api but the purpose is to then give that information to lua
we now use it for decompiling and stuff but that wasn't the original purpose
the general function mappings live here right now https://github.com/demiurgeQuantified/pz-rosetta-source
I wonder if there'd be a way to have a system where, if you have the decompiled java, and you use IDEA to make changes to it, you can then use git to extract a diff of the changes you made, or something... and then we could pool and merge those diffs, so that you can grab a decompilation and then apply the diff to enjoy all the community renames.
You know without distributing the actual source, just the diffs
jab was writing a whole website to edit mappings (the raw yml files here are fairly impractical to work with at scale) but there's only so much time in the day and to be honest there isn't much apparent interest in doing the grunt work of actually mapping things
i'm sure you've seen before that everyone's huge on the importance of documentation until they have to actually write some ๐
If it were as easy as using the IDE to rename things as you're reading the java with an easy way to contribute those renames upstream, then people might do it.
But seems fanciful I guess, even from just a technical perspective
yeah, that would be the ideal for me but i have no idea if that could work
yeah a technical solution isn't leaping to mind..
It's like you'd need to be able to take a git repo, and tell git "here's what the files looked like at the initial commit" (the decompilation result) and then have it replay a history of commits ontop of that.
So people need to do their own decompile, but then somehow git can replay the diffs onto that, without requiring the original files be in the actual git repo somehow.
I'm gonna ask the AI just to see if they know some magic off the top of their head XD
i honestly have no idea how mappings are normally done, the minecraft community keeps their secrets
lol
RIP git stores snapshots not diffs
TIL
Ah but apparently Mercurial works this way
ah wait this wont work
when zomboid updates, the decompiles will change and the hash will change and you wont be able to inject it as the content of the first commit
dang it
we could probably make some local tool that parses the file and extracts names
yeah but that really feels like a lot of work heh
What might be interesting is a custom IDEA plugin
When you do a rename there, it must understand the symbol from a semantic perspective. Maybe the information at hand could be recorded. And then all those refactors could be "played back" later
it's definitely something i want to improve, we've had this dataset for over two years now and i'll be honest: we've had *one* community contribution
know what I mean?
even i hadn't contributed anything (manually, beyond the tooling that generates what data we can) until literally today
by played back, I mean, having IDEA go and do all those refactors using the refactor machinery
yeah, i definitely pondered that possibility too, i'd love to look into that sometime
the data basically feeds the entire modding ecosystem (umbrella, the javadocs, zomboiddecompiler, and hopefully in the future leaf), so if it was easy to contribute it'd improve the modding experience for literally everyone in the community in some way, and everyone would have some personal motivation to contribute
A rename-refactor IDEA plugin that could record the renames done (saving that information to a file somewhere) is the best I idea I have so far
yeah, that definitely sounds the most realistic to me
(and then playback those renames by ingesting the same file)
i can't imagine their plugin API can't do that
I like the IDEA plugin idea better, because it would survive most game updates, since it would be utilizing the semantics, rather than lexical content.
I could imagine diffs no longer properly applying with significant enough game updates
And then you'd have to do even more surgery on the repo
hmm all the AIs are quite confident both recording and playing back the built-in refactoring mechanisms is quite doable
@full mountain O_O https://github.com/tsantalis/RefactoringMiner
that was what fabric stores intermediary mappings for
can you say that a different way
oh sorry, I can parse it now
getting sleepy XD
its files that store information about classes, functions, parameters and fields
they use them so that mods for the most part don't need to update names. AND because their game is obfuscated (probably the main reason)
I initially disabled all that system because the game isn't obfuscated
adding them back wouldn't be too hard. They do require maintaining though, like having to generate them for each game version
Hmm, the game isn't obsfucated, but there are missing local variable names all over. Would what you're talking about magically resolve those?
I didn't like the IDEA plugin initially because a handful of people probably use the command line with gradle or some other IDE (which is supported)
No. Currently, the tool that remaps code like param and class names doesn't support locals because it would inflate mappings by an insane amount. That would probably be a good idea for a plugin tho
I did ask them and they said it was being considered though. But I'd imagine the mappings would go from a few kb to possibly megabytes
Are you saying that the decompiler technically has the locals of the names, but isn't outputting them (or something) because it would inflate mappings?
Like when I run ZomboidDecompiler, the reason there are no locals is because it utilizes the mappings data, and locals are excluded for size?
I presumed the information was just not available in the first place, and so community needs to do work and make up names where they're missing.
A few megabytes seems like a small price to pay for full symbol coverage, imo.
no, we never had data about locals to begin with
aha, I see
The IDEA plugin then seems like a good idea because all other options seem so tedious that no one will do it.
Mappings are just files that store information to be transformed by the tiny remapper. It is mainly just function signatures and other name stuff storing mapping names paces. Most common names paces in fabric are official aka obfuscated, intermediary which is the mappings that are extremely similar between game versions (such as method_2427) and named which is yarn for human readable. In dev, the game is mapped to named so you can read the code good. In prod, the game is at runtime remapped to intermediary and mods are also already remapped to intermediary when they get distributed, so the game loads them fine and that's basically it. Leaf strip's out intermediary and the main reason why was because it would've been yet another step to maintain and that mattered the most at the early stages of the fork where I wanted to get stuff working quickly
Intermediary also means every game version, someone needs to create yarn mappings if anything changes like if TIS adds class_1234 it will appear that way to the developer unless it has been renamed with yarn.
But it personally seems a bit odd for me to use intermediary when the game is not obfuscated. Its so much extra work for little benefit. Like sure you don't have to update your mod every update but maybe every second update, at the cost of having to maintain an extra mapping layer. AND its pointless considering we'd be basically doing this: IsoPlayer -> class_1234 -> IsoPlayer which like why even store mappings about that lol
What do you mean that it's not obsfucated if local variable names are mangled?
Local variables are never kept by the compiler
The only reason why we can read class names, function names and method names is because they get stored some signature information in the bytecode when its compiled, or can usually infer the name
I have an IDEA plugin going, I'm currently exploring the intellij API regarding rename stuff.
yoooooooo
{
"variableType": "zombie.characters.BodyDamage.BodyPart",
"newName": "bodyPart",
"oldName": "part",
"filePath": "zombie/characters/BodyDamage/BodyDamage.java",
"containerFqName": "zombie.characters.BodyDamage.BodyDamage.save",
"elementType": "PsiLocalVariableImpl",
"fqName": "zombie.characters.BodyDamage.BodyDamage.save.part"
}
saved to file after doing right-click -> rename
Now to see if this is enough information to reliably automatically reapply it.
50% of the puzzle right there though
very cool!
maybe just being able to export it?
also how does it handle when something is removed
It gets written to JSON automatically. I was thinking more about parallel work, merging, etc.
You mean like if TIS removes a variable?
yes, or if function or class gets nuked
also make sure this doesn't affect line numbers. I don't know why it would but I'm just putting that out there
I've been improving it a lot, and it checks all the renames and their current status. One of them is "warning", if it can't find the original or the replacement. I'll specifically handle if the package, class, or method are just gone.
Yeah it uses IDEA's Structural Search
Honestly, I'm sure when you folks look at it, you'll be able to improve it a lot
I'm not a java developer, though I mostly have a handle on it
ok that's good
I was going to talk about local reordering but if its naming based off of name only and not local index then that isn't an issue
The principle I went with is that the tool is designed to take a fresh decompile to the fully renamed state.
If the JSON says Foo -> Bar, but you renamed Foo -> Baz, it's not gonna try to detect stuff you did not using the tool, or before you installed the tool.
Additionally, it only stores one rename per variable. So if Foo -> Bar, but then you rename Bar -> BetterBar, then what's stored is Foo -> BetterBar.
hmm ok. This will be a decent enough solution until enigma gets local renaming
one variable rename is fine honestly
I orignally had it as a timeline of renames, so you could rename things multiple times over time
And it would work out because it would apply them in chronological order
But what's the point
yes exactly lol
When you update your rename file, you should apply it to a clean decompile.
I'm slightly considering writing an OAuth protected "rename server" that the plugin will communicate with
So renames just happen in realtime for everyone
But it's getting late in the night ๐
@jagged scarab I am continuing the conversation here just for the purpose of a tracked conversation if this ever happens in the future. That stacktrace is fucking baffling, mainly because it doesn't even show where it errors. There's obviously an IOException being caught in an outer try/catch that im not catching inside the actual function to copy a game file, but I literally catch EVERY single IOException possible
I am confused on why anything in the copy game file code would throw an exception that I am not catching. basically every single file manipulation option like checking if a file exists and deleting a file is done with IOException
@floral sluice Thanks for your assistance. What is actually the full process of creating a Java mod for PZ using de template one? Why it need to "copy" the game?
didn't this happen to me because I was using symlinks
The game is copied to be manipulated only in the dev environment (and also to be ran correctly in the IDE)
Yes but yours was caught by my 500 million try catch sstatements for literally every file operation
So it pointed me correctly to the right place after some digging
His stack trace is basically "oh yeah it threw an IOException somewhere, haha"
This is one of the inner functions for copying a file, I literally handle basically every IOException possible
And the functions that throws IOException that I don't handle are usually handled inside the function itself
This is just friendly advice! But I would move each of those logical blocks to their own protected methods, it will result in the original function being more readable (imo).
When I build the exemple mod the exceptions thrown refer to files deep in the PZ ressources path, which I'm not sure is existing maybe due to a versionning error?
I probably should but im not going to because I don't want 3-4 extra functions for a relatively short function and also because I don't want to accidentally break anything ๐
This is the main outer-trycatch statement I was talking about
This kind of "move a logical block to a protected function" shouldn't really break anything as it's functionally equivalent
But fair enough
You can see this being thrown in the stacktrace, but it's not followed by the Throwable at all
I'm pretty sure if you highlight a block there is a refactor function that will move the code automatically to a new method and replace it with a function call.
JetBrains are actual gods at automatic refactor stuff
if only the IDe didnt run like ass
Rider/Reshaper are actually marvels of engineering imo
java frontend ๐ who let java people cook
hehe
@floral sluice can you explain to me on which part of the project you are debugging so maybe I can help? Why the program Throw errors because it can't find the files? Where is stored the ressource path?
Look at the "Failed to copy file from X to Y" in the stacktrace
thats the intention
That means doCopyGameFile fails with an internal exception but what is it?
I don't think you are, but I'll state this anyway, I don't think any WSL interaction is supported, though im not sure. I wouldn't try it personally.
It must be something obvious?
I thought so too, but it's not at first glance
Yes I'm using wsl but only the Windows gradlew.bat seems to works
maybe teh file exists check is one of the things I don't handle, but it's because it doesn't throw any exceptions
dont run leaf in WSL at all, make sure it's all windows stuff
There was known issues where if the filesystem doesn't support certain operations it will just shrivel up and die, not sure if WSL is supported so I generally recommend using your native OS
But I still don't think that's what is going on here
Check out the new UI:
That is nice
@floral sluice let me turn on my computer and find a way tonmake it works
that's the spirit XD
If you can run loom in debug, surely that would make the issue reveal itself
beats relying on the half drunk stacktrace
I checked the source file, it exists in my game folder
Idk why it throw an exception
What's the exception? Is it another locking issue? (shot in dark)
Failed to copy file from %s to %s
This exception
Like if the file where not found
that is this ^^^
Failed to copy file is a generic exception that is usually caused by another exception, such as "Failed to release lock on ..." or "Failed to write game file output"
I readed your screenshot of the source and IDK which Exception fires
Which the inner exception should be printed in the stacktrace, but here it's not for some reason?
That's what I was looking for
Have you two tried Cursor, asking Claude to look at it etc?
Copilot is rather good for complex mathemtical formulas (sometimes)
AI is not great at producing code, especially with long-horizon tasks
But it is really really good at reading lots of text and reporting on it
@jagged scarab Can you post another version of the stacktrace here?
Like just trying to run it again, and grab the output
This is the main function that is executed
Everything in light blue highlight is what throws IOException that would cause this
createLock, getAndResetLock, isOutdated, copyGameFileToPath, writeHash, isHashValid
These are all functions that handle internally the IOExceptions in the function itself
Which is literally every function that can throw IOException in doCopyGameFile
Getting Leaf running under a debugger would probably be a huge boon
I don't think I'll be able to get any useful information until he debugs it yea
If I can't get something running under a debugger I start feeling hopeless
oh tahts a better stacktrace this time
that is way better
it's showing the inner exception I was talking about earlier
It's the stack trace from yesterday I didn't modifyed it
Hmm, yesterday you didnt publish the full one then
No because it was very long
fair point
This: ```
Caused by: java.io.IOException: Failed to copy (C:\Program Files (x86)\Steam\steamapps\common\ProjectZomboid\steam_appid.txt) with expected hash: sha1:79A86757B3F71B64FE7266479939C2C0D8431501 got 405b492d526726cd232bc61ea8a58d63a589e52b
Is one of the many exceptions, but this only shows up if the versions are different. Is it possible this was before you changed the versions correctly or something?
Almost the entire game was copied without any error that's enven weirder
I didnt touch the steam_appid.txt file
Caused by: java.io.IOException: Failed to write hash to (C:\Users\theo\.gradle\caches\leaf-loom\42.11.0-unstable.30715\extracted\media\fonts\KO\4x\zomboidLargeKorean_22.png)
This is the main error^
libs.versions.toml
leaf-loader = "1.4.1"
leaf-loom = "0.6.0"
leaf-yarn = "41.78.16+build.1"
zomboid = "42.11.0-unstable.30715"
Basically, I keep track of hashes via file attributes, and if the file system doesnt support it (like JAR doesn't) it will write a file alongside the original like SomeFile.png.LoomHash.att attribute file that stores the sha hash
For some reason, it's basically closing the att file while writing to it
Well rather, it's failing to write bytes to the attribute file
So you have a .att hash file for every file in the game?
Only if the filesystem doesnt support writing file attributes natively
Which is only true for zip/jar usually (which have the class files)
For example, none of these extracted files have .att file because Windows supports custom file attributes
But Zip filesystem (which is JAR as well) Doesn't support this, see:
In any case, this isn't a bad thing
Okay
I was wondering how you store the hash in the file attribute, since it's only basics flag like Archive,System,Hidden etc
You know what's funny... @full mountain did have this exact same issue
Which I THOUGHT I solved. But I guess it's more of a per-computer thing that I can't fix
Weird
In albion's case, she had symlinked the .gradle folder in your user home which Java throws a tantrum over
Tell me where is the loom/leaf source you're working on I cannot find them in the exemple-mod project?
I'm not that used to Java IDE etc
loom is a separate plugin for gradle, it's used by the example mod
I found a folder named leaf-loom in the .gradle/cache folder is it the right path?
Extended file attributes are file system features that enable users to associate computer files with metadata not interpreted by the filesystem, whereas regular attributes have a purpose strictly defined by the filesystem (such as permissions or records of creation and modification times). Unlike forks, which can usually be as large as the maxim...
that is where game files are stored, where they are copied to
It's fine, I've already figured out the issue
not quite, but it's better than before
Basically, it's trying to write bytes to the file system Extended file attributes, but can't because some reason
@floral sluice you should grab Excalidraw and make a nice diagram ๐
But you can force the program to produce .att file anyway?
Forget about Extended file attributes maybe?
diagram for wat
It does, if the filesystem doesn't support attributes
All the parts of leaf and some description about them
Clearly Windows does support them, and it's corectly getting the extended file attributes, and they aren't null. There's no reason why it shouldn't be able to write to them unless like I said before you've symlinked your gradle home directory or any parent directory above that for hwatever reason
If any folder in the hierarchy C:\Users\<user>\.gradle\caches\leaf-loom\... is symlinked or some reason obstructed, it will cause this
This is what is being done for context
I didn't symlinked or anything .gradle, just following the README steps
hmm
I could add a flag for loom to specifically only use att files, but this is basically putting gum on a hole and hoping your ship doesnt sink
It's possible that multiple threads are trying to write hash to the same file or something
"Checked exception received by a thread when another thread interrupts it while it is blocked in an I/O operation upon a channel. Before this exception is thrown the channel will have been closed and the interrupt status of the previously-blocked thread will have been set."
It's apparently an issue with NIO file channels, I wouldn't be surprised however if this issue was fixed in loom upstream and im yet to add the changes lol
So the bug is dues to thread IO "collision"?
Maybe a canva ?
something in NIO is the issue, and im not about to try and fix that trash lib so I'll just add the option leaf.loom.forceAttributeFallback so you can copy all the game files in peace ๐
Funnily enough some of these fixes not even Fabric has. Maybe I should contribute some of these lol
It's a real real shame you can't maintain git history with the project
Like I imagine you have their main, and you have your fork and branch and you consistently rebase your changes over their head
But I guess it's not feasible
How I do it is I pick changes from their upstream commits and add them
I've been doing this manually whole time because some changes I do not want, that are specific to Minecraft
Yeah but not cherry-pick right? You manually do this
yeah but you'd create commits ontop of their commits that remove that stuff
I only discovered cherry picking recently. I tried it and sometimes it works but there's too much collision so Git gets angy
by consistently rebasing, all your work, the entirety of it, would sit ontop of their work
so you could undo their work, and maintain git lineage with them
for commit you did want, you'd just take them as is, no work needed
Also, their version structure is different to mine. They have all versions of loom supported for different versions, and their maven is not immutable, so they constantly change version say 1.7 loom with feature updates to support old Minecraft versions.
In my case, maven is immutable meaning I cant change artifacts once published, and im constantly doing changes as new version
yeah but you can likely customize even that, with whatever commits ontop of their work make it so
Even if I wanted to cherry pick or rebase, Git seems to not respect my git mv to rename stuff, so it still tries to create the entire files with old names instead
hmm if that's the only thing, it seems worth investigating some more
but anyway, i'm just thinking outloud, not trying to bully you into anything
this would actually be an issue too
with your plugin
what do you mean?
for example, consider decompiler output:
public final class Some {
public static void someFunc() {
String string0 = "Hello, "
print(string0)
String string1 = "World!"
print(string1)
}
}
It prints "Hello, World!"
if you rename the locals like so:
public final class Some {
public static void someFunc() {
String helloStr = "Hello, "
print(helloStr)
String worldStr = "World!"
print(worldStr)
}
}
same output
Now game updates and the order of locals declared changes, like this:
public final class Some {
public static void someFunc() {
String string0 = "Some cool string"
String string1 = "Hello, "
print(string1)
String string2 = "World!"
print(string2)
}
}
Then your rename of string0 -> helloStr would make "Some cool string" be renamed to helloStr and it would print Some cool stringWorld! to your eyes reading the source which has basically become incorrect source
I actually asked fabric team why they don't use local remapping, they said it was because of this reason, it's too unstable for each game version update, tracking the locals
when i thought about it in the past i felt that way too
if you store the index of which local is renamed, this issue still happens
I feel like that's expected though
The trick is having a really really easy way to maintain this stuff
They don't have an IDEA plugin that rides the builtin refactoring machinery ;p
The next time someone goes to that code and sees the names don't match their ininitializer content, since hopefully they're using the plugin to get the renames, they can also use it to make the renames, using just the normal IDE rename, to fix it for themselves, but that's tracked by the plugin
That's what I was asking about before, how should the collaboration work
I was thinking about integrating git into the plugin so that as you make changes, it makes commits, and you can submit PRs right from the plugin
no, they have enigma which you can rename variables through gui like renaming them in IDEA
but it's way too much work to maintain
even if you had a dedicated jobless person doing solely mappings, there's potentially thousands to tens-thousands locals to rename
all for the benefit of slightly being able to see the code path better
there's no point in maintaining it all
this is how i see it
i'm reading the java of the code
it's hard to read because of dumb variables
so at least for the parts i'm interested in, i right click and rename variable, now its easier to read
there's another scenario where i would do that
when the variable is automatically renamed, but wrong because of the issue you presented above
I see, you are doing temporary renaming for each version as you try to read the code?
in that case i still want to read the java code like before, so i make the rename
so in both cases, i'm motivated to rename the variable of the code i'm trying to understand because it helps me understand it
it's only temporary if one doesn't use the plugin ๐
with the plugin the problematic case you point out is just like coming to code i'm interested in and it has ambiguous names rather than wrong names
in both cases i'm motivated to right click and rename
so all we need is a way for what i'm already gonna do, to accumulate
and if it can be painlessly collaboratively-accumulative, then maybe at some point the code i'm interested in is already renamed! XD
that's how i'm looking at it anyway
also since the plugin i think is pretty well made, then you can take those problematic cases and build heuristics to give you warning areas to look at like "the number of variables in this function changed!" etc
you could even at some point show those warnings inline the actual functions themselves so you get a heads up as you venture into code that might be wrong due to the class of issues you point out
can also use the right-hand-side of the assignment to help heuristically too
hmm if this helps you that is good. I wont use this personally because I find reading the unnamed locals normal
ยฏ_(ใ)_/ยฏ
or an llm model on loop
that would be unreliable I think
though I don't know for sure because I don't know how an AI would handle context, especially in large functions
I know I said I wouldn't do any commits over the weekend but this is such a stupid issue that I had to, @jagged scarab It should be added in the loom 0.6.1 which is releasing right now
Then, just add to your example mod the leaf.loom.forceAttributeFallback=true property in the gradle.properties
Okay so I just need to set leaf-loom to 0.6.1 in the libs.versions.toml and put leaf.loom.forceAttributeFallback=true in the gradle.properties and it will work? @floral sluice
it should yes
Show with stacktrace pls
Also you probably want to completely wipe the leaf-loom cache folder in .gradle\caches\leaf-loom and then resync
Okay
I'm trying to rebuild everything
Same errors
This issue is still happening. It shouldn't be at all. Did they release another update?
let me check
That hash isn't correct at all
Are you sure your Steam version is on the beta unstable branch?
Yes I'm sure
If it is, verify game files in Steam
How can I verify the game files? I didn't modify anything at this point
Okay it's verificating file integrity
yes through steam
There where 1 corrupted file
Downloading/fixing
I don't know why there is 1 corrupted file.....
Sometimes steam will just shit the bed
or the file gets modified for some random reason
seemingly a common occurance for pz somehow
I'm rebuilding... ๐
you';re getting my hopes up ๐
it works on your machine??
yes
and everyone else that has used leaf
It has to be something specific to your machine somehow, but im not sure why
that force attributes thing should help though, im not sure why it wouldn't
Werid
I had a feeling it would only be a bandaid fix for the underlying issue
ok nice
It was my game I didn't touched
So now what should I do ? Is the mod actually instelled in the game folder or I must do it manually?
As I said before, it's probably not good to use the mod in production yet (on the workshop) just because of the installer. The mod will work though, use the newly-created run configuration in the ide
How? Where?
I do not see any
reload the ide, it will show Zomboid Client
the run configuration is not a file, its in the top near the run button
Where?
on the right side, it will be near the build and debug buttons
I think "Current File" is where it sould be
If you reload the ide/project it should show up, though IDEA is usually a pain in the ass and takes a minute to show it for some reason
There is no such thing
It's actually importing Gradle project
This?
yes
dont use java 24, use Java 17
that is what PZ uses
In File > Project Structure, you change the Project SDK
Like this?
it's downloading
And after I go back to edit configuration and simply click "Run" ?
yes
you just swap to that configuration in the list and click either run or debug, depending on what you want to achieve. But run is generally the option you want
And now the project is ready for coding?
LLMs can definitely track identity of multiple things through thousands of lines.
it should be
Renaming some variables is actually a pretty good use case for them
I think you've convinced me to do some docs work over the following week lol
that was a fucking hassle, not that you did anything wrong, stuff just goes wrong sometimes
im literally going to put features and fixes on hold, going to document everything I can think of for a week, that should be enough time
I think sticking to the github readme/wiki is ok for now, there's not actually too much to document in terms of how leaf operates due to it being pretty similar to fabric
the only unique thing I need to document is mainly just the IDE setup process
aka what doctoubibe just went through lol
If you are writing markdown and commiting it to a repo, might as well be a docs site for Leaf. I really don't mind.
I've got a template and done it a bunch of times
Don't forget to mention the integrity of the Steam game files!
true that, I think that's been 2 or 3 people's problems (including you)
Are you talking like a github pages or something?
The game launch but there is no "HelloWorld" in the console output
Where goes the output ? user/Zomboid/console.txt is not the right file?
I do have a domain, and I did see albion use github pages before, but I never tried
I'll set it up and you can try it out
is your mod being loaded? check the top of the console
No console apeared, and the game launched does'nt seems to be the same game (?)
@floral sluice if you wanna get ahead of me set up a CNAME leaf pointing to aoqia.github.io. (with the period at the end)
Also the game is not in debug mode
yes you have to add that args yourself like the normal game, in the run configuration you can add "Program arguments" use this
does github not support custom domain?
I thought it did, without redirects
it does, that's how you set it up
it's not a redirect
if you want your domain to point at github, you have to tell youre registrar to do that
what???
oh ok
My save doesn't appeear
yes -_- it's an isolated environment/cachedir for developing
see the run folder in your project
LOG : Leaf f:0, t:1755343704011> Loading Project Zomboid 42.11.0-unstable.30715 with Leaf Loader 1.4.1
LOG : Leaf f:0, t:1755343704414> Loading 5 mods:
- java 17
- leafloader 1.4.1
\-- mixinextras 0.5.0
- modid 1.0.0
- zomboid 42.11.0-unstable.30715
There is no hello world in the output, should I start a game?
modid is your mod
so that's a good sign at least
the fact that there's no hello world is concerning to say the least
i think it's just debugln
possibly
change it to println and i bet it shows up
they kept chaging their logging system, I was gonna go insane
i've never seen the startup message from the mod during times my mod is definitely working and doing other stuff
logging is hard to get right XD
It's possible the log category that is used (I think its Mod or General, something like that) has log level set to Info at minimum
indeed
LOG : General f:0, t:1755344058078> Hello Leaf World!!! >w<
knew it
System.out.println
ya
It would be nice if their logging system was decent
like just switch to log4j already ๐ญ
I wanted to integrate that into the loader actually, so the logs arent so cancer
@floral sluice Can you guide me to achieve my goal? What if I want to create a window when I launch a game?
What are the method I can override such as onInitialize?
Can I do
onGameBoot
onGameTick
etc?
I should refer to the Event class?
Create a ISWindow or like an OS window
There is no ISWindow.class in project zomboid
And I don't know where the events are
it's lua, yeah
all the UI stuff is
I mean I think it traces back to a Java base class
like ISElement or something
Where is the documentation for Java modding ?
Blindly trying import zombie.ui.NewWindow;
@Override
public void onInitialize() {
System.out.println("Hello Leaf World!!! >w<");
NewWindow window;
window = new NewWindow(0, 0, 500, 500, true);
window.render();
}
There really isn't any. Java modding is completely centered around the Mixin library so you should start there and the Fabric docs
sec
Okay these tree lines
NewWindow window;
window = new NewWindow(0, 0, 500, 500, true);
window.render();
Produce a bunch of non-corelated errors
LuaEventManager.init
I think thats where most of the events are, you can search each one for references
or just search the event string in the project like "OnGameBoot"
There is none
That is yet another reason why Java modding is difficult and not widely used
You're essentially writing code against decompiled Java code, it's not going to be documented
Unless TIS decides to start releasing javadocs for b42+
I should really get that API going, even if it's very small for now
If you want to access lua stuff, you need to mixin the lua initialization to execute your callback. LuaManagerMixin.init
Is it normal that these tree lines of code produces errors with the freakin Texture class?
I speak window he throw me texture wich I dont give a fuck
When onInitialize is called, it's the very start of the mod intiialization. Mods are initialized before the game is (generally). You can use functions from the game, but if you are relying on a certain event to be executed or for Lua to be initialized, thats you need to do all yourself
The "Could not execute entrypoint stage 'main' due to errors" is not normal
But the game does have uncaught exceptions normally that dont seem to crash the game?
Check the log, it's porbably a mixin error
the console logs will tell you everything
Yes
Nothing in log file because the game won't start with this minor modification
Where is LuaEventManager.init ?
There is no onInitialize in https://pzwiki.net/wiki/Category:Current_Lua_events
Still it's the only method I know
onInitialize isn't a lua event
it's the entrypoint for the mod
I'm trying to understand with grep --after-context=1 "@Override" */*/*.java on my game files
All LUA event can be Override ?
In Java?
https://docs.fabricmc.net/develop/getting-started/introduction-to-fabric-and-modding
Some of this might be helpful to you, even if it is Minecraft-specific
scripting/objects/TimedActionScript.java: @Override
scripting/objects/TimedActionScript.java- public void OnScriptsLoaded(ScriptLoadMode scriptLoadMode) throws Exception {
scripting/objects/TimedActionScript.java- }
--
scripting/objects/TimedActionScript.java: @Override
scripting/objects/TimedActionScript.java- public void OnLoadedAfterLua() throws Exception {
scripting/objects/TimedActionScript.java- }
--
scripting/objects/TimedActionScript.java: @Override
scripting/objects/TimedActionScript.java- public void OnPostWorldDictionaryInit() throws Exception {
scripting/objects/TimedActionScript.java- }
--
scripting/objects/UniqueRecipe.java: @Override
scripting/objects/UniqueRecipe.java- public void Load(String string, String string2) throws Exception {
scripting/objects/UniqueRecipe.java- String[] stringArray = string2.split("[{}]");
These fonctions are not LUA events
How can I get list of event I can use in my mod?
@jagged scarab The LuaEventManager is Java, but in order to use it, you need to write Mixin code. You can't directly interact with the events you know and love from Lua.
What is your actual high-level goal?
My goal is to add a window when the game is started, fetch the player's frustum IsoObject and render it in 3d inside the window
oh that lol
I want to gently encourage you to find something else cool to work on but I guess you wont be convinced hehe
I'm okay with spending time on creating this mod
Everyone has suggested to not do this idea because it's unfeasable, but he can still try
I would say that if you insist, start with something else first.
Like an in-game window
Even more simple, like printing to the console anytime you get a bite from a zombie.
Learn how Mixin works, that's the most important thing you can do
Not many people know (actually probably only a select few people) what the questions you're asking, because not many people go to this area in the code
With regards to events, LuaEventManager has AddEvents() method which gets called and adds all the main events for the game. You can use its EventMap to get an event by name. You then add a callback to that event. When the event is triggered, the callback will be invoked.
Now...
How you do that with Mixin is anyone's guess!!
You gotta read the Mixin documentation and puzzle it out XD
I think you need an Invoker, and other stuff to muddle through the steps of adding a callback to the Event object
Another complication is that the LuaEventManager Event's require LuaClosure's as the callback
@jagged scarab which event are you trying to respond to?
It's probably easier to just inject some code into whatever Java would invoke that event, or would invoke the lua that invokes that event, etc.
I'm digging the LuaEventManager.java file
Yeah but which event are you interested in in the first place?
OnGameBoot (the player load a game)
OnGameTick
Maybe also OnPlayerHit or something (for testing as you suggested)
So what I would do is try to find somewhere in the Java code where the game is starting or potentially where that event is triggered, but specifically from the Java side
Also OnGameQuit
If you can find that, then you can probably just write a Mixin that injects your java code there
Instead of involving Lua at all
BTW, by window do you mean a standalone OS window, or like a Project Zomboid black pane window?
More like a black pane window at first, then after try to draw directly on the screen in place of the renderer
Or just a square in the upper corner
All of this im planning on adding to the leaf api so you dont have to!
causes less mixin collisions as well
Mixins don't stack?
depends what you try to manipulate
for the most part they do
but if you try to do something destructive or a noob uses the wrong annotations, it will be incompatible with any other mod that mixins that function/class/etc
First try: chat GPT
it does know about it
AFK 15minutes, thanks for your help. Mixin does not look that complicated with his @Inject and @Override attribute ?
Ill be back in a few minutes
++
@jagged scarab Yeah I'm not exactly sure what you'll need to do. I wonder if you can just new a NewWindow and then add it to the UIManager
Maybe you have to mixin a invoker on the constructor?
I'm back ๐ I tried new NewWindow in the onInitialize method but it won't build !!
what does it say
So you say I must put it in UIManager through Mixin
Random errors with textures XD
So don't put the code in the onInitialize
Instead mixin some game class, inject the new NewWindow code there
and add it to the UIManager if you can
resources might not fully be initialized when the mod is loaded, would recommend a later stage
you'll definitely need an invoker for calling the method on the UIManager instance
Well do you have an example or something? I'm really new to this
it's all in the docs we linked
There are more extensive docs here https://github.com/SpongePowered/Mixin/wiki
If you want to know literally everything about Mixin heh
yea thats great resource for mixin
I didn't link it becuase maybe its a bit too complex if you're just starting to use it lol
@jagged scarab https://wiki.fabricmc.net/tutorial:mixin_accessors#invoker
I'm reading the examples https://wiki.fabricmc.net/tutorial:mixin_examples
okkkkkkkkayyy
So
what onIntialization should contain in this context before I go further?
onInitialization isn't the interesting part
You write a new Mixin class instead
And register it in the mod's configuration
package com.example.mixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import zombie.core.Core;
import static com.example.ExampleMod.LOGGER;
@Mixin(Core.class)
public class ExampleMixin {
@Inject(method = "getVersion", at = @At("RETURN"), cancellable = true)
private void getVersion(CallbackInfoReturnable<String> cir) {
LOGGER.println("Changing the internal game version.");
cir.setReturnValue("43.123.69");
}
}
I have this at the moment
yeah you need a new file with a new mixin
you need to figure out a class to mixin with
and a method to inject your code into
maybe there's a method on core, i dunno
So, the code I pasted do:
- take zombie/core/Core.java class
- take the method "getVersion"
Then
Looks like GameState:enter() calls LuaEventManager.triggerEvent("OnGameStart")
- It paste
LOGGER.println("Changing the internal game version.");
cir.setReturnValue("43.123.69");
At = "Return" so I assume the bytecode goes at the end before return
before all returns
if there are multiple
but yup
You can probably mixin with GameState and inject on its returns, and run your window creation code there.
public class GameState {
public void enter() {
}
Looks empty
your decompile is bad or something
inside IngameState.java
sorry the class is IngameState
I used
find ./zombie/ -name "*.class" -exec sh -c 'java -jar cfr.jar "$1" > "${1%.class}.java" && echo "Decompile: $1"' _ {} \;
Fine
@jagged scarab use IDEA's search..
You have a good general knowledge of the game
no
i am just using IDEA
which let's me control click, find all usages, find who calls a thing, etc
I started modding zomboid like 5 days ago
I must import the class before trying to @Mixin(MyDestination.class) ?
You need to import MyDestination yes
and the classes that are for mixin annotations
just CTRL and . then hit import class
package com.example.mixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import static com.example.ExampleMod.LOGGER;
import zombie.core.Core;
import zombie.gameStates.IngameState;
@Mixin(IngameState.class)
public class ExampleMixin {
@Inject(method = "enter", at = @At("RETURN"), cancellable = true)
private void enter() {
LOGGER.println("The game starts!");
}
}
also whya re you decompiling classes individually
run genSources gradle task and then used the decompiled sources
eh this puts them into a jar and so you can't manipulate them at all, etc
i recommend using ZomboidDecompiler so you get actual text files
why would you want to manipulate source?
renaming variables?
running text tools on them?
I tried but I was facing errors when I tried
ok that was your use case, but he isnt doing that
he seems pretty inclined to text tools though
what is the reason for repacking the files into a jar though?
he's not
It's using CFR decompiler (another questionable thing) to decompile the classes
CFR is a pretty shit decompiler compared to fernflower/vineflower all things considered
Still good in some areas, but mostly superseded imo
The code I pasted doesn't work
i mean he's on the commandline so the code from the decompiler has to piped somewhere (grep, etc)
its storing it just as .java files
the output of each decompiled class file
text files!!
not sure, what happens
is this a new class or did you just change the example one
are you using the minecraft plugin for IDEA
I just changed the Mixin example on