Missing method "Connect" with custom chat system's API

Hey, so I’m using Jumpathy’s BetterChat V3 (Check it out!), and I can’t figure out an error that’s going on with a custom command I’m trying to make.

I’ve tried asking in BC3’s DevForum post (which is pretty much dead as no one’s talking there anymore and the creator’s taking a break from Roblox according to their Roblox profile’s About Me section) and looked at the docs several times but there’s no mention of this issue and no possible way for me to figure out what’s causing it.

Here’s the link to BC3’s main module in case it’s needed:
create.roblox.com/marketplace/asset/9375790695

This is my code which is essentially the same as the one provided in the API documentation;
image

And this is the error:

This is the speaker module required from the API:

Speaker Module
return function(network,fetch,signal)
local speakerModule = {}
speakerModule.internal = {}
speakerModule.internal.speakers = {}
speakerModule.speakerAdded = signal.new()
speakerModule.speakerRemoved = signal.new()

local speakersList = speakerModule.internal.speakers
local channel

function speakerModule.new(name,player)
	if(speakersList[name] ~= nil) then
		warn(("[Better Chat]: Speaker '%s' already exists."):format(name))
		return false
	end
	
	local speaker = {}
	speaker.name = name
	speaker.channels = {}
	speaker.tags = {}
	speaker.isPlayer = (player ~= nil)
	speaker.id = (speaker.isPlayer and player.UserId or nil)
	speaker.player = player
	speaker.muted = false
	speaker.icon = ""
	speaker.events = {
		channelUpdated = signal.new(),
		muteUpdate = signal.new(),
		chatted = signal.new()
	}
	
	if(player) then
		speaker.events.channelUpdated:Connect(function()
			network:fireClients("receiveChannelUpdate",{player},fetch(speaker))
		end)
		speaker.events.muteUpdate:Connect(function()
			network:fireClients("receiveMuteUpdate",{player},speaker.muted)
		end)
	end
	
	function speaker:unmute()
		speaker.muted = false
		speaker.events.muteUpdate:Fire(false)
	end
	
	function speaker:mute()
		speaker.muted = true
		speaker.events.muteUpdate:Fire(true)
	end
	
	function speaker:addTag(text,color)
		table.insert(speaker.tags,{
			text=text,
			color=color		
		})	
		
	end
	
	function speaker:updateMuteStatus(state)
		speaker.muted = state
		speaker.events.muteUpdate:Fire(state)
	end
	
	function speaker:removeTag(text)
		for key,tag in pairs(speaker.tags) do
			if (tag.text == text) then
				table.remove(speaker.tags,key)
				
			end
		end
	end
	
	function speaker:addToChannel(channelName)
		channel:getByName(channelName):addSpeaker(speaker)
	end
	
	function speaker:removeFromChannel(channelName)
		channel:getByName(channelName):removeSpeaker(speaker)
	end
	
	function speaker:setIcon(icon)
		speaker.icon = icon
	end
	
	function speaker:say(channelName,message,existing)
		local toSendIn = channel:getByName(channelName)
		if(not toSendIn:canSpeakerTalk(speaker)) then
			warn(("%s cannot talk in channel '%s'"):format(speaker.name,channelName))
			return
		end
		local object = toSendIn:sendMessage(speaker,message,existing)
		speaker.events.chatted:Fire(message,object)
		return object
	end
	
	function speaker:Destroy()
		for _,channel in pairs(speaker.channels) do
			pcall(function()
				channel:removeSpeaker(speaker)
			end)
		end
		for _,event in pairs(speaker.events) do
			event:DisconnectAll()
		end
		speakersList[name] = nil
		speakerModule.speakerRemoved:Fire(name)
	end

	speakersList[name] = speaker
	channel:findAutojoinForSpeaker(speaker)
	speakerModule.speakerAdded:Fire(speaker)

	return true,speaker
end

function speakerModule:getByName(name)
	return speakersList[name]
end

function speakerModule:getById(id)
	for _,speaker in pairs(speakersList) do
		if(speaker.id == id) then
			return speaker
		end
	end
