• 🏆 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!

Best of the Wurst 9

Status
Not open for further replies.
Level 23
Joined
Jan 1, 2009
Messages
1,608


In the last couple of months, we have reached over 100 stars on GitHub, updated our homepage, and as usual caught up with support for Warcraft 3 patches 1.30.2 and beyond.


Tool updates

  • The wurst family of tools now supports the latest battle.net stable patch (1.30.2).
  • The wurst language was updated to allow classes to contain tuple array members.
  • Improper usage of generic types now throws proper compilation errors
  • Attempting to access objects that are known to have already been destroyed now fails at compile time
  • Fixed a bug in local optimizations which caused unexpected behavior.
  • Wurst no longer requires JavaFX, which enables wurst builds in a wider range of java distributions.

Standard library highlights

  • Merged over a dozen awesome pull requests.
  • Added DummyCaster in addition to InstantDummyCaster for channel based spells, and spells with delayed effects.
  • Fixed some critical bugs in HashList, HashSet and Knockback3D.
  • We have newly-added code conventions - go align your formatting!
  • We have begun writing in-depth package documentation

>> Read more <<
 

Attachments

  • stacktrace.png
    stacktrace.png
    131.3 KB · Views: 255
  • wurstbanner9.png
    wurstbanner9.png
    223.9 KB · Views: 275
Last edited:
Level 23
Joined
Jan 1, 2009
Messages
1,608

Spotlight: Stack traces

Did you know that WurstScript generates stack traces for calls of error(string msg) from the ErrorHandling package?
You might have seen this from a wurst error before - it will show you which lines in your code were executed in what order before the error occured.

Take a look at this example:

Wurst:
package Test
import ErrorHandling

function foo()
    new A().bar()

class A

    function bar()
        error("This is an error message")

init
    foo()
It produces the following stacktrace ingame:

0yUYIyy.png


As you can see the most recent line comes at the top and the oldest at the bottom. Stack traces help tremendously with debugging errors, as it gives you a history of what happened before the error. Naturally they cause quite a performance hit. If you verified your map working well, you can disable them via the corresponding runarg -stacktraces, which is enabled by default.
 
  • Like
Reactions: pyf
Level 23
Joined
Jan 1, 2009
Messages
1,608
I suppose it only causes a performance hit if the error actually occurs, or have I misunderstood something? :O

No, they always do since the stacktrace is built at any time to be available when the error occurs. You can easily see this in the generated code.
It is usually negliable, hence default on. But it doess add quite a few lines, and you can notice this in heavy or performance critical operations in single digit FPS differences or so.
 
Level 5
Joined
Mar 5, 2015
Messages
135
No, they always do since the stacktrace is built at any time to be available when the error occurs. You can easily see this in the generated code.
It is usually negliable, hence default on. But it doess add quite a few lines, and you can notice this in heavy or performance critical operations in single digit FPS differences or so.

Holy moly - here I thought I finally knew what I was doing, haha :D That's really good to know, thank you! Glad you made a spot on it, otherwise I would never have given it a thought ;) Have to learn something new every day, eh? :)

Really love these tips/tricks/mini tutorials btw! Thank you for being awesome
 
Level 23
Joined
Jan 1, 2009
Messages
1,608
Any plans to target lua once the support is supposedly implemented in the game?
We reopened our Lua backend ticket that was oroginally intended for dota2, so yes, it's kinda planned.

eally love these tips/tricks/mini tutorials btw! Thank you for being awesome

Thanks, glad you like it.

This just does full to Jass compilation right? So should have no issues with new World Editor patches that you wouldn't have otherwise anyway?

What is full jass compilation? World editor patches don't affect existing maps and the editor is only to be used for terrain with wurst, so I'm not sure what you're asking.
 
Last edited:
Level 3
Joined
Mar 3, 2018
Messages
15
Wurst seems awesome, I'm really enjoying using it and I'm starting a map based on it.
However, I wonder: being a language (or whatever is the appropriate classification for Wurst) not directly coming from blizzard, is there a chance that my project will become unusable or incompatible with future Wc3 patches?
 
Level 23
Joined
Jan 1, 2009
Messages
1,608
Wurst seems awesome, I'm really enjoying using it and I'm starting a map based on it.
However, I wonder: being a language (or whatever is the appropriate classification for Wurst) not directly coming from blizzard, is there a chance that my project will become unusable or incompatible with future Wc3 patches?

