• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

[C#] Mapmaking in csharp

Level 18
Joined
Jan 1, 2018
Messages
728
With the introduction of lua in patch 1.31, it is now possible to create maps in C# using the CSharpLua transpiler.

Templates:

Tutorials:

Packages:
 
Last edited:
Wicked, though would of course be better if WarCraft 3 supported this language script rather than depending on the Lua framework (very doubtful) if not just for efficiency's sake.

But yeah JASS and vJass are heavily crippled in comparison. Would be cool if GUI got a neutral-variable type as well, but we'll be getting Reforged soon which is going to change things up for GUI so substantially that it'll feel like upgrading to a Ferrari.
 
Level 18
Joined
Jan 1, 2018
Messages
728
Wicked, though would of course be better if WarCraft 3 supported this language script rather than depending on the Lua framework (very doubtful) if not just for efficiency's sake.
I agree it's extremely unlikely that C# would get official modding support in Warcraft 3. The security vulnerabilities this would bring alone is reason enough.
Of course, the code transpiled to lua will be less efficient than writing directly in lua, but for me personally, it's a trade-off between efficient code, and increased productivity by working with a programming language and tools like visual studio with which i have years of experience, and I prefer the latter.

Oh goody... Yet another language that someone like myself will have to deal with to solve some people's trigger errors.
Let me know if I'm missing your point, but honestly, I don't see what the problem is. If someone is requesting help for a problem with a specific programming language with which you're not familiar, you can simply let other members try to provide help. In fact, this would be more of an issue if people request help with lua, because C# is roughly 20 times more popular (source). (not trying to start a fight about which programming language is better by the way)
 

Deleted member 219079

D

Deleted member 219079

we'll be getting Reforged soon which is going to change things up for GUI so substantially that it'll feel like upgrading to a Ferrari
What's going to happen to GUI?
 
Level 18
Joined
Jan 1, 2018
Messages
728
Update:
  • Removed the .zip file from first post, the .cs files can now be found here.
  • Simplified namespaces by merging jass and lua ('FourCC', known as 'BlzS2FourCC' in jass) natives into a single class 'War3Api.Common'.
  • Replaced ApiPrefix option from compiler with 'NativeLuaMemberAttribute'.
  • Merged latest commits from yanghuan.
 
Last edited:
Level 18
Joined
Jan 1, 2018
Messages
728
Update:
  • Implemented parser & serializer for war3map.w3i file:
    • This file is now used to generate the main and config functions.
    • You can also customize its properties, like ScriptLanguage, MapName, and Player and Force settings. You no longer need to do this in the World Editor.
  • Implemented localization for imported files:
    • To use, create a folder with one of the locale strings (found here) in your AssetsDirectoryPath folder.
    • Localization for map script coming soon™.
  • Updated example C# map project:
    • Now supports the above features (obviously).
    • Updated example map code to showcase attaching data ('this' object) to a timer, thereby deprecating hashtables. This works for triggers as well.
I wish for an exe though
Also coming soon™.
 
Level 18
Joined
Jan 1, 2018
Messages
728
Update:
  • Moved the Warcraft III C# API to a new repository: War3Api
    • This repo also includes a project that automatically transpiles common.j (and Blizzard.j) to C#.
  • Experimental support for ProjectReferences and PackageReferences:
    • Before, the compiler would only retrieve .cs files from the same folder as your .csproj file.
    • Note for project references: these are still treated as folders, so it's not a good idea to have a .csproj file in the same folder as, or in a nested folder of, another .csproj file. That would result in the same .cs files being added multiple times.
    • Notes for package references:
      • The .cs files are expected to be in a specific location within the package. Make sure your package project is set up properly, see here for an example.
      • You should be able to include content files (for example an .mdx file) in your packages as well, and they will get automatically added to the map, but I have not tested this yet. This feature could be useful if you were to make a spell which uses a custom model.
      • In order to not import system packages, there is currently a limitation that only packages whose id start with "War3Api" or "War3Lib" will be imported.
  • Updated example C# map project:
    • The map now uses an additional ProjectReference, which uses a PackageReference, showing how .cs files can now be imported from other places than only the directory of the main project.
These features currently involve some hacky workarounds, but since I'm too lazy to work on a dev branch, the changes are already out there anyways, so I'm just keeping you updated. No hate plz.
 
Last edited:
Level 4
Joined
Jul 30, 2014
Messages
18
How do you handle object disposal? I have created a rather simple indexing system, which indexes units and attaches a class to them, they even deallocated, but tests confirm memory leak, although everything attached to unit is destroyed. I suspect classes themselves are not being destroyed.
Performance Tests (same indexing/deindexing logic).
Before spawn 8k units executed memory (10 runs): ~370MB
After 8k units were spawned and recycled (10 runs): ~500MB
Before spawn 8k units executed memory (4 runs): ~300MB (but the codebase is a bit smaller)
After 8k units were spawned and recycled (4 runs): ~800MB
Example,
Code:
class UnitEntity{
static Dictionary<unit, UnitEntity> Dictionary;
unit self;
trigger sometrig;

public static void UnitIndexed(unit indexed){
Dictionary[indexed] = new UnitEntity();
}

public void OnDestroy(){
DestroyTrigger(this.someTrig);
Dictionary.Remove(this.self);
this.someTrig = null;
this.self = null;
}
}
In vJass struct that would have been attached is just destroyed after OnDestroy. (same algorithm but in vjass doesn't leak as much)
Here, in C#, however, it leaks. IDisposal interface doesn't produce any results.
 
Level 18
Joined
Jan 1, 2018
Messages
728
How do you handle object disposal? ...
I'll be honest with you, I don't really know either. The transpiler and lua system libraries aren't made by me and I haven't really looked at them all that much other than making some small changes here and there so they work properly in warcraft III.
Anyways, you could try forcing the garbage collector to run and see if that helps. You can do this by putting the following code in your map:
C#:
[NativeLuaMemberContainer]
internal static class LuaMethods
{
    [NativeLuaMember("collectgarbage")]
    public static extern void RunGC();
}
PS. You can enable C# highlighting with [Code=CSharp]
 
Level 7
Joined
Dec 28, 2014
Messages
83
I really like this since I'm a C# programmer and like to make stuff in Warcraft III. I can follow the instructions and set this up by myself just fine.

It would be nice if you could set this up faster. You could reduce the complexity of the setup by creating a C# program that does it automatically or maybe there are other ways.
 
Level 4
Joined
Jul 30, 2014
Messages
18
I'll be honest with you, I don't really know either. The transpiler and lua system libraries aren't made by me and I haven't really looked at them all that much other than making some small changes here and there so they work properly in warcraft III.
Anyways, you could try forcing the garbage collector to run and see if that helps. You can do this by putting the following code in your map:
C#:
[NativeLuaMemberContainer]
internal static class LuaMethods
{
    [NativeLuaMember("collectgarbage")]
    public static extern void RunGC();
}
PS. You can enable C# highlighting with [Code=CSharp]
No luck, but garbagecollection seems to be really working tho. Possibly coding is bad ;(
Surprisingly, with garbage collector in place, I was able to make performance tests - spawn units very fast(0.01) and kill them instantly, after 5 hours of running Warcraft 3 running perfectly fine, but I was 7.8GB in memory size. The game was smooth and perfectly fine, everything was functioning just fine, no lag, stable hardcapped 120 fps, systems like damage parsing, regeneration handle were running just fine. What could be the problem? Ideas?
The whole code from there would be as follows Azureus0/NoxRaven
Indexer code is in UnitEntity. As I was writing this I had a test with code which did not use any delegates in indexing code. It seems to leak less.
In the end, I'd like to say that if C# compiler to war3lua wasn't so buggy, hands down 20/10 would use it no-brainer. Best platform. Because it supports all the magic of the modern high-level language, like polymorphism, overrides and even damn reflection! REFLECTION CARL! Tested myself, Activator.CreateInstance(Type, arguments) returns new Type(args)! There is literally nothing impossible with C# compiling to lua if it worked correctly tho.:(
But currently it has 'magical' problems which make no sense. For example,
C# generated code executes this command in a weird way. This piece of code stops unit animation (not reset), but supposed to, well, "attack".
Lua:
SetUnitAnimation(War3MapTimeAbyssSource.GlobalVars.shop_charpower, "attack")
This natively generated code does what it is told.
Lua:
SetUnitAnimation(gg_unit_n001_0024, "attack")
Don't point out code order execution. This piece comes right after previous statement and it works.
Lua:
SetUnitAnimation(War3MapTimeAbyssSource.GlobalVars.shop_charpower, "Attack")
AddUnitAnimationProperties(War3MapTimeAbyssSource.GlobalVars.Castle, "work", true)
AddUnitAnimationProperties(War3MapTimeAbyssSource.GlobalVars.gg_unit_hbla_0033, "work", true)
AddUnitAnimationProperties(War3MapTimeAbyssSource.GlobalVars.gg_unit_hlum_0038, "work", true)

I really like this since I'm a C# programmer and like to make stuff in Warcraft III. I can follow the instructions and set this up by myself just fine.

It would be nice if you could set this up faster. You could reduce the complexity of the setup by creating a C# program that does it automatically or maybe there are other ways.
If you are C# dev you should know best, that ideal project setup looks like blank project without a single reference and you go figure what you need for thing to run (true story btw).
I think the best way he can make it better is to trash the whole repo with the example project and create a new one with all required submodules and infrastructure in place, so that all you'd need to do to get started is clone repo recursively and setup string provider. done.
 
Last edited:
Level 18
Joined
Jan 1, 2018
Messages
728
I get 'Microsoft.NET.Sdk' not found error on running the project. Have the API and the CSharpLua as well. Three files sharing same root folder.

/root folder/(insert each folder for the requirement here)
Last night I created NuGet packages for CSharp.lua and War3Net, so you no longer need to clone those two repositories to get things running.
Instead, you can now add PackageReferences to War3Net.CSharpLua and War3Net.Build in the launcher project.

Regarding the 'Microsoft.NET.Sdk' error, you can try verifying that the folder "C:\Program Files\dotnet\sdk\[version]\Sdks\Microsoft.NET.Sdk" exists. The version folder should be 3.0.100, assuming your project targets netcoreapp3.0.
If it exists, you probably have an issue with the 'MSBuildSDKsPath' environment variable. I think I had this same issue in the past, but can't find the code to fix it right now. I think it was something like:
C#:
System.Environment.SetEnvironmentVariable("MSBuildSDKsPath", null)
By setting it to null it should automatically be restored to the proper value when MSBuild runs.

I really like this since I'm a C# programmer and like to make stuff in Warcraft III. I can follow the instructions and set this up by myself just fine.

It would be nice if you could set this up faster. You could reduce the complexity of the setup by creating a C# program that does it automatically or maybe there are other ways.
If you are C# dev you should know best, that ideal project setup looks like blank project without a single reference and you go figure what you need for thing to run (true story btw).
I think the best way he can make it better is to trash the whole repo with the example project and create a new one with all required submodules and infrastructure in place, so that all you'd need to do to get started is clone repo recursively and setup string provider. done.
As stated above, cloning War3Net and CSharp.lua is no longer required, so that should help alot in speeding up the setup process.
I will probably make a project template as well, which will include the launcher and an empty source project.

No luck, but garbagecollection seems to be really working tho. Possibly coding is bad ;(
Surprisingly, with garbage collector in place, I was able to make performance tests - spawn units very fast(0.01) and kill them instantly, after 5 hours of running Warcraft 3 running perfectly fine, but I was 7.8GB in memory size. The game was smooth and perfectly fine, everything was functioning just fine, no lag, stable hardcapped 120 fps, systems like damage parsing, regeneration handle were running just fine. What could be the problem? Ideas?
Units will always leak. I think the question here is how much % of the leak is caused by just units, and how much by the C# -> generated lua code. For this you'd have to set up the same experiment in lua.
Assuming the C# code does leak more, feel free to investigate in the coresystem library: Core Dictionary
Like I said before, part of the reason I started this project is because I didn't want to learn lua, so you'll have to excuse my ignorance.

Because it supports all the magic of the modern high-level language, like polymorphism, overrides and even damn reflection! REFLECTION CARL!
It's really great yeah, just a quick warning about reflection though, you might want to read the FAQ.
 
Last edited:
Level 4
Joined
Jul 30, 2014
Messages
18
I found a temporary solution to the garbage collection. You need to include extra attribute like NativeLuaCall(string inlineScript) or something, which tranforms into pure Lua code directly.
Solution to the current problem with exact same setup reduces leak by about 90% or more. Setting class that needs to be removed to nil, like so
Lua:
this = nil
Makes it stop leak as much.
Tests.
C#:
TimerStart(CreateTimer(), 0.01f, true () => {unit u = CreateUnit(players[0].PlayerRef, FourCC("hfoo"), 4800, 3800, 0); KillUnit(u); u = null;})
Tests show 270MB initial memory go to 300MB after 10 minutes running with nulled this.
Initial result of same test 270MB to 350MB in same 10 minutes (without modifications).
Ran once tho!

P.S. Corrected bad formatting in the previous message to make it more clear. The problem appears to be with weird animation setting for units. Strangely enough same code in Lua and CSharp produce different results, which is weird because they are pretty much the same string (after C# is compiled) when you read it from compiled file that is next to w3x map in build folder. Two codeblocks I attached in message abouve from that file, one from C# compiled version, the other from the original autogenerated from triggers.
 
Level 18
Joined
Jan 1, 2018
Messages
728
Update:
  • Fix bug in MPQ library that prevented a file to be both compressed and encrypted.
  • Added Default properties to the MapInfo (war3map.w3i) and MapEnvironment (war3map.w3e) classes.
    • This allows you to quickly get started with a new map without first generating these files with the World Editor.
  • Created new package for War3Net.CSharpLua.CoreSystem, which contains the C# standard library .lua files.
    • Note that these files are no longer automatically added. This allows you to have more control over which libraries get added to your map script.
    • You can use the package's CoreSystemProvider class to load all the standard library files in the correct order.
  • Many other changes, some of which breaking the public API.
    • For example, the MapInfo class was moved from War3Net.Build to War3Net.Build.Info namespace.
With the updated packages, your launcher .csproj should now reference war3net.csharplua.coresystem-1.0.2 and war3net.build-1.0.0-preview1.
 
Level 2
Joined
Dec 6, 2018
Messages
10
Hey, tried to get a test map to work, but
Code:
if (mapBuilder.Build(scriptCompilerOptions, stringProvider.AssetsDirectoryPath, stringProvider.BaseMapFilePath))
throws an System.InvalidOperationException: "Sequence contains no elements" everytime at compiling. Can someone give me an advise what to do ? thanks :)
 
Level 4
Joined
Jul 30, 2014
Messages
18
Hey, tried to get a test map to work, but
Code:
if (mapBuilder.Build(scriptCompilerOptions, stringProvider.AssetsDirectoryPath, stringProvider.BaseMapFilePath))
throws an System.InvalidOperationException: "Sequence contains no elements" everytime at compiling. Can someone give me an advise what to do ? thanks :)
You need to fill StringProvider class with your strings, ideally, in the end you would have something like this
C#:
internal sealed class TimeAbyssMapStrings : StringProvider
    {
        public string Version = "1.0";
        public override string MapAuthor => @"IBO";

        public override string MapName => @"Time Abyss "+Version;

        // Description when picking map in map menu
        public override string MapDescription => @"A survival warcraft 3 mep. Kil smesh.";

        /// <summary>
        /// Path to the input .w3x file or folder.
        /// This base map is expected to at least contain a war3map.w3i and a war3map.w3e file.
        /// However, you can update <see cref="Program"/> to create the war3map.w3i file from scratch.
        /// </summary>
        public override string BaseMapFilePath => "C:\\Users\\Azureus\\Documents\\.git\\DOTNET\\TimeAbyssWC3\\TimeAbyssWC3Live.w3x";

        /// <summary>
        /// Path to a directory containing additional files to be imported.
        /// Meant to replace World Editor's import manager.
        /// This property is optional, and can be set to null.
        /// </summary>
        public override string AssetsDirectoryPath => null;

        /// <summary>
        /// Directory in which the build files will be created, including the new .w3x file.
        /// </summary>
        public override string OutputDirectoryPath => "C:\\Users\\Azureus\\Documents\\.git\\DOTNET\\TimeAbyssWC3\\TimeAbyssBuild";

        /// <summary>
        /// Path to Warcraft III.exe.
        /// </summary>
        public override string Warcraft3ExecutablePath => "F:\\gameshared\\Warcraft III\\x86_64\\Warcraft III.exe";
    }
 
Level 2
Joined
Dec 6, 2018
Messages
10
thanks for your reply :)
i had done everything like that before. MapInfo, CompilerOptions are set too. Following I will post the content of the relevant objects during runtime debugging, so maybe you or someone else can tell me where i did a mistake.

 
Level 18
Joined
Jan 1, 2018
Messages
728
thanks for your reply :)
i had done everything like that before. MapInfo, CompilerOptions are set too. Following I will post the content of the relevant objects during runtime debugging, so maybe you or someone else can tell me where i did a mistake.

It would be more helpful for debugging if you posted the call stack instead. In order to view the entire call stack, including from external code, you must load the symbols for War3Net, which you can do by going to the options in visual studio, then in the debug tab, disable 'just my code'.
 
Level 18
Joined
Jan 1, 2018
Messages
728
Seems to be something with Linq. Maybe in the Build-function is used first() instead of firstOrDefault(). Anyway, here is the call stack:

It seems that you're triggering an edge case where my program is unable to find a suitable framework version for a certain package. The exact version requested isn't found, and when it tries to find a replacement, it can't find any either.
Can you find out for me what the values are of the method arguments 'string path' and 'string frameworkFolderName'? And then look in file explorer at that path and tell me which framework folders you see there?
 
Level 4
Joined
Jul 30, 2014
Messages
18
Hey, tried to get a test map to work, but
Code:
if (mapBuilder.Build(scriptCompilerOptions, stringProvider.AssetsDirectoryPath, stringProvider.BaseMapFilePath))
throws an System.InvalidOperationException: "Sequence contains no elements" everytime at compiling. Can someone give me an advise what to do ? thanks :)
Set strings in StringProvider file
Example from mine
StringProvider.cs
C#:
namespace War3Map.TimeAbyss.Launcher
{
    internal sealed class TimeAbyssMapStrings : StringProvider
    {
        public string Version = "1.0";
        public override string MapAuthor => @"IBO";

