Trying out MonoAGS (AGS 5 candidate) : journal

Started by Monsieur OUXX, Wed 02/05/2018 14:56:42

Previous topic - Next topic

Monsieur OUXX

I intend on trying to develop a tiny game with monoAGS.
This will be a test run to assert by myself how mature and/or easy-to-use it is. I will post my progress here.
If I succeed, I will try to convert a medium-size AGS game into MonoAGS. again, I will post my progress here.

This sort-of blog is meant to deliver tips to anyone trying to do the same, and maybe be an incentive to start something.

If you wonder why I'm posting this on the AGS forums, then please read this thread and all the other threads about the same topic.


Edit by cat:
MonoAGS Repository
MonoAGS Documentation

EDIT 2 :
Things to add in the "get started" wiki:
Quote
- if you can't build an Android project, it means you might need to install Xamarin (read more in the posts below)
- if you can't build any of the other projects, try these :
    1) make sure you have .Net Core installed (see posts below for links and version). To do so :
       - Open the Windows Command Prompt
       - type this and press return :
         dotnet --info
       - if you get an error message: then it means dotnet core is not installed. Otherwise you get the exact version currently installed.
    OR, if it still doesn't work:
    2) try to delete global.json and then rebuild the solution. This should specifically solve the error "The current .NET SDK does not support targeting .NET Standard 2.0. ..."
- If the solution builds fine but the project won't start, check if you have a message similar to "you cna't trun that type of project". If so, right-click on the actual game project in the solution (asopposed to the other projects : shared libraries and whatnot) and select "Set as Startup Project".
EDIT 3 : those comments are now included in the FAQ : https://tzachshabtay.github.io/MonoAGS/articles/faq.html
 

Crimson Wizard

#1
Hey Monsieur OUXX!

Probably I should have posted this earlier, but since you started this thread, hope you won't mind if I link my own test games on MonoAGS here for the reference (and code example).

An important note: I did not use Editor when making them, because a) I was mostly curious whether it is possible to write a game without using any tool (spoiler: it is), and b) Editor was not ready when I started (not sure if it is now).

My repository with games: https://github.com/ivan-mogilko/MonoAGSGames
(it has central MonoAGS repository as submodule, so you have to init submodule to make them build).

Games are in separate folders:
1) Game. This is the very first game made long time ago. Has a dummy scene with tweened objects simulating driving along the road.

2) LastAndFurious. The port of "Last & Furious" game previously done in AGS.
About 90% complete (no car collisions, no in-game track editing, and AI is glitching sometimes).
On another hand, it has this:
Spoiler

3) AudioMixerGame. Implements an audio mixer system with multiple channels and audio clips, where each channel and clip may be assigned a tag to bind them together. When you start a clip, it chooses a channel depending on the tag. Also, each tag has its separate volume setting.
The purpose of this "game" was prototyping advanced audio system, but later Tzachs implemented his own right in the engine (haven't checked it out yet though).

4) LayerGame. Two rooms, testing parallax effect, camera zooms and zoom trigger zones.
Spoiler


PS. As you may notice, none of my test games actually feature characters or anything adventure-related. The idea was to first test out some basic game elements, and then move to adventure genre mechanics, but I got little too busy, and a little bored, so decided to make a break.

PPS. Should have probably prepared actual runnable games, but there was some issue with compilation output having a tonn of .NET DLLs copied into game folder, so I decided to wait until there is a fix for that.

Monsieur OUXX

#2
Nope! Don't mind at all ^_^

My approach is slightly different from yours : I will want to use the Editor as much as possible.


EDIT (unrelated) : dammit! :-D why do code geniuses like you guys already use expression-bodied members? They aren't even 3 years old! How do you expect people like us to follow? Lol.:= (don't even bother answering that)
 

Crimson Wizard

Quote from: Monsieur OUXX on Wed 02/05/2018 16:40:03
EDIT (unrelated) : dammit! :-D why do code geniuses like you guys already use expression-bodied members? They aren't even 3 years old! How do you expect people like us to follow? Lol.:= (don't even bother answering that)

Did not even know they are called like that. Tzachs told me about these, and since they look kinda cool, I decided to use them also :).

Monsieur OUXX

#4
First experience when opening the .sln on my machine that has VS2017 Community installed (from Unity I believe?) --> It tells me MonoAGS needs the .Net Framework 4.6.1. I'm going to install it but is it really mandatory?

EDIT: after letting VS install the whole shebang itself, after restarting it I get "these projects are not supported" :~(
[imgzoom]https://78.media.tumblr.com/c9f4c572d673d88f3d65f7a83e099f3e/tumblr_p84gtiqtUQ1tsfksfo1_1280.png[/imgzoom]


[imgzoom]https://78.media.tumblr.com/e1f1d1fa64c291f5017bd0e2956bb1c6/tumblr_p84gxvl9HW1tsfksfo1_1280.png[/imgzoom]
 

ChamberOfFear

You probably don't have Xamarin installed. Do you really need to test the mobile platforms? It should be safe to continue and just ignore the projects that didn't load.

tzachs

Hi! And.. Cool! ;-D

A few notes so far:

Editor:

There is no editor to speak of yet. This is what I am currently working on.
Currently the only "editing" component that exists is the inspector, which is currently opened from the game itself.
From the demo game you can click alt+g to open the game view, then select one of the room objects, and edit the properties of that selected object -> only it's not actually changing any code currently, it just changes it for the current game.
Rough timeline:
In my next big code push (coming hopefully in the next week or two), I'm removing the alt+g to open the game view from the game and moving it to the editor, along with a play/pause button and the ability to select/drag/scale/rotate objects directly in the scene when paused -> though still only in the current running game.
After that the next item for the editor will be to generate the needed code for actually modifying the game code.
And then, I'll add a "create new game" button (currently there's only "load game") with one default template (for now) for generating the startup code.
Following that, working on completing up the initial version of the editor and rewriting the save/load game system before releasing an official 0.1 version: a not comprehensive list of issues for that release can be viewed here: https://github.com/tzachshabtay/MonoAGS/milestone/1

Android & IOS:

Like ChamberOfFear said, you'll need Xamarin installed and the android/ios SDKs.
I've posted links with instructions in the main readme in the repo: https://github.com/tzachshabtay/MonoAGS/blob/master/README.md
I haven't written it down in the docs website, though, I'll add it there soon.
If you currently are just developing for desktop, you can indeed ignore those errors.
Also note that IOS is not currently officially supported, it was only partially working the last time I tested it (no sound and incredibly slow on an ipad2, I haven't tested it on a newer device yet, and the editor takes priority so I'm probably not going to add ios support for a while).

General early adopter warnings:

Problems you'll probably encounter:
- Missing features: Save/load is the most striking gaping hole in the engine now. Other than that I think that most of the widely used AGS features are there in one form or another -> let me know otherwise if you're in need of something specific.
- Usability: Well, obviously, as there's no editor, you'll need to write code for everything, including object creation which might not be the most friendly experience around (check out the demo game, or Crimson Wizard's games for examples on how it's done). Also, the API might be different at times than AGS, use the AGS cheatsheet if you can't find something and let me know of any problem that arises.
- Bugs: Might go without saying, but you will encounter bugs -> open issues on github or write to me/here if you prefer, I'll try to assist in any way I can. Note that you can also open an issue on github just to ask a question or start a discussion.
- Changes: The codebase is still getting A LOT of breaking changes, so it's going to be difficult to keep pace with engine updates (Crimson Wizard's games, for example, will not compile with the newest engine version, as there were breaking changes in the last month -> I'll submit a pull request to fix this when I finish with the current editor work I'm doing).
This is optional, but if you want, you can put your code on github or some other source control provider if you prefer, and I'll try to help and submit pull requests when I have a new engine version to make sure your game still compiles and runs as expected. Creating a public repo also has the benefit of allowing me to easily debug issues that you'll report, and it will help future potential users as another sample.

Other than that, I really really appreciate you taking the effort of trying it out, I hope you'll like it, and don't be afraid to ask the silliest questions you can think of and request the tiniest or most epic features imaginable.

Monsieur OUXX

#7
Thanks for all the tips, I'll use them when I reach the next step.

For now, I'm trying to be in the head of a complete beginner : "How do I know what to do when some of the solution's projects don't load? Can I do without them or are they vital?". It's good to know that I don't need Xamarin for the Android project. (maybe adding a little note on that topic in the Wiki would be a good idea?)
However, I'm stil having issues: the AGS.Editor project is still there in the solution and doesn't build. Because of that, the other projects complain that AGS.Editor.dll is missing. I'll give more details tonight when I get home.
 

Crimson Wizard

I cannot build AGS.Editor either, it sais "The current .NET SDK does not support targeting .NET Standard 2.0.  Either target .NET Standard 1.6 or lower, or use a version of the .NET SDK that supports .NET Standard 2.0."
Probably it requires installing very particular SDK?

The only other project that requires Editor.dll is DemoGame (it did not before iirc).

tzachs

Quote from: Monsieur OUXX on Thu 03/05/2018 09:24:09
It's good to know that I don't need Xamarin for the Android project. (maybe adding a little note on that topic in the Wiki would be a good idea?)
You do need Xamarin for the Android project, you don't need the android project for running on desktop. Yes, I'll add that to the docs too, good idea.

Quote from: Crimson Wizard on Thu 03/05/2018 12:26:24
I cannot build AGS.Editor either, it sais "The current .NET SDK does not support targeting .NET Standard 2.0.  Either target .NET Standard 1.6 or lower, or use a version of the .NET SDK that supports .NET Standard 2.0."
Probably it requires installing very particular SDK?
It requires the .net core 2.0 sdk. It should be installed automatically with the latest VS2017 update. If it didn't install for some reason, you can get it from here: https://www.microsoft.com/net/download/windows/build
You can verify which version you have installed by running from console: `dotnet --info`.

Quote from: Crimson Wizard on Thu 03/05/2018 12:26:24
The only other project that requires Editor.dll is DemoGame (it did not before iirc).
Yes, that's a temporary thing, in the current version I'm working on I removed that dependency.

Crimson Wizard

I've already had .NET 2.0 installed, and I installed most recent version again, but it still gives same error.

Upon quick investigation, the error points to the file called "Microsoft.NET.TargetFrameworkInference.targets". This file has following inside:
Code: xml

  <PropertyGroup  Condition="'$(TargetFrameworkIdentifier)' == '.NETStandard' And '$(NETStandardMaximumVersionExclusive)' == ''">
    <NETStandardMaximumVersionExclusive>1.7</NETStandardMaximumVersionExclusive>
    <NETStandardMaximumVersionHumanReadable>1.6</NETStandardMaximumVersionHumanReadable>
  </PropertyGroup>

  <Target Name="_CheckForUnsupportedNETStandardVersion" BeforeTargets="_CheckForInvalidConfigurationAndPlatform;Restore;CollectPackageReferences"
          Condition="'$(TargetFrameworkIdentifier)' == '.NETStandard' And '$(NETStandardMaximumVersionExclusive)' != ''">

    <NETSdkError Condition="'$(_TargetFrameworkVersionWithoutV)' >= '$(NETStandardMaximumVersionExclusive)'"
                 ResourceName="UnsupportedTargetFrameworkVersion"
                 FormatArguments=".NET Standard;$(_TargetFrameworkVersionWithoutV);$(NETStandardMaximumVersionHumanReadable)"
      />    
  </Target>


For some reason NETStandardMaximumVersionExclusive is still 1.7.

ChamberOfFear

#11
I noticed the same thing when I was trying last night. I had to install the exact version of dotnet Core that was specified in the global.json, that is v2.0.2. If I tried any other version, higher or lower, for instance v2.1.105 it wouldn't work.

EDIT: I'm not by my computer right now, but I think runinng the command `dotnet --version` on the command line while in the project folder output an error message about the global.json file, if I was using a dotnet version that wasn't supported by the project.

Monsieur OUXX

Quote from: ChamberOfFear on Thu 03/05/2018 13:39:44
the exact version of dotnet Core that was specified in the global.json, that is v2.0.2.

Well it's not available for download >:( https://www.microsoft.com/net/download/all
Any other way? I'll try from within VS.
 

ChamberOfFear

Quote from: Monsieur OUXX on Thu 03/05/2018 14:45:59
Well it's not available for download >:( https://www.microsoft.com/net/download/all
Any other way? I'll try from within VS.

https://github.com/dotnet/core/blob/master/release-notes/download-archives/2.0.2-sdk-download.md

You could also just wait for tzachs to fix it. I don't think it's supposed to have a strict requirement to a specific version of dotnet core

tzachs

That's very weird, it doesn't reproduce on my linux machine (using version 2.1.104).
Can you try deleting the global.json file and try again?
If it doesn't work, then you can either download that specific version from the link ChamberOfFear posted (and 'un-delete' global.json), or wait for me to get to a windows machine (tonight) and I'll try to reproduce it from there.

ChamberOfFear

Deleting global.json works.

The console output looks like this when I run without the correct version installed
Code: ags

$ dotnet run
The specified SDK version [2.0.2] from global.json [E:\Programming\MonoAGS\global.json] not found; install specified SDK version

tzachs

Great! Thanks for verifying.

Quote
The console output looks like this when I run without the correct version installed

Yeah, that's what it should do, it makes sense, I was surprised that it didn't give me this error on the linux machine. But I think that was because it's not about which dotnet version is the active one, but whether it's installed on the machine at all, and I guess it is installed on my machine so it didn't yell at me even though I installed a newer version, it simply ignored it and used the older one.

cat

Interesting! I've added links to the repo and doc in the first post.

Monsieur OUXX

Deleting global.json worked. I'm now able to build the solution. Now I'm taking a deep breath and continuing ;)
I should let you know that I downloaded Godot alongside MonoAGS, though <-- that's to maintain pressure and suspense ;)
 

tzachs

Quote from: Monsieur OUXX on Thu 03/05/2018 21:00:38
I should let you know that I downloaded Godot alongside MonoAGS, though <-- that's to maintain pressure and suspense ;)
haha, game on!
Are you using Escoria? https://github.com/godotengine/escoria
Because that would make things even more interesting.

Monsieur OUXX

#20
Quote from: tzachs on Thu 03/05/2018 22:00:37
Are you using Escoria?
If you recall the thread where I was trying to compare the engines, that one was my teacher's pet. But I need to be realistic : If I ever want to have a chance to complete the game I'm working on, I need to stay somewhere where there's a community that knows shit ;)


EDIT : moving on. So now the game compiles (even without Xamarin -- that said, I didn't pay attention to the .Android project, it might just be that it's been excluded automatically  from the build the first time it failed to load/build).
The game runs.
I'm running Demo Quest, and I'm worried about two things : 1) the mixed resolutions (game in low-res, font in hi-res, and I couldn't see if the cursor is aligned to the low-res grid or to the screen's resolution), 2) building the animations (views/loops). Without a GUI, it will be a real pain! For me that's a big no no.
 

tzachs

Quote from: Monsieur OUXX on Thu 03/05/2018 22:45:20
the mixed resolutions (game in low-res, font in hi-res,
You can turn off the hi-res fonts, just delete the lines: "GLText.TextResolutionFactorX = 4; GLText.TextResolutionFactorY = 4;" in Program.cs.

Quote
and I couldn't see if the cursor is aligned to the low-res grid or to the screen's resolution)
Everything is done with sub-pixel positioning so the cursor should align with the screen's resolution. If aligning the cursor the the low-res grid is important, it shouldn't be too hard to add as a feature (though if you couldn't tell the difference, who will?).

Quote
2) building the animations (views/loops). Without a GUI, it will be a real pain! For me that's a big no no.
I agree, an animation editor is a must for version 0.1.
Note though that for loading the animation loops, you can load an entire folder as a loop without having to write every single frame path (assuming the frames are alphabetically ordered).
In fact, loading idle + walking animation for the hero in the demo game is done with this single expression:

Code: csharp

IOutfit outfit = await game.Factory.Outfit.LoadOutfitFromFoldersAsync(_baseFolder, walkLeftFolder: "Walk/left",
	walkDownFolder: "Walk/front", idleLeftFolder: "Idle/left", idleDownFolder: "Idle/front", 
	speakLeftFolder: "Talk", loadConfig: loadConfig);

Monsieur OUXX

@Crimson Wizard or others : how ae sprite resources loaded in AGS? For example, will the loop sprites of a view be loaded when I set the view to the character? Will the objects and background sprites be loaded when I enter the room?
 

Crimson Wizard

#23
Quote from: Monsieur OUXX on Fri 04/05/2018 16:34:37
@Crimson Wizard or others : how ae sprite resources loaded in AGS? For example, will the loop sprites of a view be loaded when I set the view to the character? Will the objects and background sprites be loaded when I enter the room?

This is, among with lack of the Editor, IMHO the weakest part of MonoAGS right now. The problem is that it does not have any built-in resource manager yet.
You have to mostly write storing and loading (and freeing) stuff yourself.
Of course there are factory methods, like the LoadOutfit function quoted above, that make it possible to quickly load a whole "group" of items. But still the process has to be controlled by you.

Iirc DemoGame loads every game resource at the start.

I did not like this approach, so tried to experiment a bit, looking for a way to handle rooms resources. You may check out how I did it in latest games ("Last & Furious" and "Layers Game"). There are classes that may be called "Room managers" (DemoGame has similar thing also). E.g. check "RoomScript" class, it's a parent class of "room manager", and there is "loadAsync" method in every subclass that loads stuff - you may check their implementations to see how they load resources up.


For example, this is the room loading code from the TitleScreen of the Last&Furious:
Spoiler

Code: csharp

protected async Task<IObject> addObject(string name, string gfile, int x = 0, int y = 0)
{
            IObject o = _game.Factory.Object.GetObject(name);
            o.Image = await _game.Factory.Graphics.LoadImageAsync(_roomAssetFolder + gfile);
            o.X = x;
            o.Y = y;
            return o;
}
protected override async Task<IRoom> loadAsync()
{
//========== FROM HERE ON - we load stuff and create objects ===========================
            IGameFactory factory = _game.Factory;
            _room = factory.Room.GetRoom(ROOM_ID);
            _room.Background = await addObject("TitleScreen.BG", "gradiented-title.png", 0, -80);

            // TODO: label with the game version number in the corner of the title screen
            var label = factory.UI.GetLabel("VersionLabel", LF.GAME_VERSION, 0, 0, 0, 0, addToUi: false);
            label.TextConfig.Font = AGSGameSettings.DefaultTextFont;
            label.TextConfig.AutoFit = AutoFit.LabelShouldFitText;
            _room.Objects.Add(label);

            _room.RoomLimitsProvider = AGSRoomLimits.FromBackground;

            _music = await factory.Sound.LoadAudioClipAsync(LF.MusicAssetFolder + "Car-Theft-101.ogg");


//========== Initializing other settings and subscribing to events ===========================
            _room.Events.OnBeforeFadeIn.Subscribe(onLoad);
            _room.Events.OnAfterFadeIn.Subscribe(onAfterFadeIn);
            _room.Events.OnAfterFadeOut.Subscribe(onLeave);

//========== Rooms is done, return it ===========================
            return _room;
}

[close]


Some things may be loaded separately from the room, when they are required. I made separate loading functions for that.
For example, I have a static class RaceAssets that has a method that loads anything related to racing itself.
I call it when player chooses "Start Game", during transition into racing room:
Spoiler

Code: csharp

public static async Task LoadAll(IGame game)
{
	IGraphicsFactory f = game.Factory.Graphics;
	for (int i = 0; i < Names.Length; ++i)
	{
		string name = Names[i];
		IImage carmodel = await f.LoadImageAsync(string.Format("{0}carmodel{1}.png", ObjectAssetFolder, i + 1), MagicColor.TopLeftPixel);
		CarModels.Add(name, carmodel);
		IImage portrait = await f.LoadImageAsync(string.Format("{0}face{1}.png", UIAssetFolder, i + 1), MagicColor.TopLeftPixel);
		Drivers.Add(name, new DriverCharacter(name, portrait, carmodel, 90.0F));
	}

	RacerFrames = new IImage[Race.MAX_RACING_CARS];
	for (int i = 0; i < Race.MAX_RACING_CARS; ++i)
		RacerFrames[i] = await f.LoadImageAsync($"{UIAssetFolder}racerframe{i + 1}.png", MagicColor.TopLeftPixel);
	BannerReady = await f.LoadImageAsync(UIAssetFolder + "banner1.png", MagicColor.TopLeftPixel);
	BannerSet = await f.LoadImageAsync(UIAssetFolder + "banner2.png", MagicColor.TopLeftPixel);
	BannerGo = await f.LoadImageAsync(UIAssetFolder + "banner3.png", MagicColor.TopLeftPixel);
	BannerLoose = await f.LoadImageAsync(UIAssetFolder + "banner4.png", MagicColor.TopLeftPixel);
	BannerWin = await f.LoadImageAsync(UIAssetFolder + "banner5.png", MagicColor.TopLeftPixel);
}

[close]


Similarily, I could perhaps make mirrored methods of unloading things, which would dispose all those image objects, etc.


Observing this code, you may notice that I sometimes load sprites directly in the object. This is a okay in a tiny games, but in bigger game could cause duplication of resources in memory.

In theory you could emulate AGS sprite system by creating a List<IImage>, or Dictionary<some key type, IImage>, loading sprites there first, and then assigning that list/dictionary elements into your objects and views.

tzachs

Crimson Wizard, I believe Monsieur OUXX was asking about how sprite loading works in AGS, not how it works in MonoAGS.

Quote
This is, among with lack of the Editor, IMHO the weakest part of MonoAGS right now. The problem is that it does not have any built-in resource manager yet.
You have to mostly write storing and loading (and freeing) stuff yourself.
Right, well, from my point of view the issue of having to write the loading code yourself is because there's no editor, not because there's no resource manager. The editor will generate that code for you.

As for a resource manager, the current plan is to have a resource loading strategy and resource freeing strategy which will be built on top of the current infrastructures. So for resource loading strategy you might have "load on startup", or "load when entering room (which has the specific asset)" or "load only when the asset is needed" (lazy loading), and you'll be able to code a custom resource loading strategy which does things differently. Similarly for a resource freeing strategy you might have "free after resource was not used for X amount of time" or "free when leaving room" or "always in memory" or your custom coded freeing strategy.
And you'll have the option to set a default loading/freeing strategy for the game, and override it for specific assets.

Crimson Wizard

#25
Quote from: tzachs on Fri 04/05/2018 17:59:18
Crimson Wizard, I believe Monsieur OUXX was asking about how sprite loading works in AGS, not how it works in MonoAGS.

Um, oh.

Well, in that case
Quote from: Monsieur OUXX on Fri 04/05/2018 16:34:37
how ae sprite resources loaded in AGS? For example, will the loop sprites of a view be loaded when I set the view to the character? Will the objects and background sprites be loaded when I enter the room?

In AGS sprites are loaded in memory only when they have to be displayed on screen. AGS is constantly streaming sprites into sprite cache, keeping track of the order the sprites were demanded by the drawing code. And when the cache is full it gets rid of the sprites that were used long ago first.

Note, that this is an optimal solution for low-res games, where sprites are smaller and animations are not that long. For hi-res games with smooth animations with lots of frames pre-caching strategy could be a better choice.

Room backgrounds is an exception here, they are loaded immediately.

cat

I'm joining you playing MonoAGS but I'm already stuck ;)

I checked out the source and installed Visual Studio but I get this "The current .NET SDK does not support targeting .NET Standard 2.0. blablabla" message. I installed the .NET Core and 3.5 development tools additionally via Visual Studio Installer but I don't have the dotnet command on the command line ???
For workloads I only picked .NET desktop development in the installer.

I'm really clueless, do I have to install some additional components? Seems weird this is not done automatically when installing VS.

tzachs

Quote
I'm joining you playing MonoAGS
Great! :)

Quote
but I'm already stuck
Not so great..

Quote
but I don't have the dotnet command on the command line
Hmmm, that is weird. Were there any errors during the install?
I would check first if dotnet core was really installed: is there a "C:\Program Files\dotnet" library? what folders do you see in "c:\Program Files\dotnet\sdk" and "c:\Program Files\dotnet\shared\Microsoft.NETCore.App"?
If nothing is there, then it looks like it wasn't installed. I don't know if it's a problem in VS installer, but you can also install it from here: https://www.microsoft.com/net/learn/get-started/windows
If there is a dotnet core version installed, then maybe for some reason the installation failed to add it to your PATH environment variable.

Other than that, what time did you download MonoAGS? I pushed a fix to the original problem a few hours ago. If you downloaded before the fix make sure to delete the "global.json" file.

Crimson Wizard

I have an idea. Making proper and thorough documentation takes a while, but posting solutions in forum posts make things go unnoticed.

Monsieur OUXX, what about creating a google drive document, or any similar kind of page, and sharing permission with few people, tzachs + those who are interested trying MonoAGS. Then fill that documents with FAQ and first step instructions, that all contributors could ammend.

cat

Quote from: tzachs on Fri 04/05/2018 21:33:21
Hmmm, that is weird. Were there any errors during the install?
Not that I've noticed...
Quote
I would check first if dotnet core was really installed
Right, looks like it wasn't installed at all. No idea what the VS installer was doing :-\

I installed it from your link, and now I was able to compile it and run the demo! ;-D

tzachs

Quote from: Crimson Wizard on Fri 04/05/2018 21:41:37
I have an idea. Making proper and thorough documentation takes a while, but posting solutions in forum posts make things go unnoticed.

Monsieur OUXX, what about creating a google drive document, or any similar kind of page, and sharing permission with few people, tzachs + those who are interested trying MonoAGS. Then fill that documents with FAQ and first step instructions, that all contributors could ammend.
I created a FAQ wiki page with what was raised so far: https://tzachshabtay.github.io/MonoAGS/articles/faq.html
Note that if you have a Github account you can easily (I think) contribute changes: there's an "Improve this doc" button on the top right of the screen (and all on other pages in the website) which takes you to the page on github, from there it's just about clicking the edit button (behind the scenes I believe it automatically forks the project, and creates a pull request with the suggestions).

If that's not satisfactory, I'm ok with having a google doc.

Crimson Wizard

#31
Sorry, I did not mean extra job for you, I suggested google doc for non-developers, as something you can make quick notes in without worrying for organizing, since I noticed Monsieur OUXX is already doing similar thing in his first post...
The problem with document in repository is that other people won't know what to write there, except maybe questions.
But this was just an idea, idk if anyone find that convenient.

cat

So, I have a few questions/remarks. If you think this derails this thread too much, please tell me and I'll move it somewhere else.

  • In contrast to AGS, MonoAGS' output is .NET, right? This means, that not only developers but also players will have to have .NET installed on their PCs. Isn't this a problem? It seems that the newer Windows versions ship with .NET installed, but what about the older ones? What version would be safe for most Windows versions? I guess the engine build should target a low enough version? Any thoughts on that topic?
  • When starting the game, there are two windows opened. Why is that so?
  • Did you plan localization for games? ITranslate seems to refer to positions, not language. Adding localization support later on could be a pain in the a..
  • Why do the shaders not affect the player character?
  • Is there anything that can be actually done in the demo game?

tzachs

Quote from: cat on Sat 05/05/2018 11:11:30
In contrast to AGS, MonoAGS' output is .NET, right? This means, that not only developers but also players will have to have .NET installed on their PCs. Isn't this a problem? It seems that the newer Windows versions ship with .NET installed, but what about the older ones? What version would be safe for most Windows versions? I guess the engine build should target a low enough version? Any thoughts on that topic?
Yes, MonoAGS output is .Net, but players will not necessarily need to have .NET installed. MonoAGS currently compiles to dot net framework on windows and on mono for non-windows. The plan is to also add support for .Net Core, which is the new open source runtime sponsored by Microsoft. Both .Net Core and Mono can be packaged with the game so that the player will not need to download it, and there are linkers that strip out all parts of the framework that the game doesn't actually use, so the added hard-disk space should not be too big (this is in theory, we'll need to actually try it out to see that it works as intended).
As for old Windows version, the engine supports Windows 7 and above, Windows XP (and vista) are not supported. I wanted to support Windows XP but it's too hard:
1. It would mean targetting an older dot net version and losing out on a lot of features and cross-platforming capabilities (not to mention security fixes).
2. One by one all of the dot net libraries are killing support for Windows XP, so that will require using older versions or maintaining our own forks, not feasible for the long-term.
Otoh it's getting less and less used by the day (as of this day it has only 0.25% market share on steam) so hopefully it would not be too big of an issue.

Quote
When starting the game, there are two windows opened. Why is that so?
The console window can be turned off (somewhere in the project options iirc). I currently left it on for my development purposes (I noticed that on rare occasions, at least on Mac, it will show me errors that are not visible on the visual studio debug console), but I'll turn it off by default soon.