Thanks. And I don't think your project will be come unusable. Rather it will stay usable even if the backend changes (e.g. lua) without you having to change your code, since wurst can simply output something else.
IIRC Regarding map compatibility, blizzard has stated that most "old maps" that don't do anything crazy will continue working.
Wurst only outputs maps that could also be replicated with the normal editor, and therefore not be distinguished by the game unless by malicious intention.
 
Level 26
Joined
Jun 5, 2008
Messages
1,767
What editor do you guys use to save your map then? JNGP doesn't work anymore as far as I know and whenever I tried to save old maps with vjass code on them using the new default map editor, it shattered everything but the GUI code. I'm not sure how hard it would be to tweak my code into wurst though.

If wurst would be able to save my map code, I'd embrace it with open arms. That would mean that I wouldn't have to start over from scratch and I'd be pleased as punch for such a result.
 
Level 23
Joined
Jan 1, 2009
Messages
1,608
What editor do you guys use to save your map then? JNGP doesn't work anymore as far as I know and

For terrain and minor other stuff we use the vanilla world editor. JNGP resp. our derivative Wurstpack can still work, but you need the old wc3 files.

whenever I tried to save old maps with vjass code on them using the new default map editor, it shattered everything but the GUI code. I'm not sure how hard it would be to tweak my code into wurst though.

I haven't used the recent world editor's jasshelper - in theory it should work I suppose. You just need to get the output jass from jasshelper and feed it into wurst. For a workflow see Compiling vJass and Wurst using VSCode . Also WurstScript • Legacy Map Guide
Most vjass code can be easily converted to Jurst.

If wurst would be able to save my map code, I'd embrace it with open arms. That would mean that I wouldn't have to start over from scratch and I'd be pleased as punch for such a result.

It should work, but of course there are some drawbacks.
 

~El

Level 17
Joined
Jun 13, 2016
Messages
551
I was just thinking whether the amount of function calls would be basically doubled, considering how comparatively slow function calls are in Jass. Good to know though!

Wurst's inliner is relatively aggressive, and coupled with the optimizer, is extremely efficient at both inlining and performing lots of cool optimizations. Emitted JASS code is usually on par with what you'd have written by hand, if not better.

One particular neat feature I love about it, is that it can often detect a constant argument in a function call, and upon inlining the function, eliminate dead code that would never be called with that (known) argument.

For example, this:
Code:
package Hello

function test(int a, string b)
  if a == 0
    print("0: " + b)
  else if a == 1
    print("1: " + b)
  else
    print(a.toString() + ": " + b)

init
  let number = GetRandomInt(0, 10)

  test(0, "zero")
  test(1, "one")
  test(2, "two")
  test(number, "random number")

Will compile into this:
JASS:
function init_Hello takes nothing returns boolean
    local integer number = GetRandomInt(0, 10)
    call DisplayTimedTextToPlayer(Player_localPlayer, 0., 0., 45., "0: zero")
    call DisplayTimedTextToPlayer(Player_localPlayer, 0., 0., 45., "1: one")
    call DisplayTimedTextToPlayer(Player_localPlayer, 0., 0., 45., I2S(2) + ": " + "two")
    if number == 0 then
        call DisplayTimedTextToPlayer(Player_localPlayer, 0., 0., 45., "0: random number")
    elseif number == 1 then
        call DisplayTimedTextToPlayer(Player_localPlayer, 0., 0., 45., "1: random number")
    else
        call DisplayTimedTextToPlayer(Player_localPlayer, 0., 0., 45., I2S(number) + ": " + "random number")
    endif
    return true
endfunction
 
Man, this looks like exactly what i always wanted. I've generally been really impressed by how clean scriping becomes with Wurst, and the workflow of using VSCode is also a good way of getting around the shitty built-in text editor of Wc3. With all my current maps, i'm stuck using version 1.28 with JNGP on a separate laptop, which is.... less than ideal.

@Frotty, very few Jass-users use BJs if they can help it. Sure, for maybe 80% of the cases, the overhead of wrapping a function call has no effect on performance whatsoever, and i am all for readability over overzealous optimization. However, for things like physics simulations or other heavy systems which run at 30Hz, the accumulated overhead of having all funcitons called essentially twice can make a big difference, and i've also noticed that nested function calls inside loops can have a really weird impact on performance. I love the tuple functionality for this reason, i've previously been using struct-based Vector and Quaternion libraries in Jass, but they get much worse performance than what you can get with tuples.

