Help with csm needed

User avatar
Miniontoby
Member
Posts: 616
Joined: Fri Mar 01, 2019 19:25
GitHub: Miniontoby
IRC: Miniontoby
In-game: Miniontoby
Location: The Netherlands

Help with csm needed

by Miniontoby » Post

I make a csm mod for someone and I follow the instructions on the minetest modding book and as CSM my code doesn't work, but as a normal mod it does work.

Does anyone know how to solve this problem??

P.S. Things as "minetest.register_privilege", "minetest.register_on_joinplayer" and "minetest.register_globalstep" doesn't work in my code and I think also "minetest.register_chatcommand"
All the "minetest." functions doesn't work
Last edited by Miniontoby on Sun Nov 10, 2019 11:23, edited 1 time in total.
Working on mtctl ---- Check my mod "Doorbell" -- Stay safe

micheal65536
Member
Posts: 167
Joined: Mon May 22, 2017 20:27

Re: Help with csm needed

by micheal65536 » Post

Client-side mods use a completely different API that has little in common with the server-side API. I'm not sure what you're expecting functions such as minetest.register_privilege to even mean in a client-side context but many of the server-side API functions aren't relevant to client-side mods at all, or the equivalent client-side functions need different parameters.

Read https://github.com/minetest/minetest/bl ... ua_api.txt for the client-side API documentation. It's highly unlikely that you'll be able to simply convert a server-side mod to a client-side mod. Many of the things that you'd normally do in a server-side mod, such as adding new node types or changing game mechanics, are not applicable to client-side mods (as the server controls those aspects of the game) and impossible to do in a client-side mod, and client-side mods often focus on modifying the UI of the game rather than the game world itself (such as adding extra features via chat commands or with a GUI form).

zing269
Member
Posts: 109
Joined: Sat Apr 30, 2016 19:10

Re: Help with csm needed

by zing269 » Post

It would be nice if that was actually included in the doc folder.

User avatar
Miniontoby
Member
Posts: 616
Joined: Fri Mar 01, 2019 19:25
GitHub: Miniontoby
IRC: Miniontoby
In-game: Miniontoby
Location: The Netherlands

Re: Help with csm needed

by Miniontoby » Post

Is there an "minetest" depend or something else??
Working on mtctl ---- Check my mod "Doorbell" -- Stay safe

User avatar
jas
Member
Posts: 593
Joined: Mon Jul 24, 2017 18:15
IRC: Freenode
Location: IRC

Re: Help with csm needed

by jas » Post

Minetest requires that clientmods have a file called mod.conf, and where is this documented indeed. That file is not present, and requires the user to create it.

Ideally the management of CSM mods could be managed via the GUI. At the very least, mods.conf could be present by default.

It frustrates me that so much effort was made to restrict and really neuter CSM.

micheal65536
Member
Posts: 167
Joined: Mon May 22, 2017 20:27

Re: Help with csm needed

by micheal65536 » Post

zing269 wrote:It would be nice if that was actually included in the doc folder.
It actually is. In the Minetest source tree, you will have doc/client_lua_api.txt alongside doc/lua_api.txt (the latter being the documentation for the server-side mod API). If you don't have this documentation file it's possible that you're using an old version of Minetest that doesn't support client-side mods or you're using a pre-built Linux package that for some reason doesn't include this file.

micheal65536
Member
Posts: 167
Joined: Mon May 22, 2017 20:27

Re: Help with csm needed

by micheal65536 » Post

jas wrote:Minetest requires that clientmods have a file called mod.conf, and where is this documented indeed. That file is not present, and requires the user to create it.
To clarify, the file is called mods.conf, not mod.conf, and there is one of these files for each Minetest installation located directly inside the clientmods directory. This file specifies which client-side mods should be loaded, and should not be confused with the individual mod.conf files that each server-side mod should provide (and which do not currently seem to exist in the context of client-side mods).

The clientmods/mods.conf file should contain one line for each client-side mod that you want to load, as follows: load_mod_modname = true. In this case, modname is the name of the directory containing the client-side mod (so for example if you installed the friendly_chat mod then the line would be load_mod_friendly_chat = true). You can also change true to false and in that case the mod won't be loaded (the same as if the line was missing altogether). If I remember correctly, once the file exists, Minetest will add lines (with the value set to false) for any mods that it finds but which aren't already listed in the file.

