#Leaf (forked from FabricMC/fabric)

1 messages ยท Page 2 of 1

full mountain
#

and that the issue isn't on the lua side of things

floral sluice
#

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

tropic stirrup
#

I can see it in the debugger, however in Lua it just returns nil ๐Ÿ˜ญ

floral sluice
#

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?

tropic stirrup
#

LinkedFluidContainer.class is exposed yes, I can access it in Lua

full mountain
#

if the enum member is inserted properly i don't get how it could ever be filtered out, even accidentally

tropic stirrup
#

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

floral sluice
#

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

tropic stirrup
floral sluice
#

hmm true, its probably getting inserted at a later point or something, im doing some testing rn as well because why not

floral sluice
floral sluice
#

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

tropic stirrup
#

It's private
otherwise, I get a ton of errors

floral sluice
#

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

valid nova
#

Do you guys are trying to create new components like fluid components ?

floral sluice
#

thats what gigawatte is trying to do

tropic stirrup
full mountain
#

i see, as i guessed it's not 'really' adding to the enum properly

floral sluice
#

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

floral sluice
#

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??

full mountain
#

yes

floral sluice
#

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

full mountain
#

how would you expect a non-static field to work here anyway?

#

we're not accessing it through an instance

floral sluice
#

true, it was worth a shot though

#

idk what kahlua is like with this stuff

full mountain
#

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

floral sluice
#

well I dont think values() is static either... so this means cant use that

tropic stirrup
full mountain
#

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

tropic stirrup
#

Second entry is definitely related to my changes

tropic stirrup
floral sluice
#

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

floral sluice
#

can you share that snippet

tropic stirrup
floral sluice
#

thats why, probably cant make it private either right?

tropic stirrup
floral sluice
#

nice

floral sluice
#

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

floral sluice
#

Also this will be nice ๐Ÿ™‚
its the simple things

#

you know what isn't nice, discord's really annoying image photo album feature

valid nova
#

Dear god please don't do that

floral sluice
#

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

valid nova
valid nova
#

Idk ๐Ÿ˜‚

tropic stirrup
floral sluice
#

no way choco made that lol

#

project seems really abandoned though, ill ask around

floral sluice
#

and the boilerplate for mixin in the end of init is too annoying imo over a simple function override

floral sluice
#

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.

floral sluice
#

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.

floral sluice
#

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 ;-;

tropic stirrup
#

Hii @floral sluice
B42.11 has already been released. Could you please update the manifests when you have some time? Thx!

valid nova
#

I think it's needed

olive flower
#

42.11.0-unstable.30715

floral sluice
#

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

dull stirrup
#

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.

floral sluice
#

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)

valid nova
#

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

dull stirrup
#

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.

floral sluice
#

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

floral sluice
#

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

dull stirrup
# floral sluice for example in steam, it might look like `-Dleaf.log.level=trace -Xmx8192m -- -p...
[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
floral sluice
#

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

floral sluice
#

back to square one, no clue why it doesnt work in prod environment, probably going to take a little longer to figure out lol

floral sluice
#

ok its driving me fucking insane and im pretty busy right now so I'll come back to it when I can

spark plinth
#

Hey, anybody got similar issue while building example mod (it is fresh git clone no changes)?

floral sluice
#

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

spark plinth
#

woops i've missed that, now it works like a charm, thanks ๐Ÿซถ

floral sluice
#

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.

floral sluice
#

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)

rare mural
#

@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?

rare mural
#

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.

rare mural
#

@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!

floral sluice
#

hmmmmmmmm

floral sluice
rare mural
#

gotcha

floral sluice
#

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.

floral sluice
#

I should probably create a FAQ on the example mod for this

rare mural
#

@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.

floral sluice
#

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

rare mural
#

@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:

floral sluice
#

you probably need to update the loader version in the libs.versions.toml

#

I haven't changed it in the example mod repository yet

rare mural
#

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.

floral sluice
#

