In my current game, modding is a HUGE part of the game. It took me a while to develop a good system of loading modded content into the game, but I finally settled on a method, and I would like to keep it if possible.
How I'm handling modded content
In the game's content folder (C:/Users/username/4X), there is a Mods folder. Each mod will have it's own folder inside of the Mod directory. The game goes through a file (Rather, it will. I haven't implemented it yet), and figures out which Mod directories that it's going to load. After it's figured that out, it loads all of the content into the game (I can explain in more detail if its pertinent to the topic, I just don't wan't to use up space on unnecessary things).
So what's your problem?
Well, the mods will all have raw resources (.fbx, .wav, .mp3), and since I can't load anything but XNB files, I have absolutely no idea how to load the mod's content. Well, I take it back, I've been thinking of a few solutions but I really don't know which is more practical, or if there is a better way of doing this.
First, I thought about borrowing some code from the Pipeline application, and building all of the mod's content the first time it was loaded, but I don't fully understand the Pipeline's code, and I didn't want to mess up something by partially implementing it.
Next, I thought about requiring mod creators to use the Pipeline to build their content before they release their mods, but that seemed kind of unprofessional, since I want to have a Mod Creation Engine that has all of the tools bundled together. Which brings me back to using some of the Pipeline's code and embedding it in the engine, but then I have the same issue as my last idea.
And finally, I thought about just loading raw content. But there's an obvious flaw with that idea.
So I guess what I'm asking is:
How can I load raw content? That is, content that hasn't been built into XNB Files
If not, how can I start learning about the code that makes the Pipeline application tick, since I'll probably have to use some of it's code?
You can actually load some raw content directly with MonoGame. For example:
var texture = Content.Load<Texture2D>("raw.png")`
should work if you've got the PNG file in the Content directory and set it's properties to Content / Copy if newer.
However, please note that this will only work for some content and some platforms. I know PNG files work, WAV files work (but they must be mono 44khz I believe) and I'm pretty sure I got MP3 files to work once.
You'll probably run into issues with FBX files and sprite fonts. There's nothing stopping you from bypassing the content manager and loading these yourself though. I've done this before with great success.
Oh, and the other thing I should mention, take a look at the TitleContainer.OpenStream method. This is a way to read a file without writing the platform specific code yourself.
Related
I need to load this font file somehow, and apply it globally -- meaning everything would use this font; if that's not possible, at least tell me how I could load it in;
The resources I found were confusing, they give out no explanation and just give code.
I found a solution, but it's not what you expect, it's just too difficult to load that font file from resources and make it useful, and besides, it was inevitable that I'd stop using resources.
What I did, was simply create a folder in %appdata%, and store all my assets there like fonts, animations, whatever.
I simply stopped using resources, because it's not that good for scalability, as when you start needing animations and all, it's hard to organize everything.
Now I simply have all the paths stored in a variable (that I can easily swap around), and load everything from the %appdata% folder; making the software usable for others is just as simple as making an installer and installing all the necessary assets in %appdata% folder.
If I want to add pictures, I have to put those into the resources and access them from the picturebox.Image property by using this:
AddPicturesFromOtherFolders.Properties.Resources.myPicture
Thats the only way I know. That works fine if I have 10 or so images, but what if I had 500 images? Nobody could keep track of anything. So I would like to structure these hyperthetical 500 Images in a folder structure which I could then access with something like:
pictureBox1.Image= ../../Assets/img/specialImages/myImage.png
That would be very neat, but I have found no way, that involves 100% C# code.
I would be wuite grateful, if you could help me.
Have a nice day,
Alexander Lenssen
You could use Image.FromFile and load the image from any file you have stored in your file system. For example:
pictureBox1.Image.FromFile(#"D:/Assets/img/specialImages/myImage.png");
There is no way that involves 100% C# code. At least some Compiler options or Setup actions are nessesary. But the first question is even where to store it: Programm Directory or UserProfiles?
Asuming these images are static (will only change when a installer runs), you can just store them into the Programm Directory. And from there deploy them with the rest of the code. Getting them Into the Output directory is not that difficulty. Visual Studio has options for that: https://msdn.microsoft.com/en-us/library/0c6xyb66.aspx You could go further, like having a Shared Repository for Images (i.e., most Photoshop programms have one Content Folder under Programms).
You can go as far as "soft linking" them, wich means you can have one actuall folder on your disk that will be copied/synched into the output directories on any buil.
If you need to Update those Images them on the fly (without adminsitrative rights), stuff becomes more complicated. You can still do it via the SpecialFolders. CommonApplicationData seems like the right place to put this kind of stuff. Even Steam and Minecraft's old Java Launcher do quite some storage there. Not to mention every WebBrowser.
If I set my images in Content folder to copy always, then I can use them without building it in content pipeline. I simply call them from code like this:
testImage = Content.Load<Texture2D>("MyImage");
and it works without compilation to xnb format. I've noticed that my 46kb image file after compilation have 204kb and I don't know why.
Is there some benefit of compiling it? Or why should I do that?
Whenever you build a group of files (some PNG files for example), MonoGame stops using the PNGs in the game and starts using its own format, XNB. These files are specially designed for game texture and are, in turn, for efficient. They save the user of your game valuable space on their RAM.
Hope my explanation helps
-GHC
I have this code to add an Image to ImageList :
imageList1.Images.Add(Image.FromFile(path));
I want to somehow save the image in my application(resources maybe?!) just like the way you add Image to ImageList at design time so if I move my application files somewhere else the added images move with it. I don't want to save files in application path or database or other things like that.
Is there any way to do that ?
Can you logically explain how that should work? Did you think this through?
just like the way you add Image to ImageList at design time
If you do this, they get COMPILED INTO THE PROGRAM AS RESOURCE. Which not only requires the compiler and the source code (though you can put them into a resource only assembly), but also access to changing the program files.
Doable at compile time, totally not a sane approach at runtime.
It also effectively stored them in a resource assembly in the application path, which you rule out as a location.
I don't want to save files in application path or database or other things
like that.
latest "other things like that" would ALSO rule out modifying the program (as it would store them somewhere) and make this a total fallacy request. You want to store images but not store them. Grats. Even if not:
Programs should NOT NEVER EVER modify themselves. This is a high priviledge operation, normal users can not change the program files folder.
As you rule out all other places - where you want to store the iamge? Cloud? Magic?
There is no way to do what you want because you rule out all possibilities. And "Like at design time" only seems to think you think this works by magic.
So, no - the question as you have asked it has one answer: get realistic. You can not rule out all ways to save them and then want them saved. Requirements contradict themselves.
I'm looking for a way to determine if a file has been executed or not. I've looked a bit into FileInfo's LastAccessTime but this doesn't seem to change when a file is executed. I've also looked into FileSystemWatcher but this also doesn't seem to offer a solution. Is there such a thing as a file execution listener or is there another way? If it helps, i'm looking to write a folder listener that renames an .avi file within it after it has been watched/executed.
There is a distinction between file being "executed" (e.g. a portable executable file, like an "exe") and a file being "accessed" (e.g. an AVI file that is "played" by another exe).
It sounds like you are looking in the right place and you will want the "LastAccessTime" but, be aware that resolution of the Access time is dependent on the file system... On NTFS it's a full date/time, on FAT it's just the date (hence it won't change if it's already been accessed that day.)
Actually, LastAccessTime might be what you want, since AVI files aren't "executed", only opened. I have, in the past, used it for exactly the purpose you describe, but not programmatically.
Just for the sake of completeness: Windows does not keep execution history, at least not publicly.
Edited to add:
According to MSDN, LastAccessTime is your best shot, however:
Note This method may return an inaccurate value, because it uses native functions whose values may not be continuously updated by the operating system.
But this is followed a few lines later by:
To get the latest value, call the Refresh method.
(This refers to FileSystemInfo.Refresh.)
It's all a little obtuse, if it doesn't work exactly as documented I wouldn't be surprised.
Hmmm, I'm not too sure about finding out if a file has be run, but what might be a better approach would be to monitor the media player to determine when a video has finished playing.