Can't add skins to certain itemsError

I'm so confused. i use to be able to add a skin to change the look of a garage door, but now I can't do that. I get some error in the console when trying to add a skin

Failed to call hook 'OnItemAddedToContainer' on plugin 'Skins v2.2.2' (NullReferenceException: Object reference not set to an instance of an object)

Any help is appreciated.

May I see the full error? First line doesnt help me much.

Merged post

Seems like you should not reload the plugin because it will break. I will release the fix with the next update today, for now you could delete the plugin and upload it again (or modify aka add a space or anything, maybe comment - just put "// x" anywhere at the end of the line)

I reloaded the plugin and it seems to work now at least

thanks for letting me know

To follow up on this, this issue happens when a skin is added or removed. While testing with the eoka pistol and this skin ID: 2524297461, I was able to consistently recreate this issue. When the plugin is reloaded the skin list updates are visible, so it seems like the plugin isn't handling reloading the list of skins correctly when adding or removing a skin.

Merged post

I was able to fix the bug by having always calling GenerateUI at the end of any section of code that calls LoadConfig, as LoadConfig seems to overwrite some of the UI data that GenerateUI used. This will prevent the NRE from earlier, but the modified skin will still not appear. In order for this to happen, container.TotalSkinsCache.Clear must also be called. As an example, this is a fixed version of the /skin add command:

case "add":
case "a":
{
    if (args.Length < 3)
        goto default;

    if (!isAdmin)
    {
        player.Reply(GetMsg("Not Allowed", player.Id));
        break;
    }

    var shortname = args[1];
    ulong skin;
    if (!ulong.TryParse(args[2], out skin))
    {
        player.Reply(GetMsg("Incorrect Skin", player.Id));
        break;
    }

    string permission = null;
    if (args.Length == 4)
        permission = args[3];

    LoadConfig();

    var skinData = Configuration.SkinItem.Find(null, shortname)
        .FirstOrDefault(x => permission == null || x.Permission == permission);
    
    if (skinData == null)
    {
        _config.Skins.Add(new Configuration.SkinItem
        {
            Permission = permission ?? string.Empty,
            Shortname = shortname,
            Skins = new List<ulong> {skin}
        });
        
        _config.IndexSkins();
        player.Reply(GetMsg("Skin Added", player.Id));
    }
    else
    {
        if (skinData.Skins.Contains(skin))
            player.Reply(GetMsg("Skin Already Exists", player.Id));
        else
        {
            skinData.Skins.Add(skin);
            player.Reply(GetMsg("Skin Added", player.Id));
        }
    }

    SaveConfig();
    //Added code after here
    GenerateUI();
    if (isPlayer)
        PurgeCache(ulong.Parse(player.Id), null);
    break;
}​

Also, could you please add these hooks for checking whether a skin exists and for adding skins through the API?

[HookMethod(nameof(AddSkin))]
private bool AddSkin(string shortname, ulong skinID, ulong playerId = 0)
{
    LoadConfig();

    var skinData = Configuration.SkinItem.Find(null, shortname).FirstOrDefault();

    if (skinData == null)
    {
        return false;
    }
    else
    {
        if (skinData.Skins.Contains(skinID))
        {
            return false;
        }
        else
        {
            skinData.Skins.Add(skinID);
            SaveConfig();
            LoadConfig();
            GenerateUI();
            if (playerId != 0)
                PurgeCache(playerId, null);
            return true;
        }
    }
}

[HookMethod(nameof(SkinExists))]
private bool SkinExists(string shortname, ulong skinID)
{
    LoadConfig();
    GenerateUI();

    var skinData = Configuration.SkinItem.Find(null, shortname).FirstOrDefault();

    if (skinData == null)
    {
        return false;
    }
    else
    {
        if (skinData.Skins.Contains(skinID))
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}


Merged post

Quick correction to my last comment, PurgeCache will only purge the cache of the player that initiated the skin update, which will cause everyone else to not see the skin update. In order to address this, replace
if (isPlayer)
        PurgeCache(ulong.Parse(player.Id), null);

// or 

if (playerId != 0)
        PurgeCache(ulong.Parse(playerId), null);​

with
PurgeAllCache();​

and add this function as a helper:

private void PurgeAllCache()
{
    foreach (BasePlayer basePlayer in BasePlayer.activePlayerList) {
        ContainerController container;
        if (!_controllers.TryGetValue(basePlayer.userID, out container))
            break;
        container.TotalSkinsCache.Clear();
    }
}​

Also, this gets rid of the need to have the playerId argument in the AddSkin hook.

Please create a separate thread for the API suggestions

Any news about new update version? bcs we still have issues with non loading custom skins.!

what do you mean by non loading? it might be unrelated, create a separate thread if youve read all existing so far

ofc i have read everything bro... before the last update all my skins worked perfectly but now some of my own custom skins that im designing is not loading up... blue circle icon and in console im getting either wrong manifest or download timedout (even if i have 300 on graphics download)

this is a client (rust, facepunch) issue, the plugin only sends the ID. it might also be some steam issue sending you wrong files or not sending them. anyways eh unrelated to this thread, please create a new one if you are still willing to