zing269
Member
Posts: 109
Joined: Sat Apr 30, 2016 19:10

Re: Help with csm needed

by zing269 » Post

micheal65536 wrote:
zing269 wrote:It would be nice if that was actually included in the doc folder.
It actually is. In the Minetest source tree, you will have doc/client_lua_api.txt alongside doc/lua_api.txt (the latter being the documentation for the server-side mod API). If you don't have this documentation file it's possible that you're using an old version of Minetest that doesn't support client-side mods or you're using a pre-built Linux package that for some reason doesn't include this file.
I'm using the official windows 64-bit download from minetest.net and that file is not included.

User avatar
jas
Member
Posts: 593
Joined: Mon Jul 24, 2017 18:15
IRC: Freenode
Location: IRC

Re: Help with csm needed

by jas » Post

there is one of these files for each Minetest installation located directly inside the clientmods directory
I don't see it: https://github.com/minetest/minetest/tr ... lientmods/

It's not there.

micheal65536
Member
Posts: 167
Joined: Mon May 22, 2017 20:27

Re: Help with csm needed

by micheal65536 » Post

jas wrote:
there is one of these files for each Minetest installation located directly inside the clientmods directory
I don't see it: https://github.com/minetest/minetest/tr ... lientmods/

It's not there.
You have to create it yourself. When I said "there is", I meant "there is expected to be". As in "there is one mods.conf file directly inside the clientmods directory, as opposed to individual mod.conf files for each mod". I was trying to distinguish this clearly from the similarly-named mod.conf files used for server-side mods.

User avatar
Miniontoby
Member
Posts: 616
Joined: Fri Mar 01, 2019 19:25
GitHub: Miniontoby
IRC: Miniontoby
In-game: Miniontoby
Location: The Netherlands

Re: Help with csm needed

by Miniontoby » Post

I have a "/clientmods/mods.conf" with the mod enabled and I got an error of the code
Attachments
The error
The error
Minetest 5.1.0 [Main Menu] 11-11-2019 14_33_55.png (123.13 KiB) Viewed 996 times
Last edited by Miniontoby on Thu Nov 14, 2019 13:39, edited 1 time in total.
Working on mtctl ---- Check my mod "Doorbell" -- Stay safe

micheal65536
Member
Posts: 167
Joined: Mon May 22, 2017 20:27

Re: Help with csm needed

by micheal65536 » Post

Miniontoby wrote:I have a "/clientmods/mods.conf" with the mod enabled and I got an error of the code
The error is because client-side mods use a different API to server-side mods. Please re-read this post where I already explained this:
micheal65536 wrote:Client-side mods use a completely different API that has little in common with the server-side API. I'm not sure what you're expecting functions such as minetest.register_privilege to even mean in a client-side context but many of the server-side API functions aren't relevant to client-side mods at all, or the equivalent client-side functions need different parameters.

Read https://github.com/minetest/minetest/bl ... ua_api.txt for the client-side API documentation. It's highly unlikely that you'll be able to simply convert a server-side mod to a client-side mod. Many of the things that you'd normally do in a server-side mod, such as adding new node types or changing game mechanics, are not applicable to client-side mods (as the server controls those aspects of the game) and impossible to do in a client-side mod, and client-side mods often focus on modifying the UI of the game rather than the game world itself (such as adding extra features via chat commands or with a GUI form).
Think about it logically: minetest.register_privilege registers a privilege that the server uses to control what commands players can use or what actions they can take. What would you expect minetest.register_privilege to do in a client-side mod and why would you want to call it? Privileges make no sense in the context of a client-side mod.

User avatar
Miniontoby
Member
Posts: 616
Joined: Fri Mar 01, 2019 19:25
GitHub: Miniontoby
IRC: Miniontoby
In-game: Miniontoby
Location: The Netherlands

Re: Help with csm needed

by Miniontoby » Post

That error I solved and now have an other error.

I have an question: How to check if an player is on the server and then check the file if it needs to be kicked and then that it kicked that player?

Please help me with that and make an code that I can use as an CSM
Working on mtctl ---- Check my mod "Doorbell" -- Stay safe

micheal65536
Member
Posts: 167
Joined: Mon May 22, 2017 20:27

Re: Help with csm needed

by micheal65536 » Post