        public override string MapName => @"Time Abyss "+Version;

        public override string MapDescription => @"A survival warcraft 3 mep. Kil smesh.";

        /// <summary>
        /// Path to the input .w3x file or folder.
        /// This base map is expected to at least contain a war3map.w3i and a war3map.w3e file.
        /// However, you can update <see cref="Program"/> to create the war3map.w3i file from scratch.
        /// </summary>
        public override string BaseMapFilePath => "C:\\Users\\Azureus\\Documents\\.git\\DOTNET\\TimeAbyssWC3\\TimeAbyssWC3Live.w3x";

        /// <summary>
        /// Path to a directory containing additional files to be imported.
        /// Meant to replace World Editor's import manager.
        /// This property is optional, and can be set to null.
        /// </summary>
        public override string AssetsDirectoryPath => null;

        /// <summary>
        /// Directory in which the build files will be created, including the new .w3x file.
        /// </summary>
        public override string OutputDirectoryPath => "C:\\Users\\Azureus\\Documents\\.git\\DOTNET\\TimeAbyssWC3\\TimeAbyssBuild";

        /// <summary>
        /// Path to Warcraft III.exe.
        /// </summary>
        public override string Warcraft3ExecutablePath => "F:\\gameshared\\Warcraft III\\x86_64\\Warcraft III.exe";
    }
}
 