๐Ÿค”

rare mural
#

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"
floral sluice
#

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

rare mural
#

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

floral sluice
#

The example mod gets applied at runtime, you shouldn't need to

rare mural
#

hmm, if its working correctly, the version number should say 43 right?

floral sluice
#

Unless you're running in prod then you need to either install a mod from the workshop or manually put the mods

rare mural
#

yeah from ide, get the no mappings thing in prod

floral sluice
rare mural
#
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

floral sluice
#

huh wtf is going on

#

But it works if you don't change the cachedir?

#

or still the same problem

rare mural
#

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

floral sluice
#

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

rare mural
#

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
floral sluice
#

This is super odd. I am doing some testing of my own rn

rare mural
#

cool

floral sluice
#

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

rare mural
#

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.

floral sluice
#

Yes, it doesn't get copied over into run/ at all, it's applied from build/libs when you run the game in IDE

floral sluice
#

Ok going back to loader 1.2.0 lets the mods load, im going to fix this and then push an update very soon

rare mural
#

Cool, I'm excited to try this all out. ๐Ÿ™

floral sluice
#

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

rare mural
#

at least it was an easy fix ๐Ÿ™‚

floral sluice
#

If you find any more issues, please post them as an issue on the github if you can, because it helps me track issues

rare mural
#

@floral sluice how can I pull in 1.4.1

floral sluice
#

It's being published to maven right now

rare mural
#

ah I see

floral sluice
#

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

rare mural
#

๐Ÿ˜ฎ

floral sluice
#

It is published, you should be able to use it now

rare mural
floral sluice
#

is that good or bad

rare mural
#

good it means that the example mod loaded, right?

floral sluice
#

yippeeeeeeee

rare mural
#

๐Ÿฅณ

floral sluice
#

You can always check in the mod list at the top of the console, but yeah it means the mod loaded

rare mural
#

now to remember how to write java and to learn how mixins work

floral sluice
#

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

rare mural
#

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);
    }
}
floral sluice
#

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

rare mural
#

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?

floral sluice
#

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

rare mural
#

Am I able to breakpoint game code? Do I need to run the decomp gradle task first?

floral sluice
#

run the genSources task and then in the sources you can set breakpoints

rare mural
floral sluice
#

yea, I am mixining it to add an event, and it did work for me

rare mural
#

can you share the code

#

also once you run the genSources task, where are the sources?

floral sluice
#

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

rare mural
#

when i did that IDEA claimed to be doing the decompilation itself

#

maybe that's expected, i'm not super java-aware

floral sluice
#

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

rare mural
#

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.

floral sluice
#

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

rare mural
#

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

floral sluice
#

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

rare mural
#

Can you show the code where you mixed in on random damage?

#

Oh you have to manually register new mixins don't you

floral sluice
#

Do you have the IDEA plugin installed? (Look in pinned messages)

rare mural
#

I see.

#

Pretty cool, breakpoint in the version mixin.

floral sluice
#

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

rare mural
#

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?

floral sluice
floral sluice
rare mural
#

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

rare mural
#

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

rare mural
#

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 ๐Ÿ˜…

floral sluice
rare mural
#

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

#

ยฏ_(ใƒ„)_/ยฏ

floral sluice
#

Fixing the lock issue rn

rare mural
#

holy hell that will be something

floral sluice
#

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

rare mural
#

i believe them, but my intuition would be the opposite

floral sluice
rare mural
#

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

floral sluice
#

It does work, it's just jank and unsupported fully

#

Especially since you basically need the special JVM from jetbrains to use it

rare mural
#

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

rare mural
floral sluice
#

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

floral sluice
#

im mega tired, so im going to finish it all tmr

dull stirrup
# floral sluice I still don't think that the argument issue was sneijk's actual issue though, be...

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.

floral sluice
#

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

rare mural
#

@floral sluice any luck with the file lock stuff?

floral sluice
#

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

rare mural
#

ah cool