Miniontoby wrote:I have an question: How to check if an player is on the server and then check the file if it needs to be kicked and then that it kicked that player?
For kicking you will need to make the CSM send the same kick command that you would use if you were kicking the player manually (there is no minetest.kick_player function in the client-side API). minetest.run_server_chatcommand("kick", player_name) will probably work. If you want to include a reason, you can use minetest.run_server_chatcommand("kick", player_name .. " " .. reason). Obviously you will need to have the kick privilege on whatever server you want to use this on.

I don't know how to check if a player is on the server but I know there is a client-side API function for it. I'm too lazy to look it up though because you can read the documentation that I linked to and find it yourself.

User avatar
Miniontoby
Member
Posts: 616
Joined: Fri Mar 01, 2019 19:25
GitHub: Miniontoby
IRC: Miniontoby
In-game: Miniontoby
Location: The Netherlands

Re: Help with csm needed

by Miniontoby » Post

Thanks for that, micheal65536.

And for the player (because there is no "minetest.register_on_joinplayer") I need an solution
Working on mtctl ---- Check my mod "Doorbell" -- Stay safe

micheal65536
Member
Posts: 167
Joined: Mon May 22, 2017 20:27

Re: Help with csm needed

by micheal65536 » Post

Miniontoby wrote:And for the player (because there is no "minetest.register_on_joinplayer") I need an solution
Please read the documentation that I have linked to, it provides a list of all the client-side API functions. There is an API function that will return a list of the players connected to the server. There is also an API function that lets you process incoming chat messages (including messages such as players joining/leaving and responses to chat commands), so you could also send the /status command to the server and extract the list of players from the response (the same information is normally also sent when you join the server). You could also monitor for player join/leave messages, although this will only tell you about players that have joined or left after you joined so you will need to use another approach for getting the initial list of players.

User avatar
Miniontoby
Member
Posts: 616
Joined: Fri Mar 01, 2019 19:25
GitHub: Miniontoby
IRC: Miniontoby
In-game: Miniontoby
Location: The Netherlands

Re: Help with csm needed

by Miniontoby » Post

But how exactly (please with code)

And my code need to kick players who join and need to be kicked (from the file information that did been created with the rest of the code and a chatcommand I already have done)
Working on mtctl ---- Check my mod "Doorbell" -- Stay safe

micheal65536
Member
Posts: 167
Joined: Mon May 22, 2017 20:27

Re: Help with csm needed

by micheal65536 » Post

Miniontoby wrote:But how exactly (please with code)
I will not write the code for you. I have directed you to the documentation that you need. Please read the documentation and figure out what code you need to write in order to do what you're trying to do. You cannot always rely on other people to write the code for you. You need to be able to read documentation and write the code yourself - it's not that hard to do, and that's all that I would be doing if I wrote the code for you. From your first post it sounds like you already know how to write simple code, so you should have no problem writing the code again as a client-side mod once you find the correct API functions to use.