Level 2
Joined
Dec 6, 2018
Messages
10
It seems that you're triggering an edge case where my program is unable to find a suitable framework version for a certain package. The exact version requested isn't found, and when it tries to find a replacement, it can't find any either.
Can you find out for me what the values are of the method arguments 'string path' and 'string frameworkFolderName'? And then look in file explorer at that path and tell me which framework folders you see there?

string path: "C:\\Users\\Dennis\\.nuget\\packages\\System.Collections\\4.3.0\\lib", containing folders:

ada5603af6.png

string frameworkFolderName: null
 
Level 18
Joined
Jan 1, 2018
Messages
728
string path: "C:\\Users\\Dennis\\.nuget\\packages\\System.Collections\\4.3.0\\lib", containing folders:

ada5603af6.png

string frameworkFolderName: null
The issue here is obviously that frameworkFolderName is null. I created a small fix that hopefully prevents this from happening.
You should automatically get this fix without updating War3Net.Build, because it targets version 1.3.* of War3Net.CSharpLua, which I updated from 1.3.0 to 1.3.0.1, and it will target the higher version.

If the issue remains, first check that you have the new version in "C:\Users\Dennis\.nuget\packages\war3net.csharplua\1.3.0.1".
If you do, check the value of 'string frameworkFolderName' again. If it is still null, then unfortunately my fix did not work.
 