spark plinth
#

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

rare mural
#

That's not where the JAR goes. Download the example mod from the workshop.

spark plinth
#

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

rare mural
#

Leaf mods don't show up in the in-game mod list

#

The log will say what leaf mods were loaded

floral sluice
#

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

rare mural
#

I could be interested in helping with that kind of thing

floral sluice
#

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

rare mural
#

pfffffffff no worries XD

#

polish that thang

#

what do you mean by upstream changes btw? fabric stuff you gotta merge in?

floral sluice
#

Yes, stuff from FabricMC's repositories

rare mural
#

makes sense

floral sluice
#

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

rare mural
#

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

floral sluice
#

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

rare mural
#

improving the maintainability of projects is something i enjoy but i don't understand leaf enough quite yet to help with that stuff

floral sluice
#

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

rare mural
#

but helping with leaf api and building some mod listing / option stuff i could probably at least help with

floral sluice
#

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

rare mural
#

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.

floral sluice
#

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...

floral sluice
#

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 ๐Ÿ˜‚

floral sluice
#

I wont be doing any commits over the weekend unless really necessary, so this is actually good timing

spark plinth
# rare mural The log will say what leaf mods were loaded

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

spark plinth
#

This is example mod downloaded from workshop that doesn't load

rare mural
rare mural
rare mural
#

alright going to bed, excited to try the new version tomorrow

spark plinth
#

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

floral sluice
#

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

rare mural
floral sluice
#

mods already specify the version of leaf and game they are compatible with via the mod json

floral sluice
#

I did change that, but I havent updated the example mod on the workshop in a while

floral sluice
#

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

rare mural
valid nova
#

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 ?

floral sluice
#

You can already install multiple leaf versions btw jvla

valid nova
#

But what about mods having different versions of the mod specific for different Leaf versions

floral sluice
#

switching between them is done via changing the pzexeconfig param. This doesn't apply to servers though.

valid nova
#

From my understanding of it, mods are fixed to a version ?

valid nova
#

That's what he meant with the subfolders

floral sluice
#

yeah since steam only keeps the latest for download

valid nova
#

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

floral sluice
#

ok I could do that as an optional feature

valid nova
#

Have something where it loads the closest Leaf version basically

floral sluice
#

create an issue for it on the github for loader. it doesn't need to be fancy just explaination for future me

valid nova
#

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

floral sluice
#

true

rare mural
#

@floral sluice Just checking, did you forget to push the new version?

#

Or still tinkering on it?

rare mural
#

Holy moly!!! The hotswapping works!

valid nova
#

hotswapping ?

rare mural
#

Change the code, hit save, and the java is reloaded while the game is running

#

amazin

valid nova
#

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 ?

rare mural
#

It's not really Leaf per-se, it's the Mixin library that underpins Fabric

#

Mixin + a custom javaagent from the fabric team

valid nova
rare mural
#

@floral sluice does Leaf come with mixinextras

#

wait, it must, that was the jar that was being locked yesterday

valid nova
#

It does I think yea, I remember something with this name

rare mural
#

@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.

full mountain
#

i think she mentioned the other day that she wasn't using our mappings

#

so probably no parameter names until then

rare mural
#

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? ๐Ÿค”

full mountain
#

in that case, nobody has ever made mappings for local variables

rare mural
#

@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?

full mountain
#

i'm not really sure why you can't do that, it probably is because leaf decides to jar the sources for whatever reason

rare mural
full mountain
#

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)

rare mural
#

Oh the mappings are for lua, I see.

full mountain
#

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

rare mural
#

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

full mountain
#

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 ๐Ÿ˜…

rare mural
#

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

full mountain
#

yeah, that would be the ideal for me but i have no idea if that could work

rare mural
#

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

full mountain
#

i honestly have no idea how mappings are normally done, the minecraft community keeps their secrets

rare mural
#

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

full mountain
#

we could probably make some local tool that parses the file and extracts names