Quote
Did you plan localization for games? ITranslate seems to refer to positions, not language. Adding localization support later on could be a pain in the a..
Yes, I have plans for adding localization support (tracking issue is here if you have some specific thoughts). I have some vague ideas on how it will be implemented (basically thought of a partially cloned structure of the asset tree in a specific language folder -> if there is a matching translated asset we will take it, otherwise we'll take the base language asset).
I agree that it will be a big PITA to implement in a working system, but so is everything else really: i.e I had to make some hard decisions on which features to support initially and which to add later (I couldn't do all at once), and it doesn't matter what my choice is, the later a big feature is to add, the harder it gets do develop it.

Quote
Why do the shaders not affect the player character?
Currently you can set a shader for the entire game/screen and a shader for specific entities. If you set a shader for a specific entity it overrides the shader of the game, and the player has a specific shader (just for demo purposes). There is a plan to support multiple shaders per entity/screen which will then apply the screen shader to the player as well (this will probably be opt-out because you might WANT to override the screen shader).

Quote
Is there anything that can be actually done in the demo game?
Do you mean, puzzles? No.
You can look at the window in the left-most screen to see some viewport zooming, rotating and moving in parallel with some simple tweens.
You can click on the "?" button which opens a window to show a few of the features.
You can click alt+g to open the game view and the inspector and can play with all the different properties of the entities (there's a lot more to play there than with the properties window in AGS, so it's probably worth the time understanding them all, though note that the inspector is not completed yet so there are some available things you can do with the engine which you still can't do with the inspector).

Crimson Wizard

#34
Quote from: tzachs on Sat 05/05/2018 15:41:30
Yes, I have plans for adding localization support (tracking issue is here if you have some specific thoughts). I have some vague ideas on how it will be implemented (basically thought of a partially cloned structure of the asset tree in a specific language folder -> if there is a matching translated asset we will take it, otherwise we'll take the base language asset).

Probably should be posting this in the git issue... only wanted to put my little 1 cent for now. The localization system consists of two features, or two mechanics if you prefer: picking out appropriate asset, and assigning it to game object. The first is relatively easy, and my belief is that the idea you mentioned, about overriding asset tree, is actually the optimal one. The second would require designing API in code, and probably making all built-in text based (at least) components use it by default.

IMHO in theory it is possible to write simple text translation system similar to AGS on your own for your game, it's just that you would have to remember writing something like 'label.Text = Translation.Get("Original language text")' every time. Or maybe override/clone existing components and put that in them (not sure how easy that is).

cat

@tzachs: Thanks for the explanation, especially regarding .NET

I really like the AGS approach to translation. Just having to write the text in the base language and translation is done automatically is really convenient for the user. This could also be implemented without breaking the API, I suppose. Use a translation when available, otherwise just use the text.

tzachs

Right, sorry, I only talked about replacing the assets and forgot to talk about replacing the texts. I also like the approach of the text in the code written in the base language (I really dislike using some resource id without text so you don't know what's going on when you read the code). And I imagine having an interface in the text rendering pipeline which gets as input the base language string and returns a translated string, and the built in implementation will read the translation files and build a dictionary.
There's already an interface like this now specifically for speech that you can override and add translations in there, but nothing for HUDs yet, so I'll probably add that interface further down in the engine which will cover both scenarios (hope that makes sense). And of course there will be tooling on top, it'll combine both translations and speech into one GUI (both need to display all strings from the game) and will export translation/speech scripts etc. And to cap off the localization story there will be API to get the current language (and maybe also to set? Not sure how useful it would be to change the language at run-time) and change specific puzzles if needed based on the language (monkey wrench scenarios), and maybe also get some meta-data on the language (like is it right-to-left -> this is always a very painful thing to support in software, luckily I'm in a very good position for this).

cat

Quote from: tzachs on Sat 05/05/2018 21:23:54
Not sure how useful it would be to change the language at run-time
VERY useful. This allows for implementing language change buttons in the in-game menu. It think it's much more elegant to do it this way than having to run an external setup. Please also add a subscription handle for language changes to implement custom logic there.

tzachs

I wasn't thinking of an external setup but of a separate download altogether. Each voice pack is expensive in terms of hard-disk space, so my personal preference as a game developer will be not to force it on the player who knows which language she/he wants at download time anyway. But I realize other developers might have different preferences, and it is definitely useful for text only games.

Monsieur OUXX

#39
About the wiki page : I'm all in favor of a shared doc. CW has indeed noticed that I started writing tips in my very first post, buta shared document directly on the MonoAGS site is the best imo.

About the need of installing external packages : I wouldn't worry too much about that. We already had an extensive discussion (interrogation ;) ) with tzachs in another thread, and I'd say he has it rather well planned out -- provided he doesn't lose steam on the way to converting to .Net Core. In the future there should be a module testing that the requirements are present (maybe a pre-build script?), but for now it's not too tricky.

About the code that needs to be manually written and the absence of actual puzzles in the demo : maybe we should start a shared repository where we'd code some sort of basic middleware engine (a template, really) to make it easier to start a game with MonoAGS. Something that fills the current gaps until they're properly implemented by tzachs. Something as close as possible to an AGS game structre -- with comments in the code telling you where to insert code for this and that.
Maybe a NuGet package? So that the thingy can be recompiled by the maintainer(s) and then re-imported on the fly by all the people who use it?

EDIT : about that last point of starting to split optional game features into more readable and re-useable modules, I've got the perfect example : Demoquest is literally a Sierra template, which in turn uses the "Rotating Cursor" concept (right-click iterates through cursors). But that concept is also used by ... Sam&Max. We can clearly see how some game features could be enabled or disabled, and their generic code could be easily initialized from just a few parameters (in the case of cursors : the file containing the list of icon files of each cursor mode, and the text associated to each action).
So I'd suggest creating a separate library project in the solution with those features (the first of them being "rotating cursor", but I can give more examples : "scrolling inventory"). This library could then be included in each template (Sierra, 9-verb...).


EDIT 2 : On a different note: code-wise, how do you plan on binding an event function (such as : button.OnMouseClick(() => { .../* DO THINGS */ } ) ) from the in-game GUI? I have no trouble believing that the AGS Editor can simply insert some function name in game.agf and simultaneously insert an empty function with the same name in a game script file. It happens while the game is not running. But with Visual Studio, while the .exe is running, will that not be a bit tricky?

EDIT 3 : can you explain this piece of code
Spoiler

In Rooms.cs :
Code: ags

   EmptyStreet = Task.FromResult(Find(state, EmptyStreet.Result)); 


- I don't understand how EmptyStreet is populated after game gets loaded (in other words : how EmptyStreet is not null at the time "onSaveGameLoaded" gts called).
- I don't understand what is ".Result". Is it an "out" variable were find stores its result?
- More generally I don't understand the whole sequence.
    - Where does "Task" come from?
    - What's oldID versus ID? I'm guessing these are the IDs befaore/after load, but then again I fail to visualize the sequence of calls.
[close]
 

tzachs

Quote from: Monsieur OUXX on Mon 07/05/2018 09:35:06
Maybe a NuGet package? So that the thingy can be recompiled by the maintainer(s) and then re-imported on the fly by all the people who use it?
I created a community channel on MyGet for this (currently empty). Everybody can push nuget packages there and pointing visual studio to that channel will help you find MonoAGS specific packages. I plan to make the standalone editor pointing to it by default in its "third party modules" future window.
To point visual studio to that channel, open the Package Manager Settings and create a new package source with this url: https://www.myget.org/F/ags/api/v3/index.json
To push a package to the channel, I think you need to sign in to MyGet and go to this url and then follow instructions: https://www.myget.org/feed/Packages/ags

Quote
On a different note: code-wise, how do you plan on binding an event function (such as : button.OnMouseClick(() => { .../* DO THINGS */ } ) ) from the in-game GUI? I have no trouble believing that the AGS Editor can simply insert some function name in game.agf and simultaneously insert an empty function with the same name in a game script file. It happens while the game is not running. But with Visual Studio, while the .exe is running, will that not be a bit tricky?
Yes, it's very tricky. I had a few (maybe naive, maybe not) thoughts on how to handle it, one is compiling tiny assemblies and side-load them, the other is to use an in editor interpreter, and if all else fails, then we'll fall back to "stop the game -> unload the exe -> recompile -> reload".

Monsieur OUXX

Quote from: tzachs on Mon 07/05/2018 15:38:42
To point visual studio to that channel...
To push a package to the channel...
I don't have a perfect understanding of the packages workflow.
What i I want to  maintain a package? Do I need to have a code repo that builds the latest sources and pushes them onto the channel... and then on the other end I've got the code repo of my project that pulls the channel whenever there is an update?
 

tzachs

Kind of, yes. As a package maintainer you can either push a package to the feed via command line (so you can integrate it automatically on every change in a CI build in your source code repo, for example) or by browsing and selecting the nuget package manually from the MyGet website. To actually create a nuget package from your library, I think it's just a checkbox somewhere in the build options of the project in visual studio ("create nuget" or something like that) which creates a nuget package every time you build.
On the client side, in visual studio, for example, you'll see there's an update to the package in the solution explorer, and then you can right click -> update. It doesn't update automatically by default, but apparently there's a way to configure it for automatic updates (never tried it myself).

Crimson Wizard

#43
Since tzachs missed this one...

Quote from: Monsieur OUXX on Mon 07/05/2018 09:35:06
EDIT 3 : can you explain this piece of code
Spoiler

In Rooms.cs :
Code: ags

   EmptyStreet = Task.FromResult(Find(state, EmptyStreet.Result)); 


- I don't understand how EmptyStreet is populated after game gets loaded (in other words : how EmptyStreet is not null at the time "onSaveGameLoaded" gts called).
- I don't understand what is ".Result". Is it an "out" variable were find stores its result?
- More generally I don't understand the whole sequence.
    - Where does "Task" come from?
    - What's oldID versus ID? I'm guessing these are the IDs befaore/after load, but then again I fail to visualize the sequence of calls.
[close]


First of all we need to clarify the purpose of "static class Rooms". This is something like a game-specific manager class that simply keeps reference of the room-loading Tasks (not just the room themselves), storing them in the distinctly named variables.

The rooms, as objects, are also stored in the IGameState object (if you check its definition you'll see "Rooms" list).

IGameState is a "main" holder of rooms that keeps them in memory. I am not sure for what purpose, but guess there are built-in mechanics that process that list of rooms in IGameState by default.
And "static class Rooms" is just your own custom management system, for convenience.

I am also not sure how and where, but supposedly IGameState recreates all rooms in its list when it restores save, out of data written in a save file.
What you see in "onSaveGameLoaded" function, is a restoration of references inside this custom class "Rooms" after save is loaded.
Basically what it does, it creates a new Task in a already complete state using Task.FromResult API (Quote from doc: Creates a System.Threading.Tasks.Task that's completed successfully with the specified result.), and puts a new room object from IGameState, with ID identical to an old room object (that became no longer valid after loading the save).

Task is a generic (actually, there is a non-generic and generic kind), which has "result type" as a parameter, so yes, task.Result is an actual object, set by completed task process.

cat

Before anything else, I want to say the following:
I took a somewhat deep look at the code and documentation yesterday. I have to say, I'm absolutely blown away by what you have achieved already, tzachs! It seems to be an almost feature complete new version of AGS in a clean coding style and thoroughly documented. Amazing what you have done so far all on your own.

And here I am back with more questions :P

  • What do I have to do to run the unit tests? Is there some additional stuff I need to install? I get the message "No test is available in D:\Daten\MonoAGS\MonoAGS\Source\Tests\bin\Debug\Tests.dll. Make sure that test discoverer & executors are registered and platform & framework version settings are appropriate and try again."
  • What files do I need to deploy of a game? Everything from DemoQuest.Desktop\bin\Release except .pdb?

Quote from: Monsieur OUXX on Mon 07/05/2018 09:35:06
About the code that needs to be manually written and the absence of actual puzzles in the demo :
I agree, there need to be templates instead of needing to copy stuff from the demo game.

Quote
So I'd suggest creating a separate library project in the solution with those features (the first of them being "rotating cursor", but I can give more examples : "scrolling inventory"). This library could then be included in each template (Sierra, 9-verb...).
I fully agree. I was surprised to see that RotatingCursorScheme is part of the engine when it should actually be more a built on top thing.

Quote from: Crimson Wizard on Mon 07/05/2018 19:08:37
Basically what it does, it creates a new Task in a already complete state using Task.FromResult API (Quote from doc: Creates a System.Threading.Tasks.Task that's completed successfully with the specified result.), and puts a new room object from IGameState, with ID identical to an old room object (that became no longer valid after loading the save).
So, it's something similar to a promise?

tzachs

Quote from: Crimson Wizard on Mon 07/05/2018 19:08:37
IGameState is a "main" holder of rooms that keeps them in memory. I am not sure for what purpose, but guess there are built-in mechanics that process that list of rooms in IGameState by default.
And "static class Rooms" is just your own custom management system, for convenience.

I am also not sure how and where, but supposedly IGameState recreates all rooms in its list when it restores save, out of data written in a save file.
Right, IGameState is the object that gets saved and loaded from the file, so basically everything that can change is part of the game's state, including the rooms. All variables that are created outside of game state (like if you simply do "int i = 5" instead of "int i = state.GlobalVariables.Ints.GetValue("MyVariable", 5)") will not be saved by default and it's your responsibility to load it after loading a game.

Crimson Wizard's explanation was spot on, note that this convenience Rooms game specific class will be automatically generated by the engine, including that boilerplate code of restoring the references after game load.

Quote
I took a somewhat deep look at the code and documentation yesterday. I have to say, I'm absolutely blown away by what you have achieved already, tzachs! It seems to be an almost feature complete new version of AGS in a clean coding style and thoroughly documented. Amazing what you have done so far all on your own.
Thanks! ;-D

Quote
What do I have to do to run the unit tests? Is there some additional stuff I need to install? I get the message "No test is available in D:\Daten\MonoAGS\MonoAGS\Source\Tests\bin\Debug\Tests.dll. Make sure that test discoverer & executors are registered and platform & framework version settings are appropriate and try again."
"To run the unit tests, please install the NUnit 2 Test Adapter (available from Visual Studio, tools menu -> Extensions and Updates... -> Online)." (from the readme)

Quote
What files do I need to deploy of a game? Everything from DemoQuest.Desktop\bin\Release except .pdb?
If you just want to deploy for Windows, then yes.
To deploy for Mac & Linux, the executable itself will not be recognized by default. So you can either add a small shell script just with "mono mygame.exe", and request for users to install mono, or create a self-contained mono application like we mentioned before. Like I said, I haven't tried it yet, but this is the link with instructions: http://www.mono-project.com/docs/tools+libraries/tools/mkbundle/
To deploy for Android, see here: https://docs.microsoft.com/en-us/xamarin/android/deploy-test/publishing/

Quote
I agree, there need to be templates instead of needing to copy stuff from the demo game.
Yes, this will be part of the editor. Copying code is just a temporary thing for now.

Quote
I fully agree. I was surprised to see that RotatingCursorScheme is part of the engine when it should actually be more a built on top thing.
It's part of the engine in the sense that's in the same dll, but it's definitely a built on top thing, it's a layer above everything else with nothing depending on it, and it will be no trouble to move it to a template project once the editor is ready.

Quote
So, it's something similar to a promise?
Yes, Task is c# equivalent of a promise, and it powers async/await in c# the same way a promise powers async/await in javascript.

Monsieur OUXX

#46
I've created my new local branch but I fail to publish it to the remote repo. I'm only offered to "push" it and even then I get this :
QuoteError encountered while pushing branch to the remote repository: Git failed with a fatal error.
fatal: Could not read from remote repository.
It used to prompt me for my github credentials but now it doesn't anymore. I'm not sure if it's because they're accepted (and cached somewhere) and the problem comes after, or if that's the problem.
I've tried to do the push using the git command line but I cannot make heads or tails of all that command line crap (I make nightmares where Unix laughs at me because I'm not wearing pants). I can't even go past the simple line git remote set-url origin username:password@github.com/tzachshabtay/MonoAGS.git as shown here. It tells me that it's not a valid git location. I don't know if/where I should put https.

==========

In the meatime I'm adding my "middleware" library project to the solution. I've first had to install the ".Net Core templates" extension to my VS 2017 Community I had to go to the Visual Studio Installer and check ".Net Core Cross platform workload". Then I've added a ".Net Core library" project tot he solution. I've decided to call it "FakeAGS" :=

I'm in the process of creating the feed : https://www.myget.org/feed/Packages/fakeags
I'm reading this : https://weblogs.asp.net/bsimser/automatically-publishing-nuget-packages-from-github

What's annoying me right now is a design question : I'd like to keep my "FakeAGS" in the MonoAGS solution, to benefit from neighbour sources/autocompletion and easy testing, but if I understand correctly it has to be in an entirely different solution/repo to benefit from MyHub's auto build and push. Correct?

==============

I want to create a copy of "Demo" to create a variation of it for my own test purposes. I don't understand if that's the right way to do. After I copy and paste the "Demo" folder and its contents, and rename that copy "Demo2", Visual Studio seems to ignore it. How am I supposed to proceed anyway? Is it like "one instance of MonoAGS = one game" or "one instance of MonoAGS = several potential games"?

==============

EDIT : this bit solved. Since I didn't find how to simply force a Restore Packages, I closed the solution, deleted the .nuget folder, then re-opened it. Then I got the migration report, where, without surprise, the mobile projects were not imported properly (no Xamarin). I cleaned the solution and rebuilt it. It worked.
Quote
Is it absolutely necessary to build the mobile versions every time? Here is why I'm asking: I don't know how I've done it, but yesterday I've managed to build and run the desktop version without having Xamarin installed. But today I do a rebuild and it won't restore the packages unless the Android project builds properly (therefore, the build fails). And for that, I would need Xamarin. So I'm trying to exclude the Android project from the build, but... I'm totally lost : where has the Configuration Manager gone? What the hell is that new "configure tasks" bullshit? ;-D
Spoiler

Code: ags

1>------ Build started: Project: AGS.API, Configuration: Debug|AnyCPU ------
C:\Program Files\dotnet\sdk\2.1.200\Sdks\Microsoft.NET.Sdk\build\Microsoft.PackageDependencyResolution.targets(327,5): error : Assets file 'F:\Users\GQHH9006\Mes Documents\Mes textes\prog\MonoAGS_git\Source\AGS.API\obj\project.assets.json' not found. Run a NuGet package restore to generate this file.
C:\Program Files\dotnet\sdk\2.1.200\Sdks\Microsoft.NET.Sdk\build\Microsoft.PackageDependencyResolution.targets(167,5): error : Assets file 'F:\Users\GQHH9006\Mes Documents\Mes textes\prog\MonoAGS_git\Source\AGS.API\obj\project.assets.json' not found. Run a NuGet package restore to generate this file.
2>------ Build started: Project: AGS.Engine, Configuration: Debug|AnyCPU ------
C:\Program Files\dotnet\sdk\2.1.200\Sdks\Microsoft.NET.Sdk\build\Microsoft.PackageDependencyResolution.targets(327,5): error : Assets file 'F:\Users\GQHH9006\Mes Documents\Mes textes\prog\MonoAGS_git\Source\Engine\AGS.Engine\obj\project.assets.json' not found. Run a NuGet package restore to generate this file.
C:\Program Files\dotnet\sdk\2.1.200\Sdks\Microsoft.NET.Sdk\build\Microsoft.PackageDependencyResolution.targets(167,5): error : Assets file 'F:\Users\GQHH9006\Mes Documents\Mes textes\prog\MonoAGS_git\Source\Engine\AGS.Engine\obj\project.assets.json' not found. Run a NuGet package restore to generate this file.
3>------ Build started: Project: AGS.Engine.Desktop, Configuration: Debug|AnyCPU ------
4>------ Build started: Project: AGS.Editor, Configuration: Debug|AnyCPU ------
C:\Program Files\dotnet\sdk\2.1.200\Sdks\Microsoft.NET.Sdk\build\Microsoft.PackageDependencyResolution.targets(327,5): error : Assets file 'F:\Users\GQHH9006\Mes Documents\Mes textes\prog\MonoAGS_git\Source\Editor\AGS.Editor\obj\project.assets.json' not found. Run a NuGet package restore to generate this file.
C:\Program Files\dotnet\sdk\2.1.200\Sdks\Microsoft.NET.Sdk\build\Microsoft.PackageDependencyResolution.targets(167,5): error : Assets file 'F:\Users\GQHH9006\Mes Documents\Mes textes\prog\MonoAGS_git\Source\Editor\AGS.Editor\obj\project.assets.json' not found. Run a NuGet package restore to generate this file.
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\Microsoft.Common.CurrentVersion.targets(2106,5): warning MSB3245: Could not resolve this reference. Could not locate the assembly "Autofac". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.
F:\Users\GQHH9006\Mes Documents\Mes textes\prog\MonoAGS_git\Source\Engine\AGS.Engine.Desktop\CSC : error CS0006: Metadata file 'F:\Users\GQHH9006\Mes Documents\Mes textes\prog\MonoAGS_git\Source\AGS.API\bin\Debug\netstandard2.0\AGS.API.dll' could not be found
F:\Users\GQHH9006\Mes Documents\Mes textes\prog\MonoAGS_git\Source\Engine\AGS.Engine.Desktop\CSC : error CS0006: Metadata file 'F:\Users\GQHH9006\Mes Documents\Mes textes\prog\MonoAGS_git\Source\Engine\AGS.Engine\bin\Debug\netstandard2.0\AGS.Engine.dll' could not be found
5>------ Build started: Project: DemoQuest.Desktop, Configuration: Debug|AnyCPU ------
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\Microsoft.Common.CurrentVersion.targets(2106,5): warning MSB3245: Could not resolve this reference. Could not locate the assembly "GuiLabs.Undo". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.
F:\Users\GQHH9006\Mes Documents\Mes textes\prog\MonoAGS_git\Source\Demo\DemoQuest.Desktop\CSC : error CS0006: Metadata file 'F:\Users\GQHH9006\Mes Documents\Mes textes\prog\MonoAGS_git\Source\AGS.API\bin\Debug\netstandard2.0\AGS.API.dll' could not be found
F:\Users\GQHH9006\Mes Documents\Mes textes\prog\MonoAGS_git\Source\Demo\DemoQuest.Desktop\CSC : error CS0006: Metadata file 'F:\Users\GQHH9006\Mes Documents\Mes textes\prog\MonoAGS_git\Source\Editor\AGS.Editor\bin\Debug\netstandard2.0\AGS.Editor.dll' could not be found
F:\Users\GQHH9006\Mes Documents\Mes textes\prog\MonoAGS_git\Source\Demo\DemoQuest.Desktop\CSC : error CS0006: Metadata file 'F:\Users\GQHH9006\Mes Documents\Mes textes\prog\MonoAGS_git\Source\Engine\AGS.Engine.Desktop\bin\Debug\AGS.Engine.Desktop.dll' could not be found
F:\Users\GQHH9006\Mes Documents\Mes textes\prog\MonoAGS_git\Source\Demo\DemoQuest.Desktop\CSC : error CS0006: Metadata file 'F:\Users\GQHH9006\Mes Documents\Mes textes\prog\MonoAGS_git\Source\Engine\AGS.Engine\bin\Debug\netstandard2.0\AGS.Engine.dll' could not be found
========== Build: 0 succeeded, 5 failed, 0 up-to-date, 0 skipped ==========

[close]
 

Crimson Wizard

#47
Quote from: Monsieur OUXX on Mon 07/05/2018 23:08:54
I want to create a copy of "Demo" to create a variation of it for my own test purposes. I don't understand if that's the right way to do. After I copy and paste the "Demo" folder and its contents, and rename that copy "Demo2", Visual Studio seems to ignore it. How am I supposed to proceed anyway? Is it like "one instance of MonoAGS = one game" or "one instance of MonoAGS = several potential games"?

What do you mean by "Visual Studio ignore it"? Is the new project added in solution, or you only copied folder on disk? When you build, do you build particulary that new project, rebuild all, or else? Before you try to run it, did you set "active project" in the solution tree?

I feel like this is rather a question of using VS. MonoAGS games are no different from any other project or solutions. You may have any number of game projects in one solution. This is what I have in my repository btw.

Also, you do not even have to have engine sources in your solution. You may create a solution only for game projects, and supply prebuilt MonoAGS DLLs for them, setting up the References in project settings. That is probably how regular users will be using MonoAGS after its released (because they would not want to modify engine by mistake).




Quote from: Monsieur OUXX on Mon 07/05/2018 23:08:54
What's annoying me right now is a design question : I'd like to keep my "FakeAGS" in the MonoAGS solution, to benefit from neighbour sources/autocompletion and easy testing, but if I understand correctly it has to be in an entirely different solution/repo to benefit from MyHub's auto build and push. Correct?

Did not understand the part about "MyHub's auto build and push", probably that has something to do with NuGet? will ignore that for now.

If I understood correctly, what you are going to do is not supposed to become a part of MonoAGS source, but a separate thing for which you just want to have engine source nearby?

In such case the best way IMHO is to create a new blank repository for your project, and include MonoAGS source as submodule.
Again, you may check my games repository, the VS solution there includes both my games AND MonoAGS, but MonoAGS comes as a submodule directly from tzach's repo, and even if I change something there by mistake I won't be able to occasionally push it back to his (it simply won't let me).

Submodule also lets you precisely control the version of code you are using. I.e. if tzachs pushes breaking changes to MonoAGS, your submodule may still refer to older version until you are ready to upgrade.

Git submodules are actually great thing to link various project sources (libraries etc) together without actually copying all of them into one place. They may require a bit of patience to learn to work with, but that's totally worth it.

Monsieur OUXX

#48
Quote from: Crimson Wizard on Tue 08/05/2018 01:47:38
I feel like this is rather a question of using VS.
Yes and no. It is, because for some reson the "build manager" had disappeared from the VS GUI until I managed to build the solution at least once. It was making me very confused.
So now that it's back, I can enable or disable the building of individual projects inside the solution. that's where my understanding of MonoAGS was insufficient. I wasn't sure if MonoAGS was referenced in the game as a separate, pre-built DLL, or if the game was built directly on top of MonoAGS (the whole thing being built as a single project). Now it seems obvious but yesterday it was way past midnight (roll)



Quote from: Crimson Wizard on Tue 08/05/2018 01:47:38
Did not understand the part about "MyHub's auto build and push", probably that has something to do with NuGet?
Yes. The whole purpose of NuGet is that it connects to your GitHub sources and builds the DLL project by itself, making it available online. then on the other end you have another project that needs that DLL, but instead of being physically present and referenced in your project, you reference a "NuGet" package that gets re-downloaded when needed (when the DLL has been modified). You can see it as a DLL being hosted in the cloud.


Quote from: Crimson Wizard on Tue 08/05/2018 01:47:38
If I understood correctly, what you are going to do is not supposed to become a part of MonoAGS source,
yes because I feel like its lifespan will be short (until the rest of MonoAGS arrives) and that its coding quality will not meet the standards of MonoAGS.

Quote from: Crimson Wizard on Tue 08/05/2018 01:47:38
In such case the best way IMHO is to create a new blank repository for your project, and include MonoAGS source as submodule.
Yes, now that I understand that MonoAGS is just a DLL, that's the way to go. Or at least, it should be when MonoAGS becomes stable.
I'm still hesitating because part of my work will be to extract hard-coded things from the demo game and turn them into some sort of generic library to simplify some tasks, and I feel like tzachs might want to get some of that back for MonoAGS. If it's a separate repo, it might be a pain to recover and integrate that code. Damn.

I didn't know about submodules though. I'll read more about them. Maybe they're the solution to my questionnings. Thanks!
 

Crimson Wizard

#49
Quote from: Monsieur OUXX on Tue 08/05/2018 12:33:51
I'm still hesitating because part of my work will be to extract hard-coded things from the demo game and turn them into some sort of generic library to simplify some tasks, and I feel like tzachs might want to get some of that back for MonoAGS. If it's a separate repo, it might be a pain to recover and integrate that code.

So, you also want to make changes to DemoGame in MonoAGS repository?

There actually may be following solution:

1) Create a fork of MonoAGS on github; not just a local clone on your computer, but full repository (unles you already did that).
Keep that fork clear from any unnecessary things, like test games, etc, only stuff required to sync with tzach's MonoAGS.

2) Create a completely separate repository for your "template" project. That repository should only have your own project, plus include your fork of MonoAGS (not tzach's) as a submodule.

When you work, and want to modify DemoGame, you do this:

* create a branch , e.g. "demogame-refactor" in the MonoAGS fork.
* in the Template repo, your submodule of MonoAGS should link to that "demogame-refactor" branch.
Now, whenever you make changes to DemoGame code itself, you may actually commit these changes in this special branch, and push to your remote on GitHub.
After you complete some stage, you go to GitHub, and suggest this branch as a pull request from your fork into main MonoAGS repository. That will bring the changes you made to DemoGame (and only them) to the main MonoAGS.

Sorry if that is confusing, I may later expand the explanation (with pictures :tongue:) when have more spare time.

Monsieur OUXX

That's pretty clear; even though each additional step from me actually starting to code makes me lose a little bit of steam ;) But that's not your problem, only mine.

Is there an easy way to create the submodule? First of all: should it be done on the github online gui or locally in my repo (with the .gitmodules file?). Then : how should I proceed? Create the subfolder first? Run a git command that actually does it?
 

Crimson Wizard

#51
Quote from: Monsieur OUXX on Tue 08/05/2018 13:43:23
Is there an easy way to create the submodule? First of all: should it be done on the github online gui or locally in my repo (with the .gitmodules file?). Then : how should I proceed? Create the subfolder first? Run a git command that actually does it?

Submodule is a part of repository configuration, and so should be created locally. Submodule registration (and every other update of it) will become a "change" which should then be staged, commited and pushed as any other change in the source.

You only need to create subfolder yourself if you are going to put submodule inside nested folders. The last subfolder is always created by git. In other words, if you want submodule as a folder in root of your repository, you do not need to create anything on your own.

What OS you are working on, and do you use any GUI program to work with git? On Windows I am using mainly GitExtensions, which let me avoid using console most of times. (There may be others)
I do not remember git commands by heart, but there is documentation: https://git-scm.com/docs/git-submodule
Also, the documentation for creating .gitmodules file which is submodule configuration: https://git-scm.com/docs/gitmodules

IIRC to work with submodule changes you need to simply enter the submodule directory. Submodule has its own commits, separate from your "main" repository contents (because submodule is a clone of another repo). So if you are making changes to submodule code, you need to:
1) first commit and push changes in submodule.
2) then make commit in the parent repository, which will include "submodule update". This will record the fact that your repo now links to the newest commit in submodule.

Think of it as of modifying two repositories while having both in same place.

tzachs

#52
Quote from: Monsieur OUXX on Mon 07/05/2018 23:08:54
I've created my new local branch but I fail to publish it to the remote repo.
So it sounds like you didn't create a remote repo. You can create a a remote repo from the console by doing "git remote add" or directly from github by clicking on the branches drop-down and then click on "create new branch". However you can't do this from my repository as you don't have permissions. That's why, as CW said, you need to fork first.
Also, as you're console-phobic (like me, btw) you can do it without using the console:
1. Click the fork button on my repository to create your own repository.
2. Create a new remote branch on your repository from the branches drop-down in Github.
3. Clone that remote branch directly from Visual Studio's Team Explorer. You can also commit and push directly from visual studio, no console or third party GUI required (at least not for the basics).

Quote
Then I've added a ".Net Core library" project tot he solution.
I don't think that would work (I don't know if mono will be able to run a dot net core project). What you want is to create a DotNet Standard library -> this then works with both  mono and dotnet core.

Quote
I'm in the process of creating the feed : https://www.myget.org/feed/Packages/fakeags
I wasn't proposing that you'd create your own feed, but rather push your package(s) to the community feed I created already. Each feed can host multiple packages, so having all AGS-related packages in one feed will make it easier for people to find stuff. The editor will show packages from that community feed so that's where you'd want to push your package.

Quote
I'm reading this : https://weblogs.asp.net/bsimser/automatically-publishing-nuget-packages-from-github

What's annoying me right now is a design question : I'd like to keep my "FakeAGS" in the MonoAGS solution, to benefit from neighbour sources/autocompletion and easy testing, but if I understand correctly it has to be in an entirely different solution/repo to benefit from MyHub's auto build and push. Correct?
I think if you publish your nuspec (that's the file that's created when you build your project for nuget) then (if I understand correctly) MyGet will pick it up for your nuget so it might work.
Btw, I just tried it on MonoAGS without having a nuspec, and it seemed to create a package per project. I'll need to create a nuspec to have multiple projects in the same package.

EDIT:
Quote
I'm still hesitating because part of my work will be to extract hard-coded things from the demo game and turn them into some sort of generic library to simplify some tasks, and I feel like tzachs might want to get some of that back for MonoAGS. If it's a separate repo, it might be a pain to recover and integrate that code. Damn.
As long as your repository is public (and with a permissive license) it's not going to be a problem for me to take your code if I need it, so don't worry about it.

cat

Quote from: tzachs on Mon 07/05/2018 21:39:32
"To run the unit tests, please install the NUnit 2 Test Adapter (available from Visual Studio, tools menu -> Extensions and Updates... -> Online)." (from the readme)
Oh, I completely missed that readme. I just read the github.io documentation. Maybe you should add the info about test runner also to the "Getting Started" section there.
Anyway, tests are running now.

About that git/submodule thing:
I plan to port one of my games to MonoAGS for fun. How should I handle this in Git? Create a new repository somewhere else for the game and then include it in the solution? Or should I do this submodule thing?

tzachs

Quote from: cat on Tue 08/05/2018 20:34:23
Oh, I completely missed that readme. I just read the github.io documentation. Maybe you should add the info about test runner also to the "Getting Started" section there.
Anyway, tests are running now.
Maybe, the thing is though that the github.io documentation is intended for game developers and the readme is intended for MonoAGS developers. Running the tests is not something that game developers should really care about, which is why I didn't put it there.

Quote from: cat on Tue 08/05/2018 20:34:23
About that git/submodule thing:
I plan to port one of my games to MonoAGS for fun. How should I handle this in Git? Create a new repository somewhere else for the game and then include it in the solution? Or should I do this submodule thing?
You can do both. I think that the main advantage of the submodule is that it allows you to more easily update to a new version (or to restore to an older version), and easier to see which version you're actually running against. The disadvantage is that it's another tool that you need to learn and occasionally shout WTF at (it is part of git, after all, being intuitive was not part of its original goal).
Note that if you do the submodule thing, it's not instead of creating a repository for your game, it's about how you link from your game repo to MonoAGS.

cat

Quote from: tzachs on Tue 08/05/2018 20:54:16
Running the tests is not something that game developers should really care about
Au contraire! Especially for developing templates/modules or non-adventure games testing would be very helpful. Maybe not running the engine tests, but the DemoQuest could provide some examples for actual gameplay tests.

Quote
Quote from: cat on Tue 08/05/2018 20:34:23
About that git/submodule thing:
I plan to port one of my games to MonoAGS for fun. How should I handle this in Git? Create a new repository somewhere else for the game and then include it in the solution? Or should I do this submodule thing?
You can do both. I think that the main advantage of the submodule is that it allows you to more easily update to a new version (or to restore to an older version), and easier to see which version you're actually running against. The disadvantage is that it's another tool that you need to learn and occasionally shout WTF at (it is part of git, after all, being intuitive was not part of its original goal).
Note that if you do the submodule thing, it's not instead of creating a repository for your game, it's about how you link from your game repo to MonoAGS.
I WTF git everytime I need to do anything else besides the regular branch/commit/push/tag. Maybe I'll give it a try nonetheless.

Monsieur OUXX

#56
Obsolete talk : @tzachs I did not create a remote repo since I cloned and branched from your repo. But since then I've changed strategy (with my own repo embedding MonoAGS as a submodule). In the future you should think of a way to allow contributions, though (EDIT: that you have already, when you explained how to do a pull request in your CONTRIBUTION file).

Up-to-date talk : @tzachs : I'm giving up on MyGet for now because it is out of my reach. I'm doing what CW suggested : a submodule. I've created two repos : one for FakeAGS (where I have a submodule to MonoAGS) and one for "DemoQuest2" (where I have two submodules : one to MonoAGS and one to FakeAGS -- side note: I don't know if it is necessary to have both or if MonoAGS is implicitly included when I include FakeAGS).
 

Crimson Wizard

#57
Quote from: Monsieur OUXX on Tue 08/05/2018 23:38:33
I did not create a remote repo since I cloned and branched your repo. But since then I've changed strategy (with my own repo embedding MonoAGS as a submodule). In the future you should think of a way to allow contributions, though.

There is already a way to do contributions to any github project, it's called "pull requests", and it requires to fork original repository to your own remote repository on github.

https://help.github.com/articles/about-pull-requests/

How does this work in short: you push changes to your remote, then go to your page on github and press "new pull request" button. There you choose name of your branch that contains changes and name of tzach's branch where you'd like to push them, then enter some description (optional). When you submit the form, tzachs will have your request appear as a new "issue" thread (sort of).

Monsieur OUXX

#58
Yup sorry : I updated my post since.

New question: how would I add a reference to a project present in a submodule? Do I add a reference to the Assembly, or do I add a reference to the Project (VS lets us do both)? In both cases, should I just browse to the corresponding submodule subfolder (and point to the .vsproj file in one case or .dll file in the other case)?
 

tzachs

You can do both, but I would recommend on adding a reference to the project. You can have MonoAGS projects as part of your solution, and then you don't need to browse to the sub folder when adding a project reference, it would appear in your list of projects.
If you add a reference to a dll however, then yes, you'll need to browse to the location of the dll file.

The advantage of adding a project reference (and having it in your solution), is that if you change the code to your version of MonoAGS and then run your project, it will automatically compile both.

Monsieur OUXX

#60
I'm seeing interesting things in AGSSplashscreen.cs :

About Tweens :
Question 1 : If I understand the code correctly, you can have tweens that do not update automatically, but instead you let them give you a dummy function (_visitTween) when you create them, and then it's your responsibility to call that function whenever you want?
Question 2 : Is there a way to let the Tweens do their thing without having to call that function? (in a normal context where the game is not busy loading resources, like it's the case in the splash screen). I suppose yes, by calling "Run" instead of "RunWithExternalVisit".

About onRepeatedLyExecute :
I see that you actually call it yourself (insteads of letting the game engine do it automatically), by making the function call itself recursively every Task.Delay(5).
Question 3: Isn't there a risk that the recursive calls stack explodes after some time? Or am I being a dinosaur for even thinking that it's still (ever was) a thing?
 

tzachs

Quote from: Monsieur OUXX on Wed 09/05/2018 11:41:30
Question 1 : If I understand the code correctly, you can have tweens that do not update automatically, but instead you let them give you a dummy function (_visitTween) when you create them, and then it's your responsibility to call that function whenever you want?
You understood correctly.

Quote from: Monsieur OUXX on Wed 09/05/2018 11:41:30
Question 2 : Is there a way to let the Tweens do their thing without having to call that function? (in a normal context where the game is not busy loading resources, like it's the case in the splash screen). I suppose yes, by calling "Run" instead of "RunWithExternalVisit".
Right again.
In case you missed it, there's a few dozens of built in tweens, and they are implemented as a one-liner using Tween.Run: https://github.com/tzachshabtay/MonoAGS/blob/master/Source/Engine/AGS.Engine/Misc/Tweening/Tweens.cs

Quote from: Monsieur OUXX on Wed 09/05/2018 11:41:30
About onRepeatedLyExecute :
I see that you actually call it yourself (insteads of letting the game engine do it automatically), by making the function call itself recursively every Task.Delay(5).
Question 3: Isn't there a risk that the recursive calls stack explodes after some time? Or am I being a dinosaur for even thinking that it's still (ever was) a thing?
You're not a dinosaur, but there's no risk (I think), because it's using async which means it's not a direct continuation of the call stack (every time the logic continues after Task.Delay it's a new stack).

Monsieur OUXX

#62
My roadmap is as follows :
(IMPORTANT: I'm not trying to write a AGS-->MonoAGS converter, I'm just trying to have something that produces a basic game as fast as possible even without an actual Editor in MonoAGS)

1) I was going to write a small program that splits game.agf into xml fragments (definitions files) carefully organized into file-system subfolders, but then I got lazy when I realized that I have no idea how to read the acsripte file. So I got lazy and instead, for now, I'll export a game with the XAGE exporter plugin and see what files structure is produces. Maybe a combination of both methods. Anyway, for now, the quicker the better.
2) Write a few loader classes (factories, really) that load these XML fragments into configuration classes and then construct the corresponding classes (Character, Room, whatever).
3) Write a set of wrappers implementing ICharacter, IRoom, etc. that will perform the most basic initialization tasks (from the configuration files mentionned above), and, more interestingly, add a few overridable methods (the most obvious being : "RepeatedlyExecute") so that all a complete MonoAGS newbie has to do is to make their classes (Rooms, Characters, etc.) inherit from those classes. Then they will know instantly where to add custom code. I know it's not ideal (or possible) to make a MonoAGS game work exactly like an AGS game, but as I said the goal here is to have a prototype game as quickly as possible with as little hard-coded script as possible. From my perspective, the more code hidden under the hood (for a start), the better.

==========

Question 4: what core feature does not work in MonoAGS? Does save/load work? That's super duper important and that's the most difficult task. I would be pretty pissed off if I spent several months developing in MonoAGS only to realize that the difficulty of Save/load implementation was underestimated and the project stalled.

Question 5 : is there a more natural way of implementing "RepeatedlyExecute" than the one relying on recursive call (which is targetting specifially the splash screen, that is a room with very unstable framerate)? I've seen in one of the source files that you issue a warning about Repeatedly Execute, that might cause an infinite loop of calls/dependencies if not used properly. Can you produce a simple example of : a) such infinite loop issue, b) a proper way of doing things?
The naive, dirty approach that comes to mind would be for the scripter to define an arbitrarily stack storing the order in which to call the repeatedlyExecute method of each object, just like scripts in AGS can be moved up and down and that defines the order of execution.

=================

I would suggest to make the help articles (those ones : https://github.com/tzachshabtay/MonoAGS/tree/4f0189c1bebe15b4d36a0e8c34dea6c5f0120399/Docs/articles ) easier to find.
When you're here, you have no idea that they exist : https://github.com/tzachshabtay/MonoAGS/tree/4f0189c1bebe15b4d36a0e8c34dea6c5f0120399
When you're here, either : https://github.com/tzachshabtay/MonoAGS/blob/4f0189c1bebe15b4d36a0e8c34dea6c5f0120399/Docs/index.md
When you're here, you still don't know that they exist : https://tzachshabtay.github.io/MonoAGS/
And here either : https://github.com/tzachshabtay/MonoAGS/blob/4f0189c1bebe15b4d36a0e8c34dea6c5f0120399/Docs/articles/getting-started.md

I know I've stumbled upon a page where they were listed on the left, but I cannot find how to go back to that page.
 

tzachs

Quote from: Monsieur OUXX on Wed 09/05/2018 15:18:04
Question 4: what core feature does not work in MonoAGS? Does save/load work? That's super duper important and that's the most difficult task. I would be pretty pissed off if I spent several months developing in MonoAGS only to realize that the difficulty of Save/load implementation was underestimated and the project stalled.
Save/Load game does not work now. I don't think I'm underestimating the task, as I've never given an estimation: I have no idea how long it's going to take to get it right. Same goes for having a complete editor.
Those are both very complicated things to get done right and I expect they will come through several iterations until they will perform reliably and be stable.
Note though, that the fact that built in save/load doesn't work does not mean you can't roll out your own. Depending on your game, specific save/load systems might be much easier to create than a generic works-for-everyone system: especially if you do saved checkpoints, which would be very easy (relatively) to implement.

Other core features (that I know of) from AGS which are not implemented yet: Object.Solid (characters will walk through each other), playing videos, text parser, translations, lip syncing, non 32-bit games (and color palettes).
Also you can see missing APIs in the cheat-sheet: https://tzachshabtay.github.io/MonoAGS/articles/ags-cheat-sheet.html#api-comparisons

Quote from: Monsieur OUXX on Wed 09/05/2018 15:18:04
Question 5 : is there a more natural way of implementing "RepeatedlyExecute" than the one relying on recursive call (which is targetting specifially the splash screen, that is a room with very unstable framerate)? I've seen in one of the source files that you issue a warning about Repeatedly Execute, that might cause an infinite loop of calls/dependencies if not used properly. Can you produce a simple example of : a) such infinite loop issue, b) a proper way of doing things?
The naive, dirty approach that comes to mind would be for the scripter to define an arbitrarily stack storing the order in which to call the repeatedlyExecute method of each object, just like scripts in AGS can be moved up and down and that defines the order of execution.

You can subscribe to repeatedlyExecute from the game events: "game.Events.OnRepeatedlyExecute.Subscribe(onRepeatedlyExecute);".
I don't remember any warning about an infinite loop, the docs for this event have warnings about not to do slow operations or intensive memory allocations from repeatedly execute (same warnings apply to classic AGS as well) so maybe that's what you were referring to? Those same docs also give good/bad examples for those issues: https://tzachshabtay.github.io/MonoAGS/api/AGS.API.IGameEvents.html#AGS_API_IGameEvents_OnRepeatedlyExecute

Quote from: Monsieur OUXX on Wed 09/05/2018 15:18:04
I would suggest to make the help articles (those ones : https://github.com/tzachshabtay/MonoAGS/tree/4f0189c1bebe15b4d36a0e8c34dea6c5f0120399/Docs/articles ) easier to find.
When you're here, you have no idea that they exist : https://github.com/tzachshabtay/MonoAGS/tree/4f0189c1bebe15b4d36a0e8c34dea6c5f0120399
When you're here, either : https://github.com/tzachshabtay/MonoAGS/blob/4f0189c1bebe15b4d36a0e8c34dea6c5f0120399/Docs/index.md
When you're here, you still don't know that they exist : https://tzachshabtay.github.io/MonoAGS/
And here either : https://github.com/tzachshabtay/MonoAGS/blob/4f0189c1bebe15b4d36a0e8c34dea6c5f0120399/Docs/articles/getting-started.md

I know I've stumbled upon a page where they were listed on the left, but I cannot find how to go back to that page.
So you were looking at the documents on github instead of in the documentation website. The documents in github is the source which triggers the generation of the website.
In the main readme on github you linked to there's a link to the documentation website, it's both in the top of the page and in the bottom of the page.
Here's the link again: https://tzachshabtay.github.io/MonoAGS/index.html
From the documentation website you have a link to the articles and api on the top, and the getting started link (or any article link) have the list of articles in the left.

Monsieur OUXX

#64
I'm very confused because none of the pages you mentionned have any links on the left, nor at the top, nor at the bottom. I only see the article. Maybe it's because they're iframes blocked by my current firewall at work (they have a very restrictive policy).

So anyways, don't spend any more time on that, it's not on you.

Spoiler


[close]

================

About repeatedlyExecute : the "warning" I was talking about is in AGSGame.cs :
Quote
177                 //Invoking repeatedly execute asynchronously, as if one subscriber is waiting on another subscriber the event will 
178                 //never get to it (for example: calling ChangeRoom from within RepeatedlyExecute calls StopWalking which 
179                 //waits for the walk to stop, only the walk also happens on RepeatedlyExecute and we'll hang.
180                 //Since we're running asynchronously, the next UpdateFrame will call RepeatedlyExecute for the walk cycle to stop itself and we're good.
181                 ///The downside of this approach is that we need to look out for re-entrancy issues.
182                 await Events.OnRepeatedlyExecute.InvokeAsync(_repeatArgs);

 

tzachs

Quote from: Monsieur OUXX on Wed 09/05/2018 16:26:36
I'm very confused because none of the pages you mentionned have any links on the left, nor at the top, nor at the bottom. I only see the article. Maybe it's because they're iframes blocked by my current firewall at work (they have a very restrictive policy).

So anyways, don't spend any more time on that, it's not on you.
8-0

Hmm, just to make sure: which browser and version are you using?
Assuming you're running on chrome, if you right-click the page and click inspect, and then switch to the console tab, do you see any errors?

Quote
About repeatedlyExecute : the "warning" I was talking about is in AGSGame.cs :
Ah, that's a comment meant to explain why the engine invokes the function asynchronously (to any future engine developer or a future version of myself), it's not relevant to how a game developer would use the event.

Monsieur OUXX

#66
Quote from: tzachs on Wed 09/05/2018 17:24:42
which browser and version are you using? any errors in the inspector?
IE11, in "non-Edge" mode. Pah, just ignore it, it's either my damn workplace firewall or that shit browser. That might explain how I knew that the articles exist while not being able to remember how I saw them earlier : probably because everything works as expected when I'm at home on Firefox.
 

Monsieur OUXX

#67
I'm facing issues because the injection of dependencies makes some bits of code too abstract for me.
Let me explain what I'm failing to do :
- I want to load some XML files using a custom class of my making.
- For that, I need the Resource Loader (either the FileSystem one, or the other one)
- to get the actual instanciated object, I need the device instance
- All the device instances I see are int he factories, which are constructed automatically by the injection of dependencies (I guess! since I see their contructor get called nowhere in the code).
- But I don't want my class to be one of the built-in factories. I want it to be part of my custom library built on top of MonoAGS.

============

Also, pretty cool Facebook page : https://www.facebook.com/mono.ags
 

Crimson Wizard

#68
Quote from: Monsieur OUXX on Wed 09/05/2018 23:21:14
- But I don't want my class to be one of the built-in factories. I want it to be part of my custom library built on top of MonoAGS.

I may not understand something from your intentions, but I believe you could simply require passing reference to factories to your loader constructor, create empty object using factory, then load your XML and fill the object's fields, then return object.

As a very primitive conceptual example:
https://github.com/ivan-mogilko/MonoAGSGames/blob/master/Games/LastAndFurious/Rooms/RoomScript.cs#L48
Code: csharp

protected async Task<IObject> addObject(string name, string gfile, int x = 0, int y = 0)
{
    IObject o = _game.Factory.Object.GetObject(name);
    o.Image = await _game.Factory.Graphics.LoadImageAsync(_roomAssetFolder + gfile);
    o.X = x;
    o.Y = y;
    return o;
}


As you may see, my "object creator" function uses one factory to create an empty object, another factory to load an image, then combines them and sets some parameters, then returns resulting object.

You may expand it to a class that does the same by reading parameters from XML.

EDIT: imho since now these are code-related questions, maybe it would be more convenient if you wrote some prototype, even non -working with dummy functions, as something we could observe and refer to.

Monsieur OUXX

You're using factories that already exist : "Object" and "Graphics". Both already have their resource-loading function : LoadImageAsync. That function, behind the scene, uses the IResourceLoader that has already been automatically provided to that factory.
I want to write my own class that loads resources (XML files) from the disk, and I don't know how to get the IResourceLoader instance.

Are you saying that I should just use "Object"? Isn't that only meant for room objects?

 

Crimson Wizard

#70
Quote from: Monsieur OUXX on Thu 10/05/2018 00:36:03
You're using factories that already exist : "Object" and "Graphics". Both already have their resource-loading function : LoadImageAsync. That function, behind the scene, uses the IResourceLoader that has already been automatically provided to that factory.
I want to write my own class that loads resources (XML files) from the disk, and I don't know how to get the IResourceLoader instance.

Oh.

game.Factory.Resources <-- this is IResourceLoader.

But you could make your loader class have a constructor that requires user to pass IResourceLoader to you, and not worry about that yourself. When they create your loading-from-XML class, they will assign IResourceLoader from the game instance.*

*by "user" I mean the developer who uses your library, ofc. And that may be also you :).

I apologize, if it's still not what you need. I believe it would be better if you draw some chart, or write dummy code to elaborate on your idea. Maybe start with how your loader itself is going to be created in the game, - that may define available options.


Quote from: Monsieur OUXX on Thu 10/05/2018 00:36:03
Are you saying that I should just use "Object"? Isn't that only meant for room objects?

Object class may be used for most things visible on screen, it is used as a parent class for Character, and also for GUI, if I remember correctly. In most cases you may use it and add more Components to expand it further for advanced behavior.

For more bare entities, you may create IEntity, although I do not remember how.

Snarky

I realize you're sticking with "Object" and "Character" from AGS, but is it too late to change that? It makes it much more annoying to discuss scripting when you have the ambiguity with the standard data types.

I like the SCUMM convention where Rooms are Scenes, Objects are Props and Characters are Actors, and would suggest that as an alternative.

Crimson Wizard

#72
Quote from: Snarky on Thu 10/05/2018 08:41:19
I like the SCUMM convention where Rooms are Scenes, Objects are Props and Characters are Actors, and would suggest that as an alternative.

To clarify more, in MonoAGS Object is not a "prop", it is a default class for anything that has position and image. It is not necessarily belongs to the room too.
It's actually more basic than a "Room Object" from AGS, beause it does not have any interactions by default.

Monsieur OUXX

#73
Quote from: Crimson Wizard on Thu 10/05/2018 00:43:48
game.Factory.Resources <-- this is IResourceLoader.
Oh OK. Duh. I'll see how I can work with it.

Quote from: Crimson Wizard on Thu 10/05/2018 00:43:48
But you could make your loader class have a constructor that requires user to pass IResourceLoader to you
Well I'd still be stuck with the same issue, as I'm ultimately the user (I'm making the demo game too) and I don't know where to get the (implemented and constructed) IResourceLoader. See my commant about game.Factory.* below


Quote from: Crimson Wizard on Thu 10/05/2018 00:43:48
I believe it would be better if you draw some chart, or write dummy code
Well all I want to do really is to write a "XML.Load(path)" function, but to make sure that it uses the abstract resources system of MonoAGS instead of just hard-coding the reading of the file from the hard drive.


EDIT: dammit, this is just too abstract for me.
Let's take the simple example of how AudioClips are loaded, and now imagine that I want to do the same with an XML file, the only difference being that my classes are in my own library instead of MonoAGS project.

Here is how it's done in MonoAGS :

game.Factory.Sound.LoadAudioClipAsync(path)
  |
   -----> IAudioFactory implementation
            |
             ----->  LoadAudioClip(path)
                       |
                        ---->  loadSoundData(path)
                                |
                                 ----> IResourceLoader (or is it IResourcePack ? I don't even understand) implementation : _loader.LoadResource(path)
                                         |
                                          ---> Finally, the basic file-opening code.

I'm just not good enough to be able to mimic that cleanly (some of the interfaces being in the engine, the other being in the API project), without just writing a function that opens a file from the hard drive and reads it.

I don't even understand how game.Factory.* are populated, when and by who.
 

Crimson Wizard

#74
Quote from: Monsieur OUXX on Thu 10/05/2018 11:17:08
I'm just not good enough to be able to mimic that cleanly (some of the interfaces being in the engine, the other being in the API project), without just writing a function that opens a file from the hard drive and reads it.

Ok, I am a bit confused right now, not quite sure what exactly you want to mimic and why.

But assuming you want to go simple for starters, all you need is a pointer to IResourceLoader, or rather pointer to IGameFactory (that includes a set of all default factories). You library won't, and perhaps should not know where the actual factories are created, they only need to require a pointer to one.

For instance, this is a mockup example of a simple class that creates stuff from XML. User needs to pass IGameFactory instance into constructor.

Code: csharp

public class LoaderThatCreatesAGSObjectsFromXML
{
    IGameFactory _factory;

    public LoaderThatCreatesAGSObjectsFromXML(IGameFactory factory)
    {
        _factory = factory;
    }

    public List<IObject> LoadRoomObjects(string resourceName)
    {
        // get named resource
        IResource r = _factory.Resources.LoadResource(resourceName);
        // parse the stream into XML document
        XMLDoc doc = LoadXMLFromStream(r.Stream);

        // create a list of objects, reading their properties from the doc
        List<IObject> objs = new List<IObject>();
        int count = doc.GetValue("numobjs");
        for (int i = 0; i < numobjs; ++i)
        {
            // create blank object
            IObject newObj = _factory.Object.GetObject("bla");
            // set parameters
            newObj.SomeParam = doc.GetValue("blabla");
            objs.Add(newObj);
        }
        return objs;
    }
}


This class will read named resources using provided abstract IResourceLoader, which was configured by the engine, or game specifically, without knowing (or bothering) where those resources come from (file on disk, zip archive, net connection etc).


And here is a dummy example of using this class in a game:
Code: ags

protected void setupRoom(IGame game, string roomFileName)
{
    LoaderThatCreatesAGSObjectsFromXML loader = new LoaderThatCreatesAGSObjectsFromXML(game.Factory);
    List<IObject> room1objs = loader.LoadObjectsFromXML(roomFileName);
    // do something
}

As you may notice, here the game developer simply gives your class the factories created by the engine.

tzachs

Quote from: Snarky on Thu 10/05/2018 08:41:19
I realize you're sticking with "Object" and "Character" from AGS, but is it too late to change that? It makes it much more annoying to discuss scripting when you have the ambiguity with the standard data types.

I like the SCUMM convention where Rooms are Scenes, Objects are Props and Characters are Actors, and would suggest that as an alternative.
It's not too late to change.
It annoys me too, but I opted for keeping familiarity to AGSers to be higher priority than ambiguity when I think that ambiguity is tolerable (i.e I don't think I actually use the dotnet object anywhere in the code, and the keyword for characters is char). But I agree that it can be confusing when discussing or reading c# general tutorials.
I'm open to change names if there's a majority agreement, although slightly concerned as I think the early adopters represent the more advanced AGSer who might cares less about familiarity than mainstream AGSers.
About the names themselves:
- Room vs Scene: I find scene to be a better name than room too, but there's also no ambiguity here, so Room doesn't actually bother me that much. I'm ok either way.
- Object vs Prop: Like CW said, I'm not sure prop covers all scenarios for object. An object in MonoAGS is something that has a transform (move, scale, rotate), an image/animation, a collider, and can be placed in a room or as a GUI. So all characters and guis are also objects. Some alternative names that come up: "Drawable", "Moveable", "Thing"?
- Character vs Actor: I have a problem with Actor because it has ambiguity with the actor model which is a model used to utilize safe concurrency, and we might choose to use it in the future. Alternative names that I can think of all suck: "Creature", "Person", "Individual"?

@Monsieur OUXX: I'm going to answer your questions to try helping you better understand the inner workings of the engine, though I agree with CW, you don't actually need that, the example he gave is what you should probably do, unless I misunderstood what you want to do.

First of all, any API that you can't find a direct reference to and want to use, you can try resolving it. So:
Code: csharp

using AutoFac;

var resourceLoader = AGSGame.Resolver.Container.Resolve<IResourceLoader>();
var device = AGSGame.Resolver.Container.Resolver<IDevice>();


Although like CW said, resource loader can be found in "game.Factory.Resources" (and device can be found in AGSGame.Device).
The resolver is how the engine gets the concrete implementations injected to it (and also how you can give it different implementations and customize almost everything imaginable), and how the factory is populated.

Quote
IResourceLoader (or is it IResourcePack ? I don't even understand) implementation : _loader.LoadResource(path)
It's resource loader. The resource loader has multiple resource packs to allow loading resources from multiple sources. Currently there's a "file system" resource pack and an "embedded resource" resource pack, but in the future we can have a "get from web" resource pack, "get from ftp" resource pack, etc.

Regarding the actual example CW gave, here's a minor improvement you can make (you might argue that it's not an improvement but at least know you have the option). You can access the game statically with "AGSGame.Game" as well.
So you can provide a default in your class and allow the user not to think about it:
Code: csharp

public class LoaderThatCreatesAGSObjectsFromXML
{
    IGameFactory _factory;
 
    public LoaderThatCreatesAGSObjectsFromXML(IGameFactory factory = null)
    {
        _factory = factory ?? AGSGame.Game.Factory;
    }

    ...


And then you can call it like CW showed, or without giving the factory: "var loader = new LoaderThatCreatesAGSObjectsFromXML();"

Crimson Wizard

#76
EDIT2: Aw, scrap that, there are types that always resolve to a single instance apparently, there is what SingleInstance() is for. :sealed:
This kind of makes things simplier, but only if you know for sure that they are registered as single instance.


EDIT: Oh, and the actual custom implementations are registered like this:
Code: csharp

Builder.RegisterType<MyOwnResourceLoaderClass>().SingleInstance().As<IResourceLoader>();

If you do that, every next IResourceLoader created with the use of Resolver will be actually your class.
TBH I do not know at which point you need to call this command, probably before IGame is created?

Personally, I'd prefer to stay away from this Resolver stuff if possible, because it will affect everything in the engine.

tzachs

Quote from: Crimson Wizard on Thu 10/05/2018 16:00:52
I would like to add, that although indeed you can create a ResourceLoader from resolver, that will be a separate new object, not the one from game.Factory.
That's not true, it will be the same object that the game factory gets, because it's registered by the engine as a single instance.

Quote from: Crimson Wizard on Thu 10/05/2018 16:00:52
TBH I do not know at which point you need to call this command, probably before IGame is created?
If you want to override engine behavior, then yes, you need to do it before IGame is created.

Quote from: Crimson Wizard on Thu 10/05/2018 16:00:52
Personally, I'd prefer to stay away from this Resolver stuff if possible, because it will affect everything in the engine.
Using the resolver for changing behaviors can affect things in the engine, and you need to know what you're doing.
But as for resolving things from the resolver, that wouldn't have an effect (worst case scenario is that you won't be able to resolve something because it's missing a parameter and you'll get an exception immediately).

Crimson Wizard

Quote from: tzachs on Thu 10/05/2018 16:19:01
Quote from: Crimson Wizard on Thu 10/05/2018 16:00:52
I would like to add, that although indeed you can create a ResourceLoader from resolver, that will be a separate new object, not the one from game.Factory.
That's not true, it will be the same object that the game factory gets, because it's registered by the engine as a single instance.

I've got a question, is this single instanceness enforced for an interface somehow? For example, if someone will re-register their own implementation, can they do change it to multiinstance? Because if they may, that would mean that the common/library code cannot rely on interface being single-instanced.

tzachs

It's not enforced (and I don't think it can be enforced).

cat

I'm sure I just missed some documentation somewhere but I can't find it.
I created a new solution and added my game projects as well as Api, Engine and Engine.Desktop projects from the git submodule. But I get an error that autofac is missing. I don't have the packages folder that I have in my other checkout. What do I have to do to get it? It is not checked in, so there has to be some other package management.

tzachs

How did you create your game project?
Did you create a project with visual studio or copy the project from the demo game?
The thing is, the demo game is using an older project format which has some issue where packages from dependencies are not properly copied to your folder.
I already converted the demo game to the new format in one of the dev branches which should resolve the issue, I haven't pushed it to master yet.
So if you copied the project from the demo game, this might be the same issue. You can work around it by either converting your project to the new format, or directing the engine project to compile to the same directory as your game, or manually copy the dll to your binaries folder.
If, however, you created the project using recent visual studio, then I'm not sure what's going on, and I'll need to investigate further (so if you're ok with sending me your project I can take a look).

Monsieur OUXX

Quote from: cat on Thu 10/05/2018 20:47:35
I'm sure I just missed some documentation somewhere but I can't find it.
I created a new solution and added my game projects as well as Api, Engine and Engine.Desktop projects from the git submodule. But I get an error that autofac is missing. I don't have the packages folder that I have in my other checkout. What do I have to do to get it? It is not checked in, so there has to be some other package management.

Because some of the projects have evolved since then and you need to add references to Autofacs and System.ValueTuple (and possibly Guilabs.Undo). These are not mentionned in the docs.
However they are not simple Assemblies/DLLs. They are NuGet packages, so to add them you need to right-click on "References" in Visual Studio, and select "Manage NuGet Packages" (please indicate if this option is not present). Then in the new panel that opens you need to select the "browse" tab, and in the search box type "Autofacs". Once you find the reseult, click on "Install". Do it again for the two other packages.

If you find that they are already installed, then you need to force Visual Studio to re-download them (because it doesn't like sources and packages to be moved around). The simplest way is to delete the ".nuget" folder from your project (not in Visual Studio, on the actual hard drive).
 

Monsieur OUXX

#83
Everything present in the quote below has been resolved by now.
Spoiler

About my issue with loading a resource.
Let's start the simplest way possible : what method should I call to open a single file present on the hard drive? I'm not talking about good old File.Open, Im' talking in the context of MonoAGS (where there's the resources system inbetween me and the files, and I don't know if I'm on a desktop or on an Android device).
Point me to that one single instruction.

Is it simply Game.Factory.Resources.LoadResource(path) ? But then how does the engine know if it's a resource on disk or an embedded resource? Can it be both in one game or is it resoved from the path or...?
EDIT: OK I see it : it's in ResourceLoadder.cs::LoadResource. Any resource that returns null from any resource pack is ignored. So it's definitely the path that tells a "proper" resource from an invalid resource. Could you give an example of path that allows to load from an embedded resource?
EDIT 2 : OK, by using breakpoints I found one : "DemoQuest.Desktop.Assets.Fonts.pf_ronda_seven.ttf". So that's an embedded resource. I don't know how they work. I see the resource in the Solution Explorer at DemoQuest.Assets.Fonts.pf_ronda_seven.ttf (no ".Desktop"). So at runtime the path is updated with the current system running the game. Oh well. I'll deal with that later.
[close]
EDIT 4 : This is actually still extremely confusing to me, because to load the font you call game.Factory.Fonts.InstallFonts("../../Assets/Fonts/pf_ronda_seven.ttf") (which is a physical path in the file system) but then with my breakpoint I see that it's the EmbeddedResourcesPack that ends up doing the job, using the embedded path I mentionned (DemoQuest.Desktop.Assets.Fonts.pf_ronda_seven.ttf). What's the point then?
 

Crimson Wizard

#84
Quote from: Monsieur OUXX on Thu 10/05/2018 22:52:43
Let's start the simplest way possible : what method should I call to open a single file present on the hard drive? I'm not talking about good old File.Open, Im' talking in the context of MonoAGS (where there's the resources system inbetween me and the files, and I don't know if I'm on a desktop or on an Android device).
Point me to that one single instruction.

Is it simply Game.Factory.Resources.LoadResource(path)

Yes.

Quote from: Monsieur OUXX on Thu 10/05/2018 22:52:43
? But then how does the engine know if it's a resource on disk or an embedded resource? Can it be both in one game or is it resoved from the path or...?

The idea is that the user of IResourceLoader does not know, and should not bother about where the resource actually comes from.
Resource loader will look into several places until it finds the resource you asked.

It is up to game developer to configure possible places to look, and their priority.
This is how it's done in DemoGame:
Code: sharp

game.Factory.Resources.ResourcePacks.Add(new ResourcePack(new FileSystemResourcePack(AGSGame.Device.FileSystem), 0));
game.Factory.Resources.ResourcePacks.Add(new ResourcePack(new EmbeddedResourcesPack(AGSGame.Device.Assemblies.EntryAssembly), 1));


This is also like AGS currently works: it first looks for a file in the directory, and then for a file embedded in the game package.

Quote from: Monsieur OUXX on Thu 10/05/2018 22:52:43
EDIT 4 : This is actually still extremely confusing to me, because to load the font you call game.Factory.Fonts.InstallFonts("../../Assets/Fonts/pf_ronda_seven.ttf") (which is a physical path in the file system) but then with my breakpoint I see that it's the EmbeddedResourcesPack that ends up doing the job, using the embedded path I mentionned (DemoQuest.Desktop.Assets.Fonts.pf_ronda_seven.ttf). What's the point then?

This is not the physical path. It is a virtual path in a virtual filesystem. This may be __used__ as a path on disk, relative to game.exe, or as a path inside a ZIP archive. The path may be also converted someway into another form, if particular implementation of resource loading requires it.

Monsieur OUXX

#85
Can you explain how the virtual file system works?
Basic questions:
- is the root folder the execution folder?
- is this file system before or after the resource was loaded? (in other words : is it a path to target a resource, or a path invented after the resource was loaded, made to give us a clue of where it was found?) OK this one is obvious, it's the path before loading, since it's the one you provide to Installfont.
- can you give a correspondance of a path for an embedded resource and this virtual file system? OK, InstallFont anwsers that question too : It turns the virtual path "../../whatnot" into an embedded resource path. I'm still not clear about the correspondance between the very real (and changing) execution folder (which requires to add "../.." to go back to the solution's root folder) and the resources root folder.
 

Crimson Wizard

#86
Oh, ok, you struck out couple questions. The last one is -

Quote from: Monsieur OUXX on Thu 10/05/2018 23:34:25
- is the root folder the execution folder?

Either location of exe, or "current working directory", and TBH that's kind of annoying. I believe there should be a way to configure this.

I had to invent a trick, because path may be different depending on whether you run the game from Visual Studio or from explorer.
What I do is that I pass a part of path as a command line argument when debugging the game, as "../../Assets/". And in game code I assign this argument to a variable called "_baseAssetFolder", which I use to construct resource paths.

By default _baseAssetFolder is just "Assets/", so that you could put Assets folder to same directory where exe is, and run it normally.

My best hopes are that in the end this is what resource loader's implementation will be doing on its own. So that we would have to type just "Images/room.png" instead of "../../Assets/Images/room.png".

cat

#87
Quote from: tzachs on Thu 10/05/2018 21:16:13
How did you create your game project?
I created a new empty solution with VS. I then added a new empty game project and a game.Desktop project from visual studio. I created a local git repo for it and included a git submodule of MonoAGS. Then I added AGS.Api, AGS.Engine and AGSEngine.Desktop to the solution using VS.
When I build the solution, I get the following message:
QuoteSeverity   Code   Description   Project   File   Line   Suppression State
Error   CS0246   The type or namespace name 'Autofac' could not be found (are you missing a using directive or an assembly reference?)   AGS.Engine.Desktop   D:\Daten\MonoAGS\Games\CorneliusCat\MonoAGS\Source\Engine\AGS.Engine.Desktop\AGSEngineDesktop.cs   4   Active
AGSEngine.Desktop has a reference to Autofac, while AGSEngine has Autofac as nuget dependency.

Quote from: Monsieur OUXX on Thu 10/05/2018 22:49:04
Because some of the projects have evolved since then and you need to add references to Autofacs and System.ValueTuple (and possibly Guilabs.Undo). These are not mentionned in the docs.
However they are not simple Assemblies/DLLs. They are NuGet packages, so to add them you need to right-click on "References" in Visual Studio, and select "Manage NuGet Packages" (please indicate if this option is not present). Then in the new panel that opens you need to select the "browse" tab, and in the search box type "Autofacs". Once you find the reseult, click on "Install". Do it again for the two other packages.

If you find that they are already installed, then you need to force Visual Studio to re-download them (because it doesn't like sources and packages to be moved around). The simplest way is to delete the ".nuget" folder from your project (not in Visual Studio, on the actual hard drive).
I assumed that this is nuget related. But didn't know how to tackle it. I now did as you suggested (the broken autofac reference was then replaced by a working one and there is now a newly created packages folder in my solution) and I can compile now.

The question is: Why did I have to do this in my new solution with the git submodule but not in the original checkout of MonoAGS? Because there I magically have the packages folder already and the references work.

Edit: I realised that re-installing autofac did not cause any pending changes in the repo, i.e. just the packages folder was created. When I do a clean checkout, is there a command I can run on nuget to automatically retrieve all missing packages? I think this is the actual step that was missing.
Edit: re-installing autofac did actually cause a change to the submodule, which I of course don't want.

Monsieur OUXX

#88
Quote from: cat on Fri 11/05/2018 09:10:43
The question is: Why did I have to do this in my new solution with the git submodule but not in the original checkout of MonoAGS?
To put it simply: NuGet is black magic ;) Sometimes the packages are considered "up to date", sometimes they need to be "restored" (9 times out of 10 : when you moved a solution or when it's your first build in a newly-downloaded repo). A bit like in the old days when you needed to Clean your VS solution from time to time, for mysterious reasons. (Well I'm sure it's not that mysterious for people who know things, but I'm sadly not one of those).

If I'm not mistaken, NuGet packages are excluded from the commits. That's one of the reasons why they're successful these days. That's by design, so that your commits don't mixup your actual code and the random changes in third-party binary libraries.

So, you ask "how to restore them"? There are some command line instructions that you can perform from the NuGet Console (Tools--> Nuget Packge manager--> Package Manager Console), but then again as I've said before, normally deleting the .nuget folder forces a clean restore. The .nuget folder is just a storage folder where VS puts the packages.
https://docs.microsoft.com/en-us/nuget/consume-packages/package-restore

 

Monsieur OUXX

#89
Quote from: Crimson Wizard on Thu 10/05/2018 23:42:40
You wouldn't have any tips by any chance on how to extend the ResourceLoader to, let's say, detect the list of subfolders

I'm getting a headache trying to do extend some classes functionalities without modifying directly MonoAGS's code. The reason is that tzachs used "private" everywhere instead of "protected"! Is there a specific reason? I thought that nowadays, "protected" was more common than the very punishing "private".
Because of that, I cannot derive any class from the engine's classes. Or if I do, I have to rewrite all the helper methods exactly as they are in the parent class instead of just calling them.
PS: if you read closely all the good practices about "protected" vs "private", people say "member variables should always be private, not protected"... but then they say "it's ok if accessors are protected". So I'd say : make everything but member variables protected.
 

cat

I really don't know what happened to my VS installation. First I had problems with the SDK not installed, and now there is something wrong with nuget. In the options I have Allow NuGet to download missing packages and Automatically check for missing packages during build in Visual Studio checked but it is simply not done during build.

Monsieur OUXX

Quote from: cat on Fri 11/05/2018 10:43:48
I really don't know what happened to my VS installation. First I had problems with the SDK not installed, and now there is something wrong with nuget. In the options I have Allow NuGet to download missing packages and Automatically check for missing packages during build in Visual Studio checked but it is simply not done during build.

Have you deleted .nuget? I know I've said it several times but you've never confirmed that you tried. Sometimes it's not about the package being missing, it's about VS not expecting that specific file (with stuff like the encryption key jumping into the issue). So you need to delete it and force VS to re-download it.
 

cat

#92
.nuget is a checked-in folder of MonoAGS, in my solution I don't even have one. I'm not sure how deleting it would help, besides, the config in there has nothing to do with autofac. I don't have a local .nuget file/folder in my project.

For testing purposes I checked out a clean copy of CW's MonoAGSGames repo and tried to build it. I get the same problem here.

Edit: Another thing I tried: I checked out another clean copy of the original MonoAGS solution. This I can build and run without problems ???

Monsieur OUXX

Quote from: cat on Fri 11/05/2018 12:36:19
.nuget is a checked-in folder of MonoAGS, in my solution I don't even have one. I'm not sure how deleting it would help, besides, the config in there has nothing to do with autofac. I don't have a local .nuget file/folder in my project.

For testing purposes I checked out a clean copy of CW's MonoAGSGames repo and tried to build it. I get the same problem here.


If you don't have the folder it means that the NuGet packages are not there. Have you tried following the steps I described earlier about how to include Autofac and two other packages from the VS interface?
 

cat

#94
I can install Autofac from the nuget manager, but this causes a change in the MonoAGS repository.

Also, could you explain what the difference is between dependencies (as seen in the solution explorer for AGS.Engine) and references (as seen for AGS.Engine.Desktop)?

I'm sorry for so many dumb questions, I haven't been working with C# for a few years now and obviously I'm not up-do-date anymore.

Edit: It might be something related to paths i.e. where the packages folder is created. One of the changes I see in the diff when I install the nuget package is related to the location of the packages folder.

Monsieur OUXX

Quote from: cat on Fri 11/05/2018 12:50:55
I can install Autofac from the nuget manager, but this causes a change in the MonoAGS repository.

Is it a big deal? Are you planning on not only commiting your changes in the engine itself, but pushing them too?
If you just want to change things in the Demo Game, then really create your separate repository (I think it's what you've done).

Quote from: cat on Fri 11/05/2018 12:50:55
Also, could you explain what the difference is between dependencies (as seen in the solution explorer for AGS.Engine) and references (as seen for AGS.Engine.Desktop)?
Conceptually it's different but from your end-user perspective it's pretty much the same thing. From memory, if you right-click it takes you to the same "add reference" dialog anyways.
 

cat

I just edited while you posted. I'm investigating paths now.

It's not about big deal, it's just weird and shouldn't be like that. After a clean checkout during rebuild all resources should be fetched and the solution built.

I have a separate repository for my game and MonoAGS as submodule. In contrast to CW I plan to have a separate repo for each game and not one for them all.

Crimson Wizard

#97
Quote from: Monsieur OUXX on Fri 11/05/2018 09:44:09
You wouldn't have any tips by any chance on how to extend the ResourceLoader to, let's say, detect the list of subfolders

I'm getting a headache trying to do extend some classes functionalities without modifying directly MonoAGS's code. The reason is that tzachs used "private" everywhere instead of "protected"! Is there a specific reason? I thought that nowadays, "protected" was more common than the very punishing "private".
Because of that, I cannot derive any class from the engine's classes. Or if I do, I have to rewrite all the helper methods exactly as they are in the parent class instead of just calling them.

No, I was not investigating that code much.
Question about possible inheritance is something that tzachs should answer, as an author.
Extending game objects is supposed to be done rather using custom components, but idk about other utility classes.

PS. Whan you say "extend ResourceLoader" do you mean actually Loader, or ResourcePack implementation?
Thing is that, if you create your own modification based on one of manager classes, such as ResourceLoader, you will have a hard time keeping in sync with the engine in future, or it will be difficult for users of your library to use it in their games.
If you think that these changes could be useful, maybe suggest them to the engine code? Or, perhaps, think of some interface that engine could use, and you implement.

Monsieur OUXX

Quote from: Crimson Wizard on Fri 11/05/2018 14:20:32
do you mean actually Loader, or ResourcePack implementation?
Well it would actually have to be both : ResourcePack has to be implemnted in as many flavors as there are potential file systems, but then it's really ResourceLoader that you use to start the loading (and it chooses between its resource packs behind the scene, but you're not supposed to really care about that).