Level 2
Joined
Dec 6, 2018
Messages
10
The issue here is obviously that frameworkFolderName is null. I created a small fix that hopefully prevents this from happening.
You should automatically get this fix without updating War3Net.Build, because it targets version 1.3.* of War3Net.CSharpLua, which I updated from 1.3.0 to 1.3.0.1, and it will target the higher version.

If the issue remains, first check that you have the new version in "C:\Users\Dennis\.nuget\packages\war3net.csharplua\1.3.0.1".
If you do, check the value of 'string frameworkFolderName' again. If it is still null, then unfortunately my fix did not work.

unfortunately this version doesn't exist for me. Can you tell me a different way how i can get it?
 
Level 18
Joined
Jan 1, 2018
Messages
728
unfortunately this version doesn't exist for me. Can you tell me a different way how i can get it?
You're right, I tried with my own project and it doesn't update automatically as I hoped it would.
The solution is to explicitly require this new version in your .csproj file:
Code:
<ItemGroup>
  <PackageReference Include="War3Net.Build" Version="1.0.0-preview1" />
  <PackageReference Include="War3Net.CSharpLua" Version="1.3.0.1" />
  <PackageReference Include="War3Net.CSharpLua.CoreSystem" Version="1.0.2" />
</ItemGroup>
 