rare mural
#

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

full mountain
#

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

rare mural
#

know what I mean?

full mountain
#

even i hadn't contributed anything (manually, beyond the tooling that generates what data we can) until literally today

rare mural
#

by played back, I mean, having IDEA go and do all those refactors using the refactor machinery

full mountain
#

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

rare mural
#

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

full mountain
#

yeah, that definitely sounds the most realistic to me

rare mural
#

(and then playback those renames by ingesting the same file)

full mountain
#

i can't imagine their plugin API can't do that

rare mural
#

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

rare mural
#

@full mountain well now I gotta try don't I

floral sluice
rare mural
#

oh sorry, I can parse it now

#

getting sleepy XD

floral sluice
#

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

rare mural
#

Hmm, the game isn't obsfucated, but there are missing local variable names all over. Would what you're talking about magically resolve those?

floral sluice
#

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)

floral sluice
#

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

rare mural
#

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.

full mountain
#

no, we never had data about locals to begin with

rare mural
#

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.

floral sluice
# full mountain i honestly have no idea how mappings are normally done, the minecraft community ...

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

rare mural
#

What do you mean that it's not obsfucated if local variable names are mangled?

floral sluice
#

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

rare mural
#

I have an IDEA plugin going, I'm currently exploring the intellij API regarding rename stuff.

rare mural
#

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

rare mural
#

@full mountain

#

it renamed part to bodyPart

rare mural
#

@full mountain what do you think

full mountain
#

very cool!

rare mural
#

@full mountain how should collaboration work?

#

๐Ÿค”

floral sluice
#

maybe just being able to export it?

#

also how does it handle when something is removed

rare mural
rare mural
floral sluice
#

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

rare mural
# floral sluice yes, or if function or class gets nuked

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.

rare mural
#

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

floral sluice
#

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

rare mural
#

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.

floral sluice
#

hmm ok. This will be a decent enough solution until enigma gets local renaming

#

one variable rename is fine honestly

rare mural
#

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

floral sluice
#

yes exactly lol

rare mural
#

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 ๐Ÿ˜‚

floral sluice
#

@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

jagged scarab
#

@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?

full mountain
#

didn't this happen to me because I was using symlinks

floral sluice
#

The game is copied to be manipulated only in the dev environment (and also to be ran correctly in the IDE)

floral sluice
#

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

rare mural
jagged scarab
floral sluice
#

This is the main outer-trycatch statement I was talking about

rare mural
#

But fair enough

floral sluice
#

You can see this being thrown in the stacktrace, but it's not followed by the Throwable at all

rare mural
#

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.

floral sluice
#

Yea it's called "Extract"

#

good feature

rare mural
#

JetBrains are actual gods at automatic refactor stuff

floral sluice
#

if only the IDe didnt run like ass

rare mural
#

Rider/Reshaper are actually marvels of engineering imo

floral sluice
#

java frontend ๐Ÿ™ who let java people cook

rare mural
#

hehe

jagged scarab
#

@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?

floral sluice
#

Look at the "Failed to copy file from X to Y" in the stacktrace

#

thats the intention

jagged scarab
#

That means doCopyGameFile fails with an internal exception but what is it?

floral sluice
#

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.

jagged scarab
#

It must be something obvious?

floral sluice
jagged scarab
floral sluice
#

maybe teh file exists check is one of the things I don't handle, but it's because it doesn't throw any exceptions

floral sluice
#

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

rare mural
#

Check out the new UI:

floral sluice
#

That is nice

jagged scarab
#

@floral sluice let me turn on my computer and find a way tonmake it works

floral sluice
#

If you can run loom in debug, surely that would make the issue reveal itself

#

beats relying on the half drunk stacktrace

jagged scarab
#

I checked the source file, it exists in my game folder

#

Idk why it throw an exception

rare mural
#

What's the exception? Is it another locking issue? (shot in dark)

jagged scarab
#

This exception

#

Like if the file where not found

