ResetButtonCallback has not been registered by the CoreScripts

They are not guaranteed to be registered within a certain time frame. You should wrap these calls in a pcall and continuously try it at a time interval until it goes through.

eww


local resetBindable = Instance.new("BindableEvent")

local remote_reset = game.ReplicatedStorage:WaitForChild('remote_reset')
resetBindable.Event:connect(function()
    --custom reset logic on server-side
	remote_reset:FireServer()
end)

local success = false

while not success do
	success = pcall(function()
		game:GetService("StarterGui"):SetCore("ResetButtonCallback", resetBindable)
	end)
	if success then
		break
	else
		print'coregui being slow for ResetButtonCallback'
	end
	wait(.2)
end
10 Likes
repeat success = pcall(function() setCore() end) wait(0.2) until success

Little bit cleaner

14 Likes

You could make use of name call.

while not pcall(starterGui, "SetCore", "ResetButtonCallback", resetBindable) do
  wait()
end

Though of course, this would be I’ll advised.

3 Likes

All that works fine…until one of those items is no longer supported, throwing your script into an infinite yield. I would probably want to add some sort of time-out logic too–something quite large though, like 15 seconds.

2 Likes
local coreCall do
	local MAX_RETRIES = 8

	local StarterGui = game:GetService('StarterGui')
	local RunService = game:GetService('RunService')

	function coreCall(method, ...)
		local result = {}
		for retries = 1, MAX_RETRIES do
			result = {pcall(StarterGui[method], StarterGui, ...)}
			if result[1] then
				break
			end
			RunService.Stepped:Wait()
		end
		return unpack(result)
	end
end

coreCall('SetCore', 'ResetButtonCallback', false)

I post this every time this comes up. Always keep a utility function around for core calls.

132 Likes

Why is this even a thing?

2 Likes

Because if the game scripts would only run after the corescripts are finished initializing, that means your game scripts are unnecessarily delayed. You don’t want that situation. The errors and the delay in initialization are a minor inconvenience at best and the alternative is worse for all games (even those that don’t interact with core scripts through SetCore).

5 Likes

Really wish the call would do the waiting itself so I don’t need to do a loop …

9 Likes

If we make the assumption (for the purpose of the following question) that Roblox’s code is perfectly organized in such a way that independent things will not yield each other, what does ResetButtonCallback need to yield for? (I assume the 0.001 seconds of actual script runtime can be disregarded?)

SetCore items are not guaranteed to be available within a certain time frame, or ever, for that matter.

You can find the source code of the corescripts here:
https://github.com/Roblox/Core-Scripts/tree/f2965847c9eac9715af9323d76b9ef36d40619bb/CoreScriptsRoot

Now keep in mind that just because something seems to be immediately available in those scripts right now (i.e. no yielding before the point at which a thing is registered), that doesn’t mean they will be in the future. If they add something to the core scripts that needs to perform a web request first, for example, it could be that SetCore items that are almost immediately available now will take longer to become available in the future.

This should not be a problem in your code, because the guarantee that they are available immediately was never given. If you are assuming that right now, that’s your mistake because you assumed wrongly, not the mistake of the implementation.

(And refer back to the post above on why they can’t make the core scripts fully initialize first)

3 Likes

in the wiki guides I read about usage of setcore, for example disabling the reset button, there was no code relating to waiting in a pcall loop for it. lol

3 Likes

There isn’t but there should be. I have to have pcalls for my reset button.

3 Likes

Thanks for sharing the utility function @Fractality_alt!

I noticed that you used RunService.Stepped:Wait() instead of a longer wait like 0.1. Is 8 iterations of RunService.Stepped:Wait() long enough to guarantee setcore is available in time?

5 Likes

From what I have seen, No.

It can take more than 10 seconds to be available so you might want to give it more time

3 Likes

Sorry, a little late of a reply–I was looking back at this thread because of a new thread on this same issue

Your reasoning makes a little more sense to me now, but I’m wondering if it might be better to guarantee that corescripts finish initializing (all their outward interfaces are accessible) before normal scripts run. I think I am okay if there are race conditions between replicatedfirst localscripts and corescripts, although I’d even prefer if replicatedfirst scripts are guaranteed to execute first; do you think this is a good idea?

Also I am thinking events for corescripts.initialized and bools for corescripts.isinitialized would be really useful

I think really all we need is that last bit, events for when they are ready and a method to check that they are ready.

5 Likes

I tried adding this and when I spawned in I could reset. After resetting once, I couldn’t reset anymore. Why did it let me reset the first time?

A little off-topic, but still related to CoreGui not being registered. I am having huge problems with CoreGuiChatConnections not registering at all. I have tried using @Fractality_alt’s utility function to wait for CoreGuiChatConnections to register, but it never does. Even after waiting for thousands of tries, it never gets registered. Extremely annoying for me because I need to fire MessagePosted via creating a new Event and overriding current CoreGuiChatConnections’ MessagePosted event with mine.

1 Like

I was able to come up with a good core system that has worked for me very well. While wait is often frowned upon, it works really well here, and it doesn’t cause any notable lag for the short amount of time this code is active. When calling this function locally, make sure that you put it in a coroutine.wrap() so whatever else runs after it isn’t halted for the short period of time it takes for this to complete (unless that’s what you want.) It completely stops and frees up your memory when it’s done, thanks to Lua’s Automatic Garbage Collection:

[‘LoadRobloxCore’] = function(CoreType, CoreProperty, Toggle)
repeat
    local success = pcall(function()
        if CoreType == "SetCore" then
            game.StarterGui:SetCore(CoreProperty, Toggle)
        elseif CoreType == "SetCoreGui" then
            game.StarterGui:SetCoreGuiEnabled(CoreProperty, Toggle)
        end
    end)
    wait(0.02)
until
    success
end;

Hope this utility function helps you as much as it’s done for me!

11 Likes