end

function speakerModule:getSpeakers()
	return speakersList
end

function speakerModule:setup(module)
	channel = module
end

return speakerModule

end

and this is where the module’s located.

image

Any help is appreciated!

Can you send us the signal module? That’s the one that should have the connect function. (API shows you’re using signal correctly.)

I bet the problem is that you aren’t getting the speaker class in the right way, so api.speaker isn’t an instance of the speaker class. (events wouldn’t exist in that case)

I would try printing out the api.speaker. I read the API and your code definitely looks correct.

Hi! Here’s what api.speaker prints out:
image
I’m assuming that’s good, since it’s not printing nil or anything like that, but idk

1 Like

If you look at it in the studio console and not in the dev console it will print out all the table elements.

A:

This is because the function Speaker:Say() takes a string argument, not a bool.
local speaker = require(game.Speaker)

speaker:Say(“I’m a string!”)

I’m not using Speaker:Say() (I mean, not currently, but I will after I fix this), and speaker would be required with local speaker = api.Speaker, as it’s not using the default Roblox stuff since this is a completely custom made system. I also haven’t used a bool for :Say() when I did use it, so that’s a bit random

??? What are you right about that I am wrong about? I am a bit confused

Your answer answered nothing and you clearly didn’t even read the docs as you thought you should get the speaker from game.Speaker when it’s not even an object in the game.

I am not going to mark your post as the solution unless you actually provide help on how to fix this, which I can tell you won’t.

what if i say “pretty please” would you do it then “with a cherry on top”

No. Stop commenting if you’re not going to help. I’m not asking for help as a joke here.


Table doesn’t have any contents apparently and then comes the “Missing method” thing again… Does that mean stuff from the module is not being inserted into the table or something like that?

1 Like

A:

I believe this error means that the speaker object was not defined inside of the scope.
In order to solve it, you will need to pass the speaker object into the callback function.
function on_speaker_set(speaker)
local message = "Speaker set to " … speaker.Name
Chat:Chat(message)
end

Chat:RegisterCommand(“speaker”, {
– …
Callback = on_speaker_set,
– …
})

Again, this is NOT the default Roblox chat. This is a custom chat with it’s own, custom and independent API, so your code will not work.

Please check out the actual module and the API’s documentation that I provided in the main post so that you can actually understand what the issue is.

1 Like

You still dont know what you want yourself we cannot help

Yes, I do! Read my post so you can actually help me or just don’t bother replying! I want to make a custom command in the server using the server api. That’s what I need to do. But the :Connect method is missing from the speakerAdded function that detects when the player sends a message, so the command does not work! Do you understand now?

There is someone else trying to ACTUALLY help me right now, and by arguing here we are flooding the topic. Are you going to actually try to help or are you going to keep posting unrelated answers?

1 Like

@BendsSpace Sorry for all the arguing in this topic lol, here’s what the Studio output says when printing out api.speaker, the table is apparently empty

I’m reading the code. The person who made this wrapped the table with a meta table in a weird way that makes it super hard to debug (they did it only so people can use what ever casing like CONNECT, Connect, or connect).

I think the person who made the chat has a bug in their code, I removed the (smart but kind of bothersome) wrapping code and it seems to work.

Where’s the wrapping code located at? I’ll try to remove it and see if it works (I’m not too experienced with tables so I really just don’t know how wrapping works lol)

It basically just changes how the table looks for values.

More detailed explaination

__index is a meta table index that determines how the table looks for values based on the index when the index isn’t in the table. The wrap code creates a new blank table and sets the __index to a function that uses the index to look through the original table.

The wrapping code is betterchat_shared.wrap. You can disable it by changing line 36 of MainModule to

local wrap = function(a) return a end -- Instead of wrapping and returning it just skips wrapping.

Edit:

I tested that and it seemed to solve the problem (the code printed when the player chatted using your code above. There are some data store warnings in the logs but I assume those are because I didn’t enabled datastores).

2 Likes

Thank you so much, I can’t believe it was so simple to fix!

1 Like