floral sluice
#

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"

jagged scarab
#

I readed your screenshot of the source and IDK which Exception fires

floral sluice
#

Which the inner exception should be printed in the stacktrace, but here it's not for some reason?

jagged scarab
rare mural
#

Have you two tried Cursor, asking Claude to look at it etc?

floral sluice
#

HELL NAW

#

I don't vibe code unfortunately (or fortunately)

jagged scarab
#

me too

#

But it's sometime useful I admit

floral sluice
#

Copilot is rather good for complex mathemtical formulas (sometimes)

rare mural
#

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

floral sluice
#

@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

rare mural
#

Getting Leaf running under a debugger would probably be a huge boon

floral sluice
#

I don't think I'll be able to get any useful information until he debugs it yea

rare mural
#

If I can't get something running under a debugger I start feeling hopeless

floral sluice
#

oh tahts a better stacktrace this time

#

that is way better

#

it's showing the inner exception I was talking about earlier

jagged scarab
#

It's the stack trace from yesterday I didn't modifyed it

floral sluice
#

Hmm, yesterday you didnt publish the full one then

jagged scarab
#

No because it was very long

floral sluice
#

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?
jagged scarab
#

Almost the entire game was copied without any error that's enven weirder

jagged scarab
floral sluice
#

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^

jagged scarab
#

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"
floral sluice
#

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

jagged scarab
#

So you have a .att hash file for every file in the game?

floral sluice
#

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

jagged scarab
#

Okay

#

I was wondering how you store the hash in the file attribute, since it's only basics flag like Archive,System,Hidden etc

floral sluice
#

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

jagged scarab
#

Weird

floral sluice
#

In albion's case, she had symlinked the .gradle folder in your user home which Java throws a tantrum over

jagged scarab
#

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

floral sluice
#

loom is a separate plugin for gradle, it's used by the example mod

jagged scarab
floral sluice
# jagged scarab I was wondering how you store the hash in the file attribute, since it's only ba...

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...

floral sluice
#

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

rare mural
#

@floral sluice you should grab Excalidraw and make a nice diagram ๐Ÿ™‚

jagged scarab
#

But you can force the program to produce .att file anyway?

#

Forget about Extended file attributes maybe?

floral sluice
rare mural
#

All the parts of leaf and some description about them

floral sluice
#

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

jagged scarab
#

I didn't symlinked or anything .gradle, just following the README steps

floral sluice
#

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

jagged scarab
#

So the bug is dues to thread IO "collision"?

floral sluice
#

Funnily enough some of these fixes not even Fabric has. Maybe I should contribute some of these lol

rare mural
#

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

floral sluice
#

I've been doing this manually whole time because some changes I do not want, that are specific to Minecraft

rare mural
#

Yeah but not cherry-pick right? You manually do this

#

yeah but you'd create commits ontop of their commits that remove that stuff

floral sluice
#

I only discovered cherry picking recently. I tried it and sometimes it works but there's too much collision so Git gets angy

rare mural
#

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

floral sluice
#

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

rare mural
#

yeah but you can likely customize even that, with whatever commits ontop of their work make it so

floral sluice
#

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

rare mural
#

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

floral sluice
#

with your plugin

rare mural
#

what do you mean?

floral sluice
#

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

full mountain
#

when i thought about it in the past i felt that way too

floral sluice
#

if you store the index of which local is renamed, this issue still happens

rare mural
#

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

floral sluice
#

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

rare mural
#

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

floral sluice
#

I see, you are doing temporary renaming for each version as you try to read the code?

rare mural
#

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

floral sluice
#

hmm if this helps you that is good. I wont use this personally because I find reading the unnamed locals normal

rare mural
#

ยฏ_(ใƒ„)_/ยฏ

floral sluice
#

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

jagged scarab
#

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

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

jagged scarab
#

I'm trying to rebuild everything

floral sluice
#

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?

floral sluice
#

If it is, verify game files in Steam

