Runtime sprite replacement

From what I understand, the content pipeline is the best way to handle assets in the monogame platform. I would like to be able to load content from a filesystem or a network location and see it appear live in my game. Does monogame support this ability? So far I’ve only been able to use the Content Pipeline Tool that lets you pre-compile the assets into xnb files and load them with Content.Load().

Precompiled content (.xnb’s) you can load at any time you wish and then use in the game. If you have fresh sprites that you aren’t running through the content processor first, so like .png’s, you can load those on the fly like this

FileStream fileStream = new FileStream("path/to/sprite/newSprite.png", FileMode.Open);
Texture2D newSprite = Texture2D.FromStream(Graphics.GraphicsDevice, fileStream);
fileStream.Dispose();

I don’t know about audio/fonts though, I think they always have to go through the content processor first.

Mp3 can be loaded using song.fromuri. Never tried a wave though so don’t know about that.

Are there any plans to make the content processors available at runtime? Could a server get an asset, compile it to xnb, and send that out to a client ?

I assume these content processors are part of the content pipeline? I’m wondering now if it wouldn’t be that hard to set up a program running on a web server that ran the content processors much like the content pipeline tool does, only with presets and no UI. Then you could just download the xnb files I suppose. Can you load xnb from a file instead of the content pipeline tool?

That would be very doable. In fact @dellis1972 has a server set up to build effects using the content builder (to build effects on Linux and Mac). You could also run it locally and embed MGCB in your game, but that would only work for 64-bit OS and effects only build on Windows, so building on a remote server would probably be better.

An xnb is just a file that was given the xnb extension to denote that it is processed for MonoGame (or XNA) and can be loaded with the content reader specified in the file. You load an xnb file with a ContentManager in your game. So you don’t load xnb’s from the content pipeline tool, the content pipeline tool is just a GUI that helps you build xnb’s from assets you have. The pipeline tool uses mgcb (MonoGameContentBuilder) for actually building content, and if you want you can run mgcb from the command line as well. So a server building content only needs mgcb, not the GUI.

@Jjagg that’s awesome. Thanks. In my readings, I think I have come to understand that the content pipeline will process the files depending on the platform you choose in the tool, but it will always name it file.xnb. How can you determine which files are processed for the current platform? Let’s say, for instance, I distribute a game on android and on windows 10. There’s a graphics called Logo.png, which I process into an xnb. In the tool I have to choose either Windows or Android. How do I do it for both? And then how does the target platform know which to choose?

If I wanted to create a plugin-ready replacement sprite set for the game (to change the look and feel, for instance) would I have to make a processed version for each platform I release on, or does XNB have some magic that just works everywhere?

You have to process the assets for each platform separately. Mgcb has an option to pass in a platform (that is what the pipeline tool uses behind the scenes as well). Every xnb has 1 character that says what platform it is built for, you can see them at the top of ContentManager source code. ContentManagers then check if the current platform matches the platform in the xnb, and if not an exception is thrown. Relevant code is

        // The first 4 bytes should be the "XNB" header. I.e. XNB[platform byte]
        byte x = xnbReader.ReadByte();
        byte n = xnbReader.ReadByte();
        byte b = xnbReader.ReadByte();
        byte platform = xnbReader.ReadByte();

        if (x != 'X' || n != 'N' || b != 'B' ||
            !(targetPlatformIdentifiers.Contains((char)platform)))
        {
            throw new ContentLoadException("Asset does not appear to be a valid XNB file. Did you process your content for Windows?");
        }

So then the best way to do it would be to process the assets for each platform and set up a separate download point for each platform?

That would be the best way, yes. The XNB for a texture, for example, only contains one representation of that texture. If the texture is compressed, it only contains that one compressed texture. Since different platforms support different texture compression schemes, a XNB containing a compressed texture created for one platform, e.g. Windows that uses DXT, will not be valid for another platform, e.g. Android that uses ETC1.