Level 2
Joined
Dec 6, 2018
Messages
10
You're right, I tried with my own project and it doesn't update automatically as I hoped it would.
The solution is to explicitly require this new version in your .csproj file:
Code:
<ItemGroup>
  <PackageReference Include="War3Net.Build" Version="1.0.0-preview1" />
  <PackageReference Include="War3Net.CSharpLua" Version="1.3.0.1" />
  <PackageReference Include="War3Net.CSharpLua.CoreSystem" Version="1.0.2" />
</ItemGroup>

Thank you, that works :)

But unfortunately it seems the fix didn't work, still the same exception with same values for 'path' and 'frameworkPath'.
 
Level 18
Joined
Jan 1, 2018
Messages
728
Thank you, that works :)

But unfortunately it seems the fix didn't work, still the same exception with same values for 'path' and 'frameworkPath'.
I created two new packages, 1.3.0.2-allownull and 1.3.0.2-disallownul. Please try them both.
The former should allow you to run the program without errors, so let me know if it works for you.
The latter is for debugging the cause that frameworkFolderPath is still null for you. It would be helpful if you posted on what line it throws the exception for you (should be either 78 or 154 if I'm not mistaken).
I'd also like to know what framework you're targeting. Can you post the <TargetFramework> property of your source (not the launcher) project?
 
Level 2
Joined
Dec 6, 2018
Messages
10
I created two new packages, 1.3.0.2-allownull and 1.3.0.2-disallownul. Please try them both.
The former should allow you to run the program without errors, so let me know if it works for you.
The latter is for debugging the cause that frameworkFolderPath is still null for you. It would be helpful if you posted on what line it throws the exception for you (should be either 78 or 154 if I'm not mistaken).
I'd also like to know what framework you're targeting. Can you post the <TargetFramework> property of your source (not the launcher) project?


1.3.0.2-allownull : works, but no player positions, mines, creeps etc. are set
1.3.0.2-disallownul : works for some reason too, and with the same issues as at"allownull".

should i try rollback to 1.3.0.1 for debugging purposes?
 
Level 18
Joined
Jan 1, 2018
Messages
728
1.3.0.2-allownull : works, but no player positions, mines, creeps etc. are set
1.3.0.2-disallownul : works for some reason too, and with the same issues as at"allownull".

should i try rollback to 1.3.0.1 for debugging purposes?
This is expected behaviour, because currently parsing of the war3map.doo and war3mapUnits.doo files is not yet implemented. I will work on this asap.

Thank you, that works :)

But unfortunately it seems the fix didn't work, still the same exception with same values for 'path' and 'frameworkPath'.
I just realized you mentioned 'frameworkPath', but I was actually interested in the value of 'frameworkFolderName'. Can you check again (with version 1.3.0.1)?

EDIT: I just updated War3Net.Build to 1.0.0-preview2, which adds parsing of the war3mapUnits.doo file. It's not fully implemented yet, so right now it will only generate 'CreateUnit' and 'SetResourceAmount' (for gold mines) invocations.
I have not tested it yet, so I may have made some errors. If your map won't load, post the 'main.lua' file from your output directory.
In order to pass the war3mapUnits.doo file to the compiler, you must add it in a similar way as the war3map.w3i file:
C#:
var mapUnits = MapUnits.Parse(FileProvider.GetFile(Path.Combine(stringProvider.BaseMapFilePath, MapUnits.FileName)));
// ...
scriptCompilerOptions.MapUnits = mapUnits;
 
Last edited:
Level 2
Joined
Dec 6, 2018
Messages
10
This is expected behaviour, because currently parsing of the war3map.doo and war3mapUnits.doo files is not yet implemented. I will work on this asap.


I just realized you mentioned 'frameworkPath', but I was actually interested in the value of 'frameworkFolderName'. Can you check again (with version 1.3.0.1)?

EDIT: I just updated War3Net.Build to 1.0.0-preview2, which adds parsing of the war3mapUnits.doo file. It's not fully implemented yet, so right now it will only generate 'CreateUnit' and 'SetResourceAmount' (for gold mines) invocations.
I have not tested it yet, so I may have made some errors. If your map won't load, post the 'main.lua' file from your output directory.
In order to pass the war3mapUnits.doo file to the compiler, you must add it in a similar way as the war3map.w3i file:
C#:
var mapUnits = MapUnits.Parse(FileProvider.GetFile(Path.Combine(stringProvider.BaseMapFilePath, MapUnits.FileName)));
// ...
scriptCompilerOptions.MapUnits = mapUnits;

frameworkFolderName: "netstandard1.0"

map loads fine :)
 