Quote from: Crimson Wizard on Fri 11/05/2018 14:20:32
Also, if you think that these changes could be useful, maybe suggest them to the engine code?
Yes, but for now I'd rather priviledge a workflow where I'm 100% in control of what I'm doing, with dirty hacks here and there (quick iterative method). I also want to be as little intrusive as possible. Once I have something that works I can initiate a conversation with tzachs to draw his attention to useful bits of my utility code, and let him pick what he likes. Then I can add it to MonoAGS myself.
 

Crimson Wizard

#99
Quote from: Crimson Wizard on Fri 11/05/2018 14:20:32
Yes, but for now I'd rather priviledge a workflow where I'm 100% in control of what I'm doing, with dirty hacks here and there (quick iterative method). I also want to be as little intrusive as possible. Once I have something that works I can initiate a conversation with tzachs to draw his attention to useful bits of my utility code, and let him pick what he likes. Then I can add it to MonoAGS myself.

Well, what I wanted to say, you could just edit these classes in your copy of MonoAGS code instead of trying to derive from them. Or edit them enough to be able to derive child classes. You may do that in a separate branch (of monoags repository), then keep syncing master branch with tzachs and merging to your custom one (or doing rebase) until you are ready to suggest these changes.

tzachs

Quote from: cat on Fri 11/05/2018 09:10:43
AGSEngine.Desktop has a reference to Autofac, while AGSEngine has Autofac as nuget dependency.
Ah, AGSEngine.Desktop was still using the old project format while AGSEngine was converted to the new format, so it's the same bug I mentioned before, I believe. I fixed it in this branch- can you try pulling from that branch and see if that solves it for you? I'll push to master once you confirm, otherwise I'll try to reproduce during the weekend when I have more time.
Btw, for posterity, this is the dotnet bug I'm referring to, which creates problems when combining old and new project formats in project references.