One more time, here is the link to the client-side API documentation which lists all of the available API functions. Please look at the documentation and find the functions that you need to use (hint: you can search the documentation with keywords such as "player", "chat", or "message" using your web browser's "find" function to find functions that might be relevant). https://github.com/minetest/minetest/bl ... ua_api.txt

EDIT: I've already given you a hint in my previous post for a way that you can find out when players are joining the game.
Last edited by micheal65536 on Fri Nov 15, 2019 20:29, edited 1 time in total.

User avatar
Miniontoby
Member
Posts: 616
Joined: Fri Mar 01, 2019 19:25
GitHub: Miniontoby
IRC: Miniontoby
In-game: Miniontoby
Location: The Netherlands

Re: Help with csm needed

by Miniontoby » Post

I amn't the best modder (I have only made the doorbell mod) and I don't know how to use /status in a CSM code
Working on mtctl ---- Check my mod "Doorbell" -- Stay safe

micheal65536
Member
Posts: 167
Joined: Mon May 22, 2017 20:27

Re: Help with csm needed

by micheal65536 » Post

Miniontoby wrote:I don't know how to use /status in a CSM code
I've already told you how to use /kick from a client-side mod (minetest.run_server_chatcommand("kick", player_name)). From this you should be able to figure out how to run the /status command.

If you want to watch for player join/leave messages (similar to minetest.register_on_joinplayer and minetest.register_on_leaveplayer) then you will need to use another client-side API function that will tell you every time a chat message is received and let you do something in response to it. You can also use the same API function to watch for the server's response after you send the /status command (if you decide to use that method, although from your description it sounds like you're more interested in doing something in response to a player joining the game). You can find the correct API function by going to the API documentation that I linked to and searching for the word "chat" or "message" (you can search for text on a page by using your browser's "find" option which can usually be accessed by pressing ctrl+f).

Once you are able to respond to incoming chat messages, you will need to find the correct messages to respond to and extract the relevant information from them. Lua provides a function that will let you see if text strings match an expected format (called a "pattern") and let you extract parts of them according to a particular format.

To get the name of a player that joins the server, you would use string.match(message, "^*** (%S*) joins the game$"). The ^ and $ symbols make sure that the entire message matches, not just a part somewhere in the middle. The %S* part means "this part can be anything that isn't a space", and the brackets around it mean "I want to get whatever text was in this part of the original string". Altogether this means "check that the entire string starts with '*** ', followed by anything that isn't a space, followed by ' joins the game', and tell me what actual text was in the part after the asterisks". If you pass each chat message to this function, you'll either get the name of the player that joined the game or nil (which means that the chat message isn't a player join message). (You can find more information about patterns in Lua here: https://www.lua.org/manual/5.3/manual.html#6.4.1.)

Getting the list of players from the server status message (which is received directly after joining the game and after running the /status command) is a bit more complicated. For this, you would use the pattern ^# Server: .*clients={([^}]*)}. The ^ symbol means "match from the beginning of the string, don't start somewhere in the middle". Following this is the text # Server: which will always appear at the start of the server status message. After this, .* means "this part can be anything, I don't care what characters there are or how many of them there are". In this case, that means "the next part should appear somewhere in the string but I don't care where". Then there's the text clients={ which indicates the start of the list of player names. Then [^}]* means "this part is anything except a } character" (because the } marks the end of the list). As with the previous example, this part is surrounded by brackets so we'll be given whatever text was in here. Finally there's the closing } symbol to mark the end of the list. We don't care what (if anything) comes after the list of player names so we can end the pattern here. Altogether this means "check that the string starts with '# Server: ', then find the list of player names starting with 'clients={' somewhere inside the string, and tell me what's between the opening and closing curly bracket". As before, you'll either get the list of player names or you'll get a nil value meaning that the chat message isn't the server status message.

However, once you have the list of players from the server status message you'll still need to split it into a list of individual names (right now it's just a single string with all the names separated by commas). To do this, you can use another Lua function called string.gmatch. This function also takes a pattern but instead of checking once if the string matches the pattern and then giving you some part of it it will let you use a pattern to split a string into multiple sections. It's used in a for loop and on the first iteration of the loop it will give you the first part of the string that matches the pattern, then on the next iteration it will give you the next matching part, and so on until there's nothing left. To split the list of players, you would use

Code: Select all

for player in string.gmatch(list, "[^, ][^, ]*") do
  -- do something with the player's name here
end
The [^, ] in the pattern means "find a single character that isn't a space or a comma" (because commas and spaces are used to separate the names in the list). It's repeated twice and the second time it's followed by the * symbol which means "find any number of characters that aren't a space or a comma", but this can include zero characters. We want to find anything that's one or more characters long, not zero or more characters long. So together this means "find a character that isn't a space or a comma, followed by zero or more characters that aren't a space or a comma", or in other words "find a sequence of one or more characters that aren't a space or a comma".

User avatar
Miniontoby
Member
Posts: 616
Joined: Fri Mar 01, 2019 19:25
GitHub: Miniontoby
IRC: Miniontoby
In-game: Miniontoby
Location: The Netherlands

Re: Help with csm needed

by Miniontoby » Post