jagged scarab
jagged scarab
#

Okay it's verificating file integrity

floral sluice
#

yes through steam

jagged scarab
#

There where 1 corrupted file

#

Downloading/fixing

#

I don't know why there is 1 corrupted file.....

floral sluice
#

Sometimes steam will just shit the bed

#

or the file gets modified for some random reason

#

seemingly a common occurance for pz somehow

jagged scarab
#

I'm rebuilding... ๐Ÿ‘€

floral sluice
#

you';re getting my hopes up ๐Ÿ˜‚

jagged scarab
#

it works on your machine??

floral sluice
#

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

floral sluice
#

I had a feeling it would only be a bandaid fix for the underlying issue

jagged scarab
#

Omg

#

BUILD SUCCESSFUL in 2m 53s

floral sluice
#

ok nice

jagged scarab
#

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?

floral sluice
#

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

jagged scarab
#

I do not see any

floral sluice
#

reload the ide, it will show Zomboid Client

jagged scarab
floral sluice
#

the run configuration is not a file, its in the top near the run button

floral sluice
#

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

jagged scarab
#

It's actually importing Gradle project

floral sluice
#

yes

#

dont use java 24, use Java 17

#

that is what PZ uses

#

In File > Project Structure, you change the Project SDK

jagged scarab
#

it's downloading

#

And after I go back to edit configuration and simply click "Run" ?

floral sluice
#

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

jagged scarab
#

And now the project is ready for coding?

rare mural
floral sluice
rare mural
#

Renaming some variables is actually a pretty good use case for them

floral sluice
#

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

rare mural
#

Want me to set up a nice modern docs site?

#

Just merge markdown and it deploys

floral sluice
#

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

floral sluice
#

the only unique thing I need to document is mainly just the IDE setup process

#

aka what doctoubibe just went through lol

rare mural
#

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

jagged scarab
floral sluice
#

true that, I think that's been 2 or 3 people's problems (including you)

floral sluice
jagged scarab
#

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?

floral sluice
#

I do have a domain, and I did see albion use github pages before, but I never tried

rare mural
#

I'll set it up and you can try it out

floral sluice
jagged scarab
rare mural
#

@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)

jagged scarab
#

Also the game is not in debug mode

floral sluice
#

yes you have to add that args yourself like the normal game, in the run configuration you can add "Program arguments" use this

floral sluice
#

I thought it did, without redirects

rare mural
#

it's not a redirect

#

if you want your domain to point at github, you have to tell youre registrar to do that

floral sluice
jagged scarab
floral sluice
#

yes -_- it's an isolated environment/cachedir for developing

#

see the run folder in your project

jagged scarab
# floral sluice 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?

rare mural
#

I've never actually seen debugln work

#

println seems to work though

rare mural
#

so that's a good sign at least

floral sluice
#

the fact that there's no hello world is concerning to say the least

rare mural
#

i think it's just debugln

floral sluice
#

possibly

rare mural
#

change it to println and i bet it shows up

floral sluice
#

they kept chaging their logging system, I was gonna go insane

rare mural
#

i've never seen the startup message from the mod during times my mod is definitely working and doing other stuff

rare mural
floral sluice
#

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

jagged scarab
rare mural
#

knew it

jagged scarab
#

System.out.println

rare mural
#

ya

floral sluice
#

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

jagged scarab
#

@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?

rare mural
#

Create a ISWindow or like an OS window

jagged scarab
#

And I don't know where the events are

rare mural
#

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

jagged scarab
#

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();
    }
rare mural
#

sec

jagged scarab
#

Okay these tree lines

NewWindow window;
window = new NewWindow(0, 0, 500, 500, true);
window.render();
#

Produce a bunch of non-corelated errors

floral sluice
#

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"

floral sluice
#

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

jagged scarab
#

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

floral sluice
#

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

floral sluice
#

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

jagged scarab
#

Nothing in log file because the game won't start with this minor modification