I am guessing that Wurst also nulls local variables for you?
 

~El

Level 17
Joined
Jun 13, 2016
Messages
551
Man, this looks like exactly what i always wanted. I've generally been really impressed by how clean scriping becomes with Wurst, and the workflow of using VSCode is also a good way of getting around the shitty built-in text editor of Wc3. With all my current maps, i'm stuck using version 1.28 with JNGP on a separate laptop, which is.... less than ideal.

@Frotty, very few Jass-users use BJs if they can help it. Sure, for maybe 80% of the cases, the overhead of wrapping a function call has no effect on performance whatsoever, and i am all for readability over overzealous optimization. However, for things like physics simulations or other heavy systems which run at 30Hz, the accumulated overhead of having all funcitons called essentially twice can make a big difference, and i've also noticed that nested function calls inside loops can have a really weird impact on performance. I love the tuple functionality for this reason, i've previously been using struct-based Vector and Quaternion libraries in Jass, but they get much worse performance than what you can get with tuples.

I am guessing that Wurst also nulls local variables for you?

It does perform auto-nulling, yes.
 
Level 23
Joined
Jan 1, 2009
Messages
1,608
Man, this looks like exactly what i always wanted. I've generally been really impressed by how clean scriping becomes with Wurst, and the workflow of using VSCode is also a good way of getting around the shitty built-in text editor of Wc3

Thanks. I hope you will be able to use it.

However, for things like physics simulations or other heavy systems which run at 30Hz, the accumulated overhead of having all funcitons called essentially twice can make a big difference

"big difference" might be a bit overstated, since there are often other things you could optimize instead, but sure, it is a measurable improvement.
Optimizations are great, but should be, for the most part, handled by the compiler and no the user.

I am guessing that Wurst also nulls local variables for you?

Of course :)
 
Level 11
Joined
Mar 6, 2008
Messages
898
Sorry if this has already been asked but: What happens with Maps using WurstScript when a new WarCraft III version is released?
Can the map still be compiled for new WarCraft III versions without requiring an update to WurstScript and associated tools?
Would be pretty painful if the world stops as soon as there is a new WarCraft III patch and modders can no longer test their maps on B.Net due to incompatibilities.
 

~El

Level 17
Joined
Jun 13, 2016
Messages
551
Sorry if this has already been asked but: What happens with Maps using WurstScript when a new WarCraft III version is released?
Can the map still be compiled for new WarCraft III versions without requiring an update to WurstScript and associated tools?
Would be pretty painful if the world stops as soon as there is a new WarCraft III patch and modders can no longer test their maps on B.Net due to incompatibilities.

Wurst does not depend at all on the current WC3 version, except for common.j and blizzard.j files.

Maps compiled with Wurst should be forward-compatible with future patches, unless there is something that Blizzard breaks (which happens rather frequently, these days).

There is usually no update to Wurst required, with one exception - if either Blizzard.j or common.j changes. Even then, the map should still compile and work with the old versions of these files, you will just be unable to use new functionality.
 
Level 23
Joined
Jan 1, 2009
Messages
1,608
Yeah, as @Sir Moriarty said. There isn't really any particular difference between a map generated by wurst and a map made using world editor and GUI.

Some wurst maps did break e.g. when blizzard screwed up event-ids, but so did any other map relying on that data.

Things that do get broken by patches are e.g. the runmap command, if blizzard changes the way how wc3 and maps are run again.

Stuff not related to the map that can break is e.g. running warcraft from VSCode, if blizzard changes how warcraft is run *again*.
But usually we are quite quick to catch up.

Definitely the way to mod in today's WarCraft III scene!

:thumbs_up:
 
Level 11
Joined
Mar 6, 2008
Messages
898
How does WurstScript behave towards variables defined in the associated map that is also used for terrain?
Especially for rects (udg_X variables for every rect) it is really convenient to create them there and access them as their "udg_" name or make another variable assign to that in the map's script during init.

tldr; is it possible to interact with GUI variables? (especially locations, rects, etc.)
 

~El