Can you please put that in a good working csm code for me (also because I cant make it working and I don't know everything about csm's and that lua_api file I also don't know how to use the commands)
Working on mtctl ---- Check my mod "Doorbell" -- Stay safe

micheal65536
Member
Posts: 167
Joined: Mon May 22, 2017 20:27

Re: Help with csm needed

by micheal65536 » Post

Miniontoby wrote:Can you please put that in a good working csm code for me (also because I cant make it working and I don't know everything about csm's and that lua_api file I also don't know how to use the commands)
Do you have any code so far? If you post your code so far I can help you figure out why it isn't working.

I have given you all the building blocks to make your CSM. Even if you have limited programming knowledge, you should be able to put them together from the information that I've given you.

User avatar
Miniontoby
Member
Posts: 616
Joined: Fri Mar 01, 2019 19:25
GitHub: Miniontoby
IRC: Miniontoby
In-game: Miniontoby
Location: The Netherlands

Re: Help with csm needed

by Miniontoby » Post

I don't know how to make a one really, but this is what is tried (with the rest of the code)

Code: Select all

print("Load 'kick2' CSM [kick2]")
print("")

minetest.register_chatcommand("kick2", {
	params = "<playername> | <playername> <reason>",
    privs = {
        kick = true,
    },
	func = function(name, param)
		local can_kick = minetest.check_player_privs(name, {kick=true})
		if can_kick then 
			if string.find(param, "^[^ ]+%s+.+") then
				player_name, reason = string.match(param, "^([^ ]+)%s+(.+)")
				minetest.run_server_chatcommand("kick", player_name .. " " .. reason)
				t = io.open(minetest.get_worldpath().."/" .. player_name .. "_players.txt", "w")
				t:write("true")
			else
				player_name = param
				reason = ""
				minetest.run_server_chatcommand("kick", player_name)
				t = io.open(minetest.get_worldpath().."/" .. player_name .. "_players.txt", "w")
				t:write("true")
			end
		else 
			minetest.log("info", name .. " don't have the kick priv")
		end
    end,	
})

minetest.register_chatcommand("unkick2", {
	params = "<playername>",
    privs = {
        kick = true,
    },
	func = function(name, param)
	local can_kick = minetest.check_player_privs(name, {kick=true})
		if can_kick then 
			t = io.open(minetest.get_worldpath().."/" .. param .. "_players.txt", "w")
			t:write("false")
		else 
			minetest.log("info", "You don't have the kick priv")
		end
    end,	
})

minetest.register_on_receiving_chat_message(function(message)
	if string.find(message, "^*** (%S*) joined the game$") then
		player_name = string.match(message, "^*** (%S*) joined the game$")
		local p = io.open(minetest.get_worldpath().."/" .. player_name .. "_players.txt", "r")
		if p ~= nil then
			local kick_message = p:read("*line")
			p:close()
			if kick_message ~= nil then
				if kick_message == "true" then
					minetest.run_server_chatcommand("kick", player_name)
				end
			end
		end
	end
end)
Working on mtctl ---- Check my mod "Doorbell" -- Stay safe

micheal65536
Member
Posts: 167
Joined: Mon May 22, 2017 20:27

Re: Help with csm needed

by micheal65536 » Post

Thanks for posting the code. There are a few things that I can comment on here.

Code: Select all

print("Load 'kick2' CSM [kick2]")
print("")
You don't need this and it is more likely to cause confusion. Minetest already lists each CSM in the terminal/console as it's loaded.

Code: Select all

minetest.register_chatcommand("kick2", {
    params = "<playername> | <playername> <reason>",
    privs = {
        kick = true,
    },

Code: Select all

minetest.register_chatcommand("unkick2", {
    params = "<playername>",
    privs = {
        kick = true,
    },
Take out the privs section. It doesn't apply to client-side mods and will be ignored. Remember, privileges are a server-side thing.

Code: Select all

    func = function(name, param)
In client-side mods, there's no name parameter to the command handler function because the command will always be run by yourself. You should only have the param parameter in your function definition.

Code: Select all

        local can_kick = minetest.check_player_privs(name, {kick=true})
This is probably unnecessary because running the command without the required server-side privileges won't do anything anyway (because the server won't allow it) but the equivalent client-side API function is minetest.get_privilege_list(), which will return a table listing your own privileges. You would use it like this: local can_kick = minetest.get_privilege_list().kick. (In the case of removing players from the list, I would strongly recommend skipping the privilege check because you're only removing someone that you've already added yourself and you might want to do this even if you don't have kick privileges for some reason.)

Code: Select all

            minetest.log("info", name .. " don't have the kick priv")
You should probably use minetest.display_chat_message("You don't have the kick priv") instead. That will show the message in your chat (but only for you, it won't send it to anyone else on the server). Also, you can't use name in the string because it isn't passed to the client-side command handler function (as previously explained).

Code: Select all

                t = io.open(minetest.get_worldpath().."/" .. player_name .. "_players.txt", "w")
                t:write("true")

Code: Select all

            t = io.open(minetest.get_worldpath().."/" .. param .. "_players.txt", "w")
            t:write("false")

Code: Select all

        local p = io.open(minetest.get_worldpath().."/" .. player_name .. "_players.txt", "r")
        if p ~= nil then
            local kick_message = p:read("*line")
            p:close()
            if kick_message ~= nil then
                if kick_message == "true" then
                    minetest.run_server_chatcommand("kick", player_name)
                end
            end
        end
There is no io.open function for client-side mods. There's also no minetest.get_worldpath() function because the world is stored on the server. The closest equivalent is minetest.get_mod_storage() however this won't give you per-world/per-server storage (so you could end up kicking the same player from a different server if you have kick privileges on multiple servers - although I do wonder if there's any particular reason why you need to save the list after you leave and re-join the game and if you can't just re-add a player to the list if you see them again later (note in particular that this code won't automatically kick the player if they're already in the game when you join, only if they join after you)). This is a bit of a difficult API function to use because you have to call it at load-time rather than at run-time (you can't call it from your command handler function), and the correct way to use this would be to add the line local storage = minetest.get_mod_storage() at the top of your code and then later you'll use

Code: Select all

storage:set_string("kick_" .. player_name, "true")
storage:set_string("reason_" .. player_name, reason)
to add the player to the kick list,

Code: Select all

storage:set_string("kick_" .. param, "")
storage:set_string("reason_" .. param, "")
to remove the player from the list (using an empty string deletes the value entirely which is better than leaving a "false" value in storage), and

Code: Select all

if storage:get_string("kick_" .. player_name) == "true" then
    local reason = storage:get_string("reason_" .. player_name)
    if reason ~= "" then
        minetest.run_server_chatcommand("kick", player_name .. " " .. reason)
    else
        minetest.run_server_chatcommand("kick", player_name)
    end
end
to kick the player when they later join the game (note that storage:get_string will return an empty string, not nil, if the value is unset or has been deleted).

If you make these changes and then post the code again I can check if there are any other issues.

User avatar
Miniontoby
Member
Posts: 616
Joined: Fri Mar 01, 2019 19:25
GitHub: Miniontoby
IRC: Miniontoby
In-game: Miniontoby
Location: The Netherlands

Re: Help with csm needed

by Miniontoby » Post

Thank you for this help

But the reason don't needed to posted everytime ;)
And I add the server info for the kicking a player on a specific server and not kicking at an other server

I have made changes and this is my code now:

Code: Select all

local storage = minetest.get_mod_storage()
local server_info = minetest.get_server_info()
local server_id = server_info.address .. ':' .. server_info.port

minetest.register_chatcommand("kick2", {
	params = "<playername> | <playername> <reason>",
	func = function(name, param)
		if string.find(param, "^[^ ]+%s+.+") then
			player_name, reason = string.match(param, "^([^ ]+)%s+(.+)")
			minetest.run_server_chatcommand("kick", player_name .. " " .. reason)
			storage:set_string(server_id .. "kick_" .. player_name, "true")
		else
			player_name = param
			minetest.run_server_chatcommand("kick", player_name)
			storage:set_string(server_id .. "kick_" .. player_name, "true")
		end
    end,	
})

minetest.register_chatcommand("unkick2", {
	params = "<playername>",
    privs = {
        kick = true,
    },
	func = function(name, param)
		storage:set_string(server_id .. "kick_" .. param, "")
    end,	
})

minetest.register_on_receiving_chat_message(function(message)
	if string.find(message, "^*** (%S*) joined the game$") then
		player_name = string.match(message, "^*** (%S*) joined the game$")
		if storage:get_string(server_id .. "kick_" .. player_name) == "true" then
			minetest.run_server_chatcommand("kick", player_name)
		end
	end
end)
And I did try to test it but it doesn't got loaded

I runned a server from the commandline, I joined it and mod doesn't got loaded (and I have put the client-side-modding on) so that is also an problem
Working on mtctl ---- Check my mod "Doorbell" -- Stay safe

Post Reply

Who is online

Users browsing this forum: No registered users and 5 guests