• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Cerrie Hot Reload & 'initialization'?

Status
Not open for further replies.
Level 11
Joined
Aug 25, 2006
Messages
971
Hello,

First off I realize that both ceres and cerrie have more-or-less been abandoned. I didn't want to let a little abandonware come between me and excellent tooling so I've given a shot at using them.

Honestly all-in-all my experience has been excellent. (Regardless of current project status, the author deserves super props!) Hot reload is the best thing ever. I remember having to spend multiple minutes waiting for my map to save and then for Wc3 to boot up between every test. Being able to hot reload is completely worth the minor architecture constraints imposed.

I'm wondering if anyone else is using Ceres + Cerrie. I'm trying to figure out the cleanest way to handle initialization. Basically I want to run code when:
  1. The map starts
  2. Cerrie does a hot reload

Just putting lua/typescript in the base of files actually fills both conditions with one minor problem. During #1 lua code put in the 'base' of the files runs before Warcraft 3 is fully initialized and as such has all kinds of weird problems. One example is FourCC spits out a LUA error, but its hardly the only blizzard method that breaks when called from that base lua file.

During a hot reload everything works just fine because warcraft 3 is fully initialized by that point, all methods work as intended.

Currently I have a work around that looks like this:
JavaScript:
let isHotReload = true;
util.contextFn("onetimeSetup", () => isHotReload = false);

function Setup() {
    // Do my setup
}

if (isHotReload) {
    Setup();
} else {
  // Schedule Setup() to run at a later time [when wc3 is initialized]
}

I'm curious if anyone else is using cerrie and has any thoughts. Or knows why FourCC doesn't work properly when called in the base lua file (as built by ceres)
 

~El

Level 17
Joined
Jun 13, 2016
Messages
551
Hi!

Basically, Ceres has a few entrypoints for runnable code which are all a bit finicky and serve slightly different purposes.

It supports 3 different modules/files as "entries" into your map code:
- init.lua
- main.lua
- config.lua

Which one you use will determine at which point during the map's lifecycle your code will run.

init.lua runs when the script is loaded or re-loaded. This is the earliest point for runnable code and happens before main and config. Because it happens very early, WC3 is still in a partially-initialized state, and so a lot of natives don't work, and I think that happens even before WC3's builtin Lua helper file. I think that's where your FourCC issue comes from if you're using init.lua. In general I don't really recommend using it at all, unless you actually need it, because there's all sorts of weird issues with it.

main.lua runs when WC3 calls the map's "main" function (and also on hot reload), and this is the traditional entrypoint into the script logic (e.g. for JASS that was the earliest possible execution point at all). config.lua is the same except with the "config" function.

If you're using init.lua then I think that's what your problem is boiling down to, and you should try switching to main.lua.

EDIT:
Ceres also has a flag `ceres.initialized` which is set to `false` during that very finicky initialization phase where things aren't available, so you can rely on that to do the dirty work of distinguishing between init and hot reload.
 
Level 11
Joined
Aug 25, 2006
Messages
971
Thanks for making all these great tools and still providing support =)

So what you said totally makes sense however it does differ from the behavior I'm seeing slightly:
  • I'm using main.lua (or main.ts actually but I see it compiles straight to main.lua)
  • Checking ceres.initialized in main.lua returns false (unless its a hot reload)
  • There's no init.lua/ts script in my project

So it seems like main.lua has the behavior you prescribed to init.lua. If it would help I can create a 'minimum size example' using the typescript template.

Thanks again!
 

~El

Level 17
Joined
Jun 13, 2016
Messages
551
Thanks for making all these great tools and still providing support =)

It brings me joy knowing someone's finding this stuff useful. I appreciate that <3

On to the troubleshooting:

Which version of Ceres are you using? This behaviour should happen in the latest public Ceres release (0.3.6).

What would be most helpful in troubleshooting this if you sent over the war3map.lua of your map (or of a reproduced example, in case you're not comfortable sharing your code). Then I should be able to figure out what the problem was very quickly.

In the meanwhile, what you can try to do is rename your main.lua to something like entrypoint.lua, and then in main.lua load entrypoint.lua with a timer or something like that. But I'm not entirely sure, since the latest Ceres version was supposed to work out of the box without these issues. At least it used to work last I used it, but that was almost a year ago by this point.
 
Level 11
Joined
Aug 25, 2006
Messages
971
I haven't written too much yet so I don't mind sharing at all. I've attached war3map.lua (in a zip so hive workshop allows the upload)

As far as I can tell ceres.init() is called at the bottom of war3map.lua, and then immediately/directly calls the 'main.lua' module.

I did also validate that my ceres version is 3.6:

Code:
C:\Main\Wc3All\Ceres>ceres --version
Ceres 0.3.6
 

Attachments

  • war3map.zip
    27 KB · Views: 36

~El

Level 17
Joined
Jun 13, 2016
Messages
551
Right, I've looked at your script and everything seems fine.

Regarding the main.lua behaviour: ceres.init() redefines the global "main" function to execute your main.lua module during the first execution of the script. It only calls main.lua immediately if it's a hot reload (indicated by ceres.initialized == true).

That said, I'm not sure what else could be going wrong here, if I'm honest. The only other thing I can think of that might be causing this is that the original "main" function gets called -after- main.lua, and that might screw up some things related to map setup, but I'm not sure. I've had this exact setup in my test map for ages and haven't had many issues with it - but I also didn't have a lot of "base" code running other than registering triggers etc.

If you have examples of issues other than FourCC breaking down, I'd be happy to wrangle my brains over them for a bit. You can also use Cerrie's util methods instead of FourCC since they're supposed to be more robust in the first place - util.id2s and util.s2id.

One other thing of note: I might be misremembering, but it might be the case that some natives were always broken during map init. Often things had to be executed in a 0-duration timer to function properly. Not sure if that's your issue here.

If it helps any, here's a test map I used for developing Ceres and Cerrie. It has quite a few examples of how Cerrie was intended to be used, since most of Cerrie was actually factored out of that codebase in the first place.
 
Level 11
Joined
Aug 25, 2006
Messages
971
You might be right about the natives just always being broken on map start! I'm using a zero second timer and it seems to have solved my problems.

And you're totally right, I saw the utility functions to replace fourcc and have absolutely been using them so thank you for that! I'm also going to check out your test map. Thanks again =)
 
  • Like
Reactions: ~El
Status
Not open for further replies.
Top