First Upload of Collective
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.
This commit is contained in:
parent
c71a72a09a
commit
f1553e6c8e
3 changed files with 397 additions and 0 deletions
38
README.md
Normal file
38
README.md
Normal file
|
@ -0,0 +1,38 @@
|
|||
# Collective
|
||||
|
||||
Collective is a mod for [Minetest](https://www.minetest.net/) that facilitates
|
||||
groups and group-related activities.
|
||||
|
||||
Collective is a work-in-progress, and currently should be used at your own risk.
|
||||
Functionality has not been sufficiently tested, nor completed.
|
||||
|
||||
## Installation
|
||||
|
||||
Collective has no dependencies. To use Collective, follow the [mod installation
|
||||
instructions](https://wiki.minetest.net/Installing_Mods) from the wiki, or this
|
||||
summary:
|
||||
|
||||
- Create a folder in your mod directory called `collective`
|
||||
- Unzip the [latest archive]() into that directory
|
||||
- Enable the mod by adding `load_mod_collective = true` to your `world.mt` file.
|
||||
|
||||
```
|
||||
minetest/
|
||||
├── ...
|
||||
├── mods/
|
||||
│ ├── ...
|
||||
│ └── collective/
|
||||
│ ├── mod.conf
|
||||
│ └── init.lua
|
||||
├── ...
|
||||
└── worlds/
|
||||
├── ...
|
||||
└── your_world
|
||||
├── ...
|
||||
└── world.mt
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
Open a PR and ping me! I'm
|
||||
[Vagabond](https://matrix.to/#/@vagabondazulien:exp.farm) on Matrix.
|
357
init.lua
Normal file
357
init.lua
Normal file
|
@ -0,0 +1,357 @@
|
|||
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,
|
||||
})
|
2
mod.conf
Normal file
2
mod.conf
Normal file
|
@ -0,0 +1,2 @@
|
|||
name = collective
|
||||
descriptions = Collective facilitates groups and group-related activities
|
Loading…
Reference in a new issue