Ludeon Forums

RimWorld => Bugs => Topic started by: Fluffy (l2032) on April 07, 2016, 04:08:25 PM

Title: [StaticConstructorOnStartup] does not appear to work correctly
Post by: Fluffy (l2032) on April 07, 2016, 04:08:25 PM
Steps to reproduce:
I've used the following snippet of code to obtain some test results; the rest of the class/mod can be found here: https://github.com/Karel-Kroeze/RW_Blueprints/ (https://github.com/Karel-Kroeze/RW_Blueprints/)

using RimWorld;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEngine;
using Verse;


namespace Blueprints
{
    [StaticConstructorOnStartup]
    public class Designator_CreateBlueprint : Designator
    {
        #region Public Constructors


        public Designator_CreateBlueprint()
        {
            Log.Error( "INSTANTIATING NOW:\n" + System.Environment.StackTrace );
            Log.Message( "Types with static constructors:" );
            foreach ( var type in GenTypes.AllTypesWithAttribute<StaticConstructorOnStartup>() )
            {
                Log.Message( "\t" + type.FullName );
            }


            LongEventHandler.ExecuteWhenFinished( delegate
            {
                Resources.Icon_AddBlueprint = ContentFinder<Texture2D>.Get( "Icons/AddBlueprint", true );
                Resources.Icon_Blueprint = ContentFinder<Texture2D>.Get( "Icons/Blueprint", true );
                Resources.Icon_Edit = ContentFinder<Texture2D>.Get( "Icons/Edit", true );


                icon = Resources.Icon_AddBlueprint;
            } );


            defaultLabel = "Fluffy.Blueprints.Create".Translate();
            defaultDesc = "Fluffy.Blueprints.CreateHelp".Translate();
            useMouseIcon = true;
        }


        #endregion Public Constructors


// more code.
}
}

Note that the LongEventHandler.ExecuteWhenFinished call does work, and circumvents the issue.


The attached output log highlights the issue. The game is clearly aware that this type (and a few others) should have a static constructor, yet the stack trace shows that it is still instantiated from a secondary thread.

[attachment deleted by admin - too old]
Title: Re: [StaticConstructorOnStartup] does not appear to work correctly
Post by: ison on April 07, 2016, 04:39:15 PM
Note that it must be a static constructor and in your case its a normal constructor. Could you try to load your resources in a static constructor and tell if it helps?
Title: Re: [StaticConstructorOnStartup] does not appear to work correctly
Post by: Fluffy (l2032) on April 07, 2016, 04:50:00 PM
doh - if that's it that would be a tad silly of me, will try right now.
Title: Re: [StaticConstructorOnStartup] does not appear to work correctly
Post by: Fluffy (l2032) on April 07, 2016, 04:58:35 PM
Nope, no luck.

new code;
using RimWorld;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEngine;
using Verse;

namespace Blueprints
{
    [StaticConstructorOnStartup]
    public class Designator_CreateBlueprint : Designator
    {
        static Designator_CreateBlueprint()
        {
            Log.Error( "INSTANTIATING NOW:\n" + System.Environment.StackTrace );
            string text = "Types with static constructors:";
            foreach ( var type in GenTypes.AllTypesWithAttribute<StaticConstructorOnStartup>() )
            {
                text += ( "\n\t" + type.FullName );
            }
            Log.Message( text );

            Resources.Icon_AddBlueprint = ContentFinder<Texture2D>.Get( "Icons/AddBlueprint", true );
            Resources.Icon_Blueprint = ContentFinder<Texture2D>.Get( "Icons/Blueprint", true );
            Resources.Icon_Edit = ContentFinder<Texture2D>.Get( "Icons/Edit", true );
        }

        #region Public Constructors

        public Designator_CreateBlueprint()
        {
            icon = Resources.Icon_AddBlueprint;
            defaultLabel = "Fluffy.Blueprints.Create".Translate();
            defaultDesc = "Fluffy.Blueprints.CreateHelp".Translate();
            useMouseIcon = true;
        }


new output attached, still called from asynch thread, now with the resulting errors.

On a possibly related note, whenever I enable any of my mods, even those where textures are (magically?) working correctly - the language flag is rendered as the bad texture box.

[attachment deleted by admin - too old]
Title: Re: [StaticConstructorOnStartup] does not appear to work correctly
Post by: ison on April 08, 2016, 08:08:53 AM
Ah, it's because Designators are created during async loading, so using a StaticConstructorOnStartup doesn't do anything because the static constructor is called during async loading anyway. I'll make it so designators are created after the loading is done. In the meantime, you'll have to use LongEventHandler.ExecuteWhenFinished.
Title: Re: [StaticConstructorOnStartup] does not appear to work correctly
Post by: Fluffy (l2032) on April 08, 2016, 08:41:24 AM
Good to hear you're on it ;)

On a related note, is it possible to check what thread ContentFinder is called from? It would be great to have a more descriptive warning pop up.  E.g. in this case, and on windows, the error suggest there is something wrong with the path. I my manager mod, loading textures from the second thread actually seems to (weirdly) work on windows - but it breaks for users running Linux, see the reply by Vee here;
https://ludeon.com/forums/index.php?topic=16888.msg201942#msg201942



Title: Re: [StaticConstructorOnStartup] does not appear to work correctly
Post by: ison on April 08, 2016, 09:31:09 AM
Quote from: Fluffy (l2032) on April 08, 2016, 08:41:24 AM
On a related note, is it possible to check what thread ContentFinder is called from? It would be great to have a more descriptive warning pop up.  E.g. in this case, and on windows, the error suggest there is something wrong with the path. I my manager mod, loading textures from the second thread actually seems to (weirdly) work on windows - but it breaks for users running Linux, see the reply by Vee here;
https://ludeon.com/forums/index.php?topic=16888.msg201942#msg201942

Good idea, I'll add a check with more descriptive error when someone tries to load an asset from a different thread so the behavior on different platforms will be consistent.