Level 18
Joined
Jan 1, 2018
Messages
728
frameworkFolderName: "netstandard1.0"
Thanks, it all makes sense now. The reason both versions of 1.3.0.2 work is because in addition to checking for frameworkFolderName being null, I also changed First() to FirstOrDefault().
This was needed because the target framework 'netstandard1.0' isn't compatible with any of the frameworks you posted earlier.

map loads fine :)
Thanks for testing. If you want to, you could post the natives that are used by the 'CreateAllUnits' in the main function (in your original map script), so I can give priority to implementing those.
I created a test map myself and so far I found CreateUnit, SetHeroLevel, SetHeroStr/Agi/Int, SetUnitAcquireRange, and SetResourceAmount. There are a lot more though, so I want to start with the ones that people actually use (I personally avoid using pre-placed units/items in my maps, which is why I neglected to implement any of this until yesterday).
 
Level 18
Joined
Jan 1, 2018
Messages
728
Update:
  • Updated CSharpLua package, which introduced @CSharpLua.Template.
    • Using this is now preferred over NativeLuaMemberAttribute, which still has some bugs which the new approach shouldn't have.
    • Some examples are at the bottom of this post.
  • Some minor fixes and additions in War3Net.Build package.
  • Created a new repository: War3Map.Template. This template auto-generates default .w3e and .w3i files, so the only thing you need to do to get started is set the path to your Warcraft III executable.