#

Where is LuaEventManager.init ?

floral sluice
#

it's the entrypoint for the mod

jagged scarab
#

I'm trying to understand with grep --after-context=1 "@Override" */*/*.java on my game files

#

All LUA event can be Override ?

#

In Java?

floral sluice
floral sluice
jagged scarab
#
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?

rare mural
#

@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?

jagged scarab
rare mural
#

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

jagged scarab
floral sluice
#

Everyone has suggested to not do this idea because it's unfeasable, but he can still try

rare mural
#

I would say that if you insist, start with something else first.

jagged scarab
rare mural
#

Learn how Mixin works, that's the most important thing you can do

floral sluice
#

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

rare mural
#

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.

jagged scarab
rare mural
#

Yeah but which event are you interested in in the first place?

jagged scarab
#

OnGameBoot (the player load a game)
OnGameTick
Maybe also OnPlayerHit or something (for testing as you suggested)

rare mural
#

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

jagged scarab
#

Also OnGameQuit

rare mural
#

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?

jagged scarab
rare mural
#

lol

#

@jagged scarab jokes aside, the black window thing is mostly a Lua side thing

jagged scarab
floral sluice
#

causes less mixin collisions as well

rare mural
#

Mixins don't stack?

floral sluice
#

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

jagged scarab
rare mural
jagged scarab
#

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

#

++

rare mural
#

@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?

jagged scarab
rare mural
#

what does it say

jagged scarab
#

So you say I must put it in UIManager through Mixin

jagged scarab
rare mural
#

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

floral sluice
#

resources might not fully be initialized when the mod is loaded, would recommend a later stage

rare mural
#

you'll definitely need an invoker for calling the method on the UIManager instance

jagged scarab
#

Well do you have an example or something? I'm really new to this

rare mural
#

it's all in the docs we linked

#

If you want to know literally everything about Mixin heh

floral sluice
#

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

rare mural
jagged scarab
rare mural
#

check the link i just sent

#

UIManager is all static

jagged scarab
#

So

#

what onIntialization should contain in this context before I go further?

rare mural
#

onInitialization isn't the interesting part

#

You write a new Mixin class instead

#

And register it in the mod's configuration

jagged scarab
# rare mural You write a new Mixin class instead
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

rare mural
#

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

jagged scarab
#

So, the code I pasted do:

  1. take zombie/core/Core.java class
  2. take the method "getVersion"
    Then
rare mural
#

Looks like GameState:enter() calls LuaEventManager.triggerEvent("OnGameStart")

jagged scarab
#
  1. 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

rare mural
#

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.

jagged scarab
rare mural
#

your decompile is bad or something

#

inside IngameState.java

#

sorry the class is IngameState

jagged scarab
jagged scarab
rare mural
#

@jagged scarab use IDEA's search..

jagged scarab
#

You have a good general knowledge of the game

rare mural
#

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

jagged scarab
#

I must import the class before trying to @Mixin(MyDestination.class) ?

floral sluice
#

You need to import MyDestination yes

#

and the classes that are for mixin annotations

#

just CTRL and . then hit import class

jagged scarab
#
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!");
    }
}
floral sluice
#

run genSources gradle task and then used the decompiled sources

rare mural
#

i recommend using ZomboidDecompiler so you get actual text files

floral sluice
#

why would you want to manipulate source?

rare mural
#

running text tools on them?

jagged scarab
floral sluice
#

ok that was your use case, but he isnt doing that

rare mural
#

he seems pretty inclined to text tools though

#

what is the reason for repacking the files into a jar though?

floral sluice
#

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

jagged scarab
#

The code I pasted doesn't work

rare mural
#

i mean he's on the commandline so the code from the decompiler has to piped somewhere (grep, etc)

floral sluice
#

the output of each decompiled class file

rare mural
#

text files!!

rare mural
#

is this a new class or did you just change the example one

#

are you using the minecraft plugin for IDEA

jagged scarab