Level 17
Joined
Jun 13, 2016
Messages
551
How does WurstScript behave towards variables defined in the associated map that is also used for terrain?
Especially for rects (udg_X variables for every rect) it is really convenient to create them there and access them as their "udg_" name or make another variable assign to that in the map's script during init.

tldr; is it possible to interact with GUI variables? (especially locations, rects, etc.)

I haven't used this functionality myself, but;

When building/running a map, Wurst will copy the war3map.j file from the map and automatically add it to your project. This is done every time you run/build a map. Consequently, any code/variables defined in war3map.j will be accessible to you in Wurst.
 
@karaulov Try Zinc, it is supported by JassHelper which is now an official part of the editor. It uses C-like syntax.

Adding "C/C++ support" is not possible per se though, everything we write has to be converted to jass code, and the best we can do is write a compiler which parses an arbitrary syntax to jass.
 
Level 23
Joined
Jan 1, 2009
Messages
1,608
Last edited:
Level 23
Joined
Jan 1, 2009
Messages
1,608
What's the policy on credits? Like, is there a certain specific way I should credit Wurst / credit the individual contributors? (Asking cause I'm not sure if made with Wurst would be enough. :p )

We generally don't mind, but of course any mention is greatly appreciated to help the project :)
If you want you can use the banner from my signature.
 
Level 7
Joined
Oct 3, 2008
Messages
183
Hmm, maps made with Wurst don't have standard JASS code in them when looked at them in the standard World Editor though do they? The reason I ask is cause I like people being able to look at my map and (maybe) learn from it.
 
Level 23
Joined
Jan 1, 2009
Messages
1,608
Hmm, maps made with Wurst don't have standard JASS code in them when looked at them in the standard World Editor though do they? The reason I ask is cause I like people being able to look at my map and (maybe) learn from it.

Wurst writes the generated JASS into the war3map.j. The trigger editor data is not touched.
If you want to publish your code, you should make a git repo with your wurst project, which is encouraged.
I personally don't, but many people optimize their maps, getting rid of the trigger editor data anyway.
 
Level 11
Joined
Mar 6, 2008
Messages
898
WurstScript is so simple, I've managed to learn it by reading through the manual in a single afternoon.
Also its syntax is very similar to that of Python (telling that as someone who dislikes Python) which is used a lot these days.
So learning WurstScript syntax is actually at least better than learning the super strange syntax from JASS or vJASS, not to mention the abomination that Zinc is.

Ah and btw. you can learn WurstScript really fast due to the near instant feedback of the IDE experience. It is simply put awesome!
 
Level 11
Joined
Mar 6, 2008
Messages
898
Just tried to test my WurstScript with other players.
Unfortunately WarCraft III is not able to read the map data ingame.
This only happens after I run MapOptimizer on it.
Do you know what could be incompatible with WurstScript and MapOptimizier.
Btw.: It even happened with completely unoptimized maps (on WurstScript side).
 
Level 23
Joined
Jan 1, 2009
Messages
1,608
Do you know what could be incompatible with WurstScript and MapOptimizier.

No, and I doubt there is any since wurst just outputs regular Jass and a regular Map.
Perhaps you forgot to link updated common.j with the optimizer.

The solution is simple anyway - don't run MapOptimizer. Wursts own code optimizations are far superior and the optimizer actually makes your code worse in most cases.
Removing WE data etc. to protect is pointless but should be unrelated and thus work.
 
Level 11
Joined
Mar 6, 2008
Messages
898
> The solution is simple anyway - don't run MapOptimizer. Wursts own code optimizations are far superior and the optimizer actually makes your code worse in most cases.

Ah okay I thought a combination of both could not hurt.
Good to know!
I will try that asap.
 
Level 11
Joined
Mar 6, 2008
Messages
898
Hey, I tried MapOptimizer without script optimizations.
It still reduces the map size by roughly 30% and the map is playable again - thanks!

I have another question ...
The other day I was trying to create some units using the UnitObjEditing module et. al. however, even though compiletime function was running and even created some legit output in the build folder, I couldn't do anything with those created unit types, e.g. I wasn't able to create them via createUnit.
Can you tell me what I am possibly doing wrong here?

Edit:
Third Question: Is it somehow possible to just edit some already existing units at compiletime? I basically just want to generate their tooltips depending on some encoded values since keeping those in sync manually is really painful. But besides that I like having them in object editor for all other stats, especially the graphical parts.
 
Last edited:
Status
Not open for further replies.
Top