Quote from: Monsieur OUXX on Thu 10/05/2018 22:49:04
Because some of the projects have evolved since then and you need to add references to Autofacs and System.ValueTuple (and possibly Guilabs.Undo). These are not mentionned in the docs.
You shouldn't need to add those as references to your game project (unless you use those directly), that was a result of that bug too (I think).

Quote from: cat on Fri 11/05/2018 09:10:43
The question is: Why did I have to do this in my new solution with the git submodule but not in the original checkout of MonoAGS? Because there I magically have the packages folder already and the references work.
I think the difference is that in MonoAGS, the engine projects and the demo project are configured to be compiled to the same folder. So the demo game happened to work because the engine project copied the dependency to its own folder which happened to be the demo folder too.
In your setup, however, I'm guessing both projects are configured to be compiled to different folders so it didn't work. I might change the demo quest to compile to a different folder so that I would encounter this bug sooner if it reoccurs.

Quote from: Monsieur OUXX on Fri 11/05/2018 09:44:09
I'm getting a headache trying to do extend some classes functionalities without modifying directly MonoAGS's code. The reason is that tzachs used "private" everywhere instead of "protected"! Is there a specific reason? I thought that nowadays, "protected" was more common than the very punishing "private".
Because of that, I cannot derive any class from the engine's classes. Or if I do, I have to rewrite all the helper methods exactly as they are in the parent class instead of just calling them.
PS: if you read closely all the good practices about "protected" vs "private", people say "member variables should always be private, not protected"... but then they say "it's ok if accessors are protected". So I'd say : make everything but member variables protected.
Having everything protected and not private will encourage people to extend via inheritance, which I (and many others) don't like. Inheritance should be used sparingly, I believe, as a lot of time it acts as an anti pattern. This is why MonoAGS tries to encourage composition over inheritance.
Note that in Java when no access modifier is declared the default is protected (same as what you want and I don't). The c# designers had the same opinion as me, that this is a mistake, and so in c# the default modifier is private.

That said, I'm not ruling out inheritance completely, so if you can explain which member you wanted to see as protected and why (i.e what are you trying to do exactly), we can discuss specific use-cases.

Crimson Wizard

#101
Quote from: tzachs on Fri 11/05/2018 16:06:34
That said, I'm not ruling out inheritance completely, so if you can explain which member you wanted to see as protected and why (i.e what are you trying to do exactly), we can discuss specific use-cases.

Imo that is question #1: what is the actual purpose of changes; because particular modification may conflict with the concept of the engine, and there could be other existing or planned methods to achieve same result.

For that reason I've been asking Monsieur OUXX what he is trying to do several times, but he does not want to tell :(.

PS. Sorry, for complaining. I understand that it is not right to demand the answer, but really, if we are discussing the development and usage of the engine here, this explanation would make things so much easier.

cat

#102
Quote from: tzachs on Fri 11/05/2018 16:06:34
I fixed it in this branch- can you try pulling from that branch and see if that solves it for you?
Awesome, it works! Thank you so much!

Quote from: tzachs on Fri 11/05/2018 16:06:34
Having everything protected and not private will encourage people to extend via inheritance, which I (and many others) don't like. Inheritance should be used sparingly, I believe, as a lot of time it acts as an anti pattern. This is why MonoAGS tries to encourage composition over inheritance.
We used to say about a college: "Some people use inheritance as a weapon" ;)