Example usage of new @CSharpLua.Template attribute:
C#:
/// @CSharpLua.Template = "pcall({0})"
public static extern bool PInvoke(Action f, out string errorMessage);

/// @CSharpLua.Template = "math.pi"
private static readonly float PI = 3.14f;

The latest package versions are now War3Net.Build 1.0.0-preview3 and War3Net.CSharpLua.CoreSystem 1.0.3
 

qbz

qbz

Level 4
Joined
Dec 1, 2019
Messages
80
I was able to get the example project mostly working, at least being opaquely built by your lib and launching wc3 successfully. However, it doesn't seem like the functionality in War3Map.Example.Source is actually running. I just get the empty map with fog of war still enabled and no Hello World message.
 
Level 18
Joined
Jan 1, 2018
Messages
728
I was able to get the example project mostly working, at least being opaquely built by your lib and launching wc3 successfully. However, it doesn't seem like the functionality in War3Map.Example.Source is actually running. I just get the empty map with fog of war still enabled and no Hello World message.
I haven't touched the example project in a while, so it doesn't use the latest versions of the packages. I will update it later today. In the meantime, you could try the template project, which has been updated more recently and can auto-generate war3map.w3e and war3map.w3i, so the only thing you need to do to get started is set the path to your Warcraft III executable.
 

