This first upload includes a relatively full and untested version of Collective. Much should be done still. - README.md: Basic repository and code information - init.lua: The first implementation of collective. Entirely tested on a single-player server, meaning much of the multi-person aspects are currently untested. This is first priority. - mod.conf: Standard Minetest mod stuff TO-DO: - Test Collective on a multi-player server with multiple people.
357 lines
11 KiB
Lua
357 lines
11 KiB
Lua
local mod_storage = minetest.get_mod_storage()
|
|
local collective = {}
|
|
|
|
-- ###################
|
|
-- #### FUNCTIONS ####
|
|
-- ###################
|
|
|
|
function collective.disband(name)
|
|
--[[
|
|
Disbands name's collective.
|
|
|
|
Params:
|
|
name[string]: current player's name
|
|
]]--
|
|
if not collective.in_collective(name) then
|
|
minetest.chat_send_player(name, "You're not in a collective.")
|
|
return
|
|
end
|
|
|
|
local player = minetest.get_player_by_name(name)
|
|
local pmeta = player:get_meta()
|
|
|
|
pmeta:set_string("collective", "")
|
|
minetest.chat_send_player(name, "Disbanding collective.")
|
|
|
|
local members = {}
|
|
members = minetest.deserialize(mod_storage:get_string(name))
|
|
for i, p in pairs(members) do
|
|
if name ~= p then
|
|
local exists = minetest.get_player_by_name(p)
|
|
if exists then
|
|
local cmeta = p:get_meta()
|
|
local membership = cmeta:get_string("collective")
|
|
if membership == name then
|
|
cmeta:set_string("collective", "")
|
|
minetest.chat_send_player(p, name.."'s collective has been disbanded")
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
mod_storage:set_string(name, "")
|
|
end
|
|
|
|
function collective.invite(name, param)
|
|
--[[
|
|
Invite users to join name's collective.
|
|
|
|
Params:
|
|
name[string]: current player's name
|
|
param[list]: list of player name strings
|
|
]]--
|
|
if not collective.in_collective(name) then
|
|
minetest.chat_send_player(name, "You're not in a collective. Use /collective start to make one.")
|
|
return
|
|
end
|
|
|
|
local players = {}
|
|
if #param > 0 then
|
|
players = param
|
|
else
|
|
minetest.chat_send_player(name, "Usage: /collective invite <player name> [player name]...")
|
|
return
|
|
end
|
|
|
|
for i, p in pairs(players) do
|
|
local exists = minetest.get_player_by_name(p)
|
|
local membership = collective.in_collective(p)
|
|
if exists then
|
|
if membership then
|
|
minetest.chat_send_player(name, "Player "..p.." already in a collective.")
|
|
minetest.chat_send_player(p, "You've been invited to "..name.."'s collective, but you can only be in one collective at a time.")
|
|
else
|
|
table.append(mod_storage[name], p)
|
|
minetest.chat_send_player(p, "You've been invited to "..name.."'s collective. Type /collective join "..name.." to join.")
|
|
minetest.chat_send_player(name, "Player "..p.." invited to your collective.")
|
|
end
|
|
else
|
|
minetest.chat_send_player(name, "Player "..p.." doesn't exist!")
|
|
end
|
|
end
|
|
end
|
|
|
|
function collective.join(name, param)
|
|
--[[
|
|
Join a collective. Requires being invited by the collective owner
|
|
|
|
Params:
|
|
name[string]: current player's name
|
|
param[list]: list of player name strings; expecting a single value
|
|
]]--
|
|
if collective.in_collective(name) then
|
|
minetest.chat_send_player(name, "You're already in a collective!")
|
|
return
|
|
end
|
|
|
|
if #param ~= 1 then
|
|
minetest.chat_send_player(name, "Usage: /collective join <player name>")
|
|
return
|
|
end
|
|
|
|
local player = minetest.get_player_by_name(name)
|
|
local pmeta = player:get_meta()
|
|
local members = mod_storage:get_string(param)
|
|
|
|
if members then
|
|
if collective.membership(name, members) then
|
|
pmeta:set_string("collective", param)
|
|
table.append(mod_storage[name], p)
|
|
|
|
minetest.chat_send_player(name, "You've joined "..name.."'s collective.")
|
|
else
|
|
minetest.chat_send_player(name, param.." has not established a collective.")
|
|
end
|
|
end
|
|
|
|
function collective.kick(name, param)
|
|
--[[
|
|
Kick a player from name's collective.
|
|
|
|
Params:
|
|
name[string]: current player's name
|
|
param[list]: list of player name strings; expecting a single value
|
|
]]--
|
|
if not collective.in_collective(name) then
|
|
minetest.chat_send_player(name, "You're not in a collective.")
|
|
return
|
|
end
|
|
|
|
if #param ~= 1 then
|
|
minetest.chat_send_player(name, "Usage: /collective kick <player name>")
|
|
return
|
|
end
|
|
|
|
if name == param[1] then
|
|
minetest.chat_send_player(name, "Cannot kick self! Use /collective disband")
|
|
return
|
|
end
|
|
|
|
local exists = minetest.get_player_by_name(param[1])
|
|
local member = collective.membership(name, param[1])
|
|
if exists then
|
|
if member then
|
|
minetest.chat_send_player(name, "Kicking "..param[1].." from your collective.")
|
|
collective.reform(name, param)
|
|
minetest.chat_send_player(param[1], "You have been kicked from "..name.."'s collective.")
|
|
else
|
|
minetest.chat_send_player(name, param[1].." is not a member of your collective.")
|
|
end
|
|
else
|
|
minetest.chat_send_player(name, param[1].." is not an active player.")
|
|
end
|
|
end
|
|
|
|
function collective.leave(name)
|
|
--[[
|
|
Leave a collective, if currently in one. If name is the owner of the
|
|
collective, also disband the collective.
|
|
|
|
Params:
|
|
name[string]: current player's name
|
|
]]--
|
|
if not collective.in_collective(name) then
|
|
minetest.chat_send_player(name, "You're not in a collective.")
|
|
return
|
|
end
|
|
|
|
local player = minetest.get_player_by_name(name)
|
|
local pmeta = player:get_meta()
|
|
local membership = pmeta:get_string("collective")
|
|
|
|
if name == membership then
|
|
collective.disband(name)
|
|
else
|
|
collective.reform(membership, name)
|
|
pmeta:set_string("collective", "")
|
|
minetest.chat_send_player(name, "You have left "..membership.."'s collective.")
|
|
minetest.chat_send_player(membership, name.." has left your collective.")
|
|
end
|
|
end
|
|
|
|
function collective.start(name, param)
|
|
--[[
|
|
Start a collective, and invite players if provided.
|
|
|
|
Params:
|
|
name[string]: current player's name
|
|
param[list]: list of player name strings
|
|
]]--
|
|
if collective.in_collective(name) then
|
|
minetest.chat_send_player(name, "You're already in a collective!")
|
|
return
|
|
end
|
|
|
|
local players = {}
|
|
if #param > 0 then
|
|
players = param
|
|
end
|
|
|
|
local player = minetest.get_player_by_name(name)
|
|
local pmeta = player:get_meta()
|
|
|
|
pmeta:set_string("collective", name)
|
|
mod_storage:set_string(name, minetest.serialize({name}))
|
|
|
|
minetest.chat_send_player(name, "Collective established!")
|
|
collective.invite(name, players)
|
|
end
|
|
|
|
function collective.status(name)
|
|
--[[
|
|
Shows current collective information
|
|
|
|
Params:
|
|
name[string]: current player's name
|
|
]]--
|
|
local player = minetest.get_player_by_name(name)
|
|
local pmeta = player:get_meta()
|
|
|
|
local player_collective = pmeta:get_string("collective")
|
|
minetest.chat_send_player(name, "Current collective: "..player_collective)
|
|
|
|
local members = mod_storage:get_string(name)
|
|
minetest.chat_send_player(name, "Collective members: "..members)
|
|
end
|
|
|
|
-- ##########################
|
|
-- #### HELPER FUNCTIONS ####
|
|
-- ##########################
|
|
|
|
function collective.in_collective(name)
|
|
--[[
|
|
Check if a player is in any collectives
|
|
|
|
Params:
|
|
name[string]: player name
|
|
|
|
Returns:
|
|
boolean; false if the player's "collective" metadata is "" or nil
|
|
true otherwise
|
|
]]--
|
|
local player = minetest.get_player_by_name(name)
|
|
local pmeta = player:get_meta()
|
|
local membership = pmeta:get_string("collective")
|
|
|
|
if membership == "" or membership == nil then
|
|
return false
|
|
else
|
|
return true
|
|
end
|
|
end
|
|
|
|
function collective.membership(name, param)
|
|
--[[
|
|
Check if current player is a member of a specific collective
|
|
|
|
Params:
|
|
name[string]: current player's name
|
|
param[list]: list of player name strings; expecting a single value
|
|
|
|
Returns:
|
|
boolean; true if name is a member of param's collective
|
|
false otherwise
|
|
]]--
|
|
local members = mod_storage:get_string(param)
|
|
|
|
if string.match(cmeta, name) then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
function collective.print_usage()
|
|
--[[
|
|
Print the /collective usage message
|
|
|
|
Returns:
|
|
string; the usage message
|
|
]]--
|
|
return "Usage: /collective [join,leave,start,disband] [player {,player...}]"
|
|
end
|
|
|
|
function collective.reform(name, param)
|
|
--[[
|
|
Reform name's collective without param
|
|
|
|
Params:
|
|
name[string]: player's name; used for collective
|
|
param[list]: list of player name strings
|
|
]]--
|
|
local members = {}
|
|
members = minetest.deserialize(mod_storage:get_string(name))
|
|
local new_members = {}
|
|
|
|
-- For each member of the collective, and each player provided in param, if
|
|
-- the member does not match the param, add the member to the new_members
|
|
-- list.
|
|
--
|
|
-- This is expensive. Is there a better way to handle this?
|
|
for i,m in pairs(members) do
|
|
for j,p in pairs(param) do
|
|
if not m == p then table.append(new_members, m) end
|
|
end
|
|
end
|
|
|
|
mod_storage:set_string(name, minetest.serialize(new_members))
|
|
end
|
|
|
|
-- #######################
|
|
-- #### CHAT COMMANDS ####
|
|
-- #######################
|
|
|
|
minetest.register_chatcommand("collective", {
|
|
func = function(name, param)
|
|
|
|
if #param <= 0 then
|
|
return false, collective.print_usage()
|
|
end
|
|
|
|
local player = minetest.get_player_by_name(name)
|
|
if not player then
|
|
return false, "You must be online to interact with the collective."
|
|
end
|
|
|
|
local parsed = {}
|
|
for w in string.gmatch(param, "%g+") do
|
|
table.insert(parsed, w)
|
|
end
|
|
|
|
local command = table.remove(parsed, 1)
|
|
if command == "start" then
|
|
collective.start(name, parsed)
|
|
return true
|
|
elseif command == "invite" then
|
|
collective.invite(name, parsed)
|
|
return true
|
|
elseif command == "join" then
|
|
collective.join(name, parsed)
|
|
return true
|
|
elseif command == "leave" then
|
|
collective.leave(name)
|
|
return true
|
|
elseif command == "kick" then
|
|
collective.leave(name, parsed)
|
|
return true
|
|
elseif command == "disband" then
|
|
collective.disband(name)
|
|
return true
|
|
elseif command == "status" then
|
|
collective.status(name)
|
|
return true
|
|
else
|
|
return false, collective.print_usage()
|
|
end
|
|
end,
|
|
})
|