Monsieur OUXX

#103
Quote from: Crimson Wizard on Fri 11/05/2018 16:21:03
For that reason I've been asking Monsieur OUXX what he is trying to do several times, but he does not want to tell :(.
Sorry I felt like my plan was crystal clear since I keep repeating what I want to do (with poor words). I want to add an extra method to ResourcesLoader that loads resources recursively. It scans all subfolders aof the Assets folder, and it also checks if there is an XML file in it.
Since all the classes involded have all their helper functions private, then (even with composition) I have to pretty much reprogram the whole system alongside the original one, by duplicating 95% of its code and changing just 5%. Don't you think it's a pity?

You can see how I've done it here : https://github.com/jeancallisti/fakeags/blob/master/FakeAGS/FakeAGS/Engine/FakeAGSResourcePack.cs
(follow the call stack of LoadAllDefinitionsRecursively )
 

tzachs

#104
Ah, ok, I missed the fact that you want to load recursively.
So, if I understand correctly, you want this method: "public List<IResource> LoadResources(string folder)", to be changed to "public List<IResource> LoadResources(string folder, bool isRecursive)". Right?
Yes, I think that can be valuable.
You haven't mentioned though which member you want to see protected and how it would help you to write the recursive scanning.

I'm also not sure what you mean by "it also checks if there is an xml file in it". Is this about the filename or about verifying the contents? Do you want a boolean true/false about a folder or the list of xml files in that folder?
If it's about the filename, then you can do:
Code: csharp