qbz

qbz

Level 4
Joined
Dec 1, 2019
Messages
80
I put a PR up on the example to fix the packages if you want.

I was able to get the template working, with running code. Although for some weird reason I kept getting file not found on my WC3 exe. Same exact absolute path that was working in the example project. I felt like I double and triple checked, got the abs path directly from that button in explorer, tried multiple times, I have no idea. I ended up putting my warcraft 3 folder in my path so I could just pass "Warcraft III.exe" and that worked.

Hoping by the end of the beta the new editor and reforged will be able to load/play these maps. I tried having reforged be my debugger but it just gives my battle.net launcher window focus. Also tried loading the generated map from template in new editor. First it gives the warning that the map was saved by a more recent editor version, then if you proceed it tells you doodad data is missing or invalid, then if you try and poke around the map or debug or anything from the new editor, the editor crashes.
 
Last edited:
Level 18
Joined
Jan 1, 2018
Messages
728
I tried fixing the example project but for some reason kept getting an error in wc3 when trying to load the map. Since that project wasn't very different from the template project I created more recently (apart from trying out some random things like integrating a lua library (which I can't do anymore now because the map won't load)), I decided to deprecate it.

Also tried loading the generated map from template in new editor. First it gives the warning that the map was saved by a more recent editor version
Normally when you save a map with the world editor, it stores version 6072 in the .w3i file, but to indicate that a .w3x was generated with War3Net instead of the world editor, I store a different version number. This is what triggers the warning, but otherwise you can simply ignore it.

then if you proceed it tells you doodad data is missing or invalid
I'm not sure what files the world editor expects exactly, I only know that warcraft III only requires war3map.w3i, war3map.w3e, and war3map.lua (assuming the mode is set to lua in the .w3i file of course). You can try creating a new map in the world editor and saving it as folder, then copy all those files to the assets folder in your launcher project.
 

qbz

qbz

Level 4
Joined
Dec 1, 2019
Messages
80
Oh have you tested this with reforged? Is it expected to work atm? I will try again when I get home. It's possible there are problems with new editor. There were custom ability problems recently fixed with an update.
 
Level 18
Joined
Jan 1, 2018
Messages
728
Oh have you tested this with reforged? Is it expected to work atm? I will try again when I get home. It's possible there are problems with new editor. There were custom ability problems recently fixed with an update.
I don't have reforged, and I generally wouldn't recommend trying to open C# maps with the world editor, but I heard that using the world editor to test a map is currently the only way to play custom maps on reforged, so I thought I'd give some pointers.
A better solution would be figuring out how the world editor runs a map. Does it still use -loadfile? Does it run warcraft III.exe or some launcher? Since I don't have reforged, I cannot test any of this.
 

qbz

qbz

Level 4
Joined
Dec 1, 2019
Messages
80
I'll look into it this weekend. Btw, idk if you have the means/interest, but I read pre-ordering gets you higher priority beta access. I pre-ordered right after reading that and was given reforged beta access instantly after pre-ordering.
 

qbz

qbz

Level 4
Joined
Dec 1, 2019
Messages
80
so reforged needs -launch and cannot have "-graphicsapi Direct3D9", but nowfpause is fine. Something like...


private const bool IsReforged = true;
private const string Warcraft3CommandLineArgs = @"-nowfpause -graphicsapi Direct3D9";
private const string Warcraft3ReforgedCommandLineArgs = @"-nowfpause -launch";
private const string CommandLineArgs = IsReforged ? Warcraft3ReforgedCommandLineArgs : Warcraft3CommandLineArgs;

Map runs fine, displays Hello World.
 
Top