var resources = loader.LoadResources(myFolder);

bool hasXml = resources.Any(r => r.ID.EndsWith(".xml"));
//or:
List<IResource> xmlResources = resources.Where(r => r.ID.EndsWith(".xml")).ToList();

And if it's about validating the contents, then you can create your validation code and filter based on that:
Code: csharp

private bool isValidXml(IResource resource)
{
   //read the stream and validate.
}

var resources = loader.LoadResources(myFolder);

bool hasXml = resources.Any(isValidXml);
//or:
List<IResource> xmlResources = resources.Where(isValidXml).ToList();


EDIT: Ah, hold on, I see you added an example, let me take a look.

Ok, I understand what you want to do now: load recursively only files matching a specific pattern.
I still don't know what member do you want to be protected to help you write that.

Crimson Wizard

#105
Quote from: Monsieur OUXX on Fri 11/05/2018 17:03:58I want to add an extra method to ResourcesLoader that loads resources recursively. It scans all subfolders aof the Assets folder, and it also checks if there is an XML file in it.

Ohhhhh! Yes, I also missed the idea to load them recursively. Now I understand this. :)


Idk if this suggestion holds any value, but an alternate approach / temporary workaround may be to have a "master" xml file that would hold a list of paths to other xmls. In other words, this will be explicit vs implicit asset loading.


EDIT
@tzachs, BTW, do you think it may make sense to provide a "file tree" interface to iterate asset entries, instead of call "load" for them? (Not sure if it actually always loads for real though).
In other words, instead of (or along with) IResourceLoader, have something like IResourceTree with dictionary of all assets and possibility to request their loading.

For instance, in AGS the engine has a full list of all assets in the package (not loaded to memory, just a list of their names and some info). It's not available in script API, but could be exposed there also in theory.

Hmm, I'd imagine this would need "Rescan" function, and listen for disk changes, because files on disk may get modified. Well, ones in package may change also, if its something like zip archive.

Monsieur OUXX

Quote from: Crimson Wizard on Fri 11/05/2018 18:11:52
an alternate approach / temporary workaround may be to have a "master" xml file that would hold a list of paths to other xmls
Game designers have no time to lose ;) Implicit all the way! Yaaaay! ;)


Quote from: Crimson Wizard on Fri 11/05/2018 18:11:52
@tzachs, if resources are actually always loaded for real when calling "Load"
I wasn't sure either, so I digged and I actually think they are. So my approach of doing some sort of "pre-load" by just searching the definition files (xml files) might come handy for memory management too. In other words: I know that there's something there on disk and I know what it is from the XML file, but I can load or unload it at will.



Quote from: Crimson Wizard on Fri 11/05/2018 18:11:52
@tzachs, BTW, do you think it may make sense to provide a "file tree" interface to iterate asset entries, instead of call "load" for them?
I actually just did that with my AssetDefsFactory.Process(wildcard). Internally it's not a tree but that's the idea.


You can see more from my repo by paying attention to that bit :
Code: ags


                List<IAssetDef> gameAssetsDefs = new AssetDefsFactory(game, resources).Process("*/Game/*");
                var roomsAssetsDefs = new AssetDefsFactory(game, resources).Process("*/Rooms/*");

                string customRes = gameAssetsDefs.First().GetValue("CustomResolution");
                Debug.WriteLine($"Debug : Custom resolution is : '{customRes}'");

(well, for the game settings it doesn't load anything deeper than root level, but for rooms it will)

Please note though that this code is horrible and slow. But it is an embryo of those concepts.
 

tzachs

Quote from: Crimson Wizard on Fri 11/05/2018 18:11:52
@tzachs, BTW, do you think it may make sense to provide a "file tree" interface to iterate asset entries, instead of call "load" for them? (Not sure if it actually always loads for real though).
In other words, instead of (or along with) IResourceLoader, have something like IResourceTree with dictionary of all assets and possibility to request their loading.
Yes, it definitely makes sense. I've added an issue for this here. We'll need to think of how the API will look and how it will be integrated with the current API, and how to integrate the "re-scan" with hot reloading.
I'll try to think about it more (and look at Monsieur OUXX's implementation) after finishing up my current work.

Monsieur OUXX

By the way CW I made a mistake when I said that all the resources are loaded. What happens is that all the files get open, as Streams. But not necessarily read. Each resource as a handle to a file. I still don't know how it's supposed to be handled cleanly outside of the built-in resources like Fonts, etc. For now I'm leaving the streams open when reading my XML files.
 

Monsieur OUXX

#109
Something is bugging me because I wrote nice code based on ResourcePacks to load the XML file that defines the title, width and depth of the game... But then I realized that game.Factories.Resources is not populated until after calling game.Start (to which you must pass the settings).

You need the resources to get the settings to call game.Start, and you need to call game.Start to get the resources to get the settings. >:(

Oh well. At least my construct works for everything else but the early initialization.
 

tzachs

You can change the title and window size after the game started (but not the virtual resolution, sorry about that): game.Settings.Title = "My title";

Monsieur OUXX

Right now I'm struggling understanding how the rooms work! Again I'm baging my head against the wall because of all the asbstraction.

Can you confirm that this is the lifecycle of a room :

Code: ags

CustomRoom customRoom = new CustomRoom(player) //by the way wouldn't it be more efficient to provide "game" straight away?
Task<IRoom> roomTask = customRoom.LoadAsync(game)
--->      IRoom room = factory.Room.GetRoom(_roomId, 20f, 310f, 190f, 10f); //Creates some dummy room object?
         //...fill all the room's attributes

waitForRoom(game, roomTask )
--->     game.State.Rooms.Add(room)


And then at any time later in the game, whenever something happens that might have broken a pointer to a room (like restoring a saved game) :
Code: ags

_updatedRoomReference = Rooms.Find(_game.State, _oldRoomReference); //This just looks up the room with the same ID as the old reference


 

tzachs

Yes, that's the lifecycle of a room.

Quote
//by the way wouldn't it be more efficient to provide "game" straight away?
I wouldn't say more efficient, but more aesthetically pleasant, yes.

Quote
And then at any time later in the game, whenever something happens that might have broken a pointer to a room (like restoring a saved game) :
Right, only restoring a saved game is the only thing that can break that pointer.

Crimson Wizard

#113
In the past I wanted to suggest to split concept of "room item" and loaded room, this way game could track available rooms, and keep some of them unloaded for a reason.

In theory it is possible to write your own manager that does that (loads and disposes all room objects, for example).

But then there is a problem of saving room state in between room unloading and reloading, and changing something in the room which is not loaded (what bugs users of AGS currently). So, that's not trivial.

Probably unloading only graphic and audio resources may be a better choice. (But then again, there could be dynamically modified sprites, so... all this requires a good design)

tzachs

I'm not following: the concept of room item and loaded room are already split. You can get a room from the factory with zero state and add stuff later to it, and you can add stuff with or without graphics/audio loaded.
We're missing the built in loading/unloading resource strategies we mentioned before (which one of them will be "load room resources when moving to room"), but other than that, I'm not sure what's missing.

Crimson Wizard

#115
Quote from: tzachs on Sat 12/05/2018 19:17:39
I'm not following: the concept of room item and loaded room are already split. You can get a room from the factory with zero state and add stuff later to it, and you can add stuff with or without graphics/audio loaded.
We're missing the built in loading/unloading resource strategies we mentioned before (which one of them will be "load room resources when moving to room"), but other than that, I'm not sure what's missing.

My meaning was that these concepts are not split in the engine API. There is only one IRoom type, which has no definition of its state. There is no way to tell if the room is a bare object just from the factory, or fully initialized room. User must track this on their own.

I am currently not sure if engine may or should be capable of that, and how to organize this, that is why I decided to not formally suggest that yet.

tzachs

Ah, ok, got you now. Yeah, I'm also not sure if we actually need this.

Monsieur OUXX

I'm currently writing that loading/unloading.
For now I don't care if the state of the room is not kept in-between visits. I'll start with a simple behavior.
How do you unload things?
 

tzachs

To remove an entity from a room: room.Objects.Remove(myEntity);
Or if it's an area: room.Areas.Remove(myEntity);
To remove an entity from the GUI list: state.UI.Remove(myEntity);

After removing the entity from room/gui: myEntity.Dispose();

Monsieur OUXX

#119
OK, thanks.

Based on these sources, does anyone understand why the word "Loading" does not appear?

FakeAGSTestGame/Assets/Rooms/Splashscreen/RoomScript.cs
FakeAGS/Rooms/FakeAGSLoadingScreen.cs


 

tzachs

#120
Quote from: Monsieur OUXX on Sun 13/05/2018 02:08:46
Based on these sources, does anyone understand why the word "Loading" does not appear?
Submitted a PR with a fix (you didn't change the current room to the loading screen).

Quote from: Crimson Wizard on Thu 10/05/2018 23:42:40
Quote from: Monsieur OUXX on Thu 10/05/2018 23:34:25
- is the root folder the execution folder?

Either location of exe, or "current working directory", and TBH that's kind of annoying. I believe there should be a way to configure this.

I had to invent a trick, because path may be different depending on whether you run the game from Visual Studio or from explorer.
What I do is that I pass a part of path as a command line argument when debugging the game, as "../../Assets/". And in game code I assign this argument to a variable called "_baseAssetFolder", which I use to construct resource paths.

By default _baseAssetFolder is just "Assets/", so that you could put Assets folder to same directory where exe is, and run it normally.

My best hopes are that in the end this is what resource loader's implementation will be doing on its own. So that we would have to type just "Images/room.png" instead of "../../Assets/Images/room.png".
I'm pushing a fix for this tomorrow (assuming the build goes well). This is a breaking change as the resources paths are now passed without the "../../Assets" prefix (i.e the default root folder will be the assets folder and it should work no matter where you run the game from). Please read the PR description for more details and let me know if you have questions/reservations.

Quote from: Monsieur OUXX

SWEET! ;-D
Permission to copy?

Monsieur OUXX

#121
Quote from: tzachs on Sun 13/05/2018 05:50:53
Permission to copy?

Well duh (laugh);)

Here:
Code: ags

[url=https://tzachshabtay.github.io/MonoAGS/][img]https://bit.ly/2Ih2c15[/img][/url]
 

SMF spam blocked by CleanTalk