prototype

This commit is contained in:
tour 2025-04-05 21:52:35 +02:00
commit 37acc9298e
12 changed files with 342 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.vscode*

6
.luacheckrc Normal file
View File

@ -0,0 +1,6 @@
std = "lua51+luajit+minetest"
ignore = {"411"}
globals = {"party_api", "party", "factions"}
read_globals = {"DIR_DELIM"}

10
factions/init.lua Normal file
View File

@ -0,0 +1,10 @@
local core = minetest
local modstorage = core.get_mod_storage()
local modpath = core.get_modpath("factions")
local party_class = dofile(modpath .. "/party.lua")
factions = party_api.manager_classes.default_manager({
storage_ref = modstorage,
party_class = party_class
})

5
factions/mod.conf Normal file
View File

@ -0,0 +1,5 @@
name = factions
title = factions redo
description = reimplementation of https://github.com/neinwhal/party
depends = party_api
author = tour

15
factions/party.lua Normal file
View File

@ -0,0 +1,15 @@
local super = party_api.party_classes.default_party
local party = {}
local call = function(_, ...)
return super(...)
end
return setmetatable({}, {
__call = call,
__index = function (_, key)
return party[key] or super[key]
end
})

4
modpack.conf Normal file
View File

@ -0,0 +1,4 @@
name = party_redo
title = party redo
description = reimplementation of https://github.com/neinwhal/party
author = tour

169
party_api/PartyManager.lua Normal file
View File

@ -0,0 +1,169 @@
-- TODO: remove once the next luacheck release is out
local core = minetest
-- Very simple PartyManager which can only do the basics
-- handles storing/accessing the data
-- mostly used as a superclass
-- storage_ref keys:
-- - "player_" .. playername = partyname
-- - "party_" .. partyname = all data except the members
-- - "members_" .. partyname = {membername = "metadata"}: members of a party. matadata is another serialized string
-- TODO: debug speed
local serialize = core.serialize
local deserialize = core.deserialize
-- local serialize = core.serialize
-- local deserialize = core.deserialize
local PartyManager = {}
local metatable = {
__index = PartyManager
}
PartyManager.listPartys = function (self)
local json_partys = self.storage_ref:get_string("partylist")
return deserialize(json_partys)
end
PartyManager.getPlayersParty = function (self, playername)
-- prefix needed to prevent malicious playernames from overriding other modstorage data
return self.storage_ref:get_string("player_" .. playername)
end
PartyManager.getParty = function (self, partyname)
local json_data = self.storage_ref:get_string("party_" .. partyname)
local json_members = self.storage_ref:get_string("members_" .. partyname)
if json_data == "" then return false, "Party does not exist" end
if json_members == "" then return false, "corrupted database" end -- TODO: error out!
local data = deserialize(json_data)
local members = deserialize(json_members)
return self.party_class(partyname, data, members)
end
PartyManager.setParty = function (self, party)
local partyname = party:getName()
local data = party:getData()
local members = party:getMembers()
local json_data = serialize(data)
local json_members = serialize(members)
self.storage_ref:set_string("party_" .. partyname, json_data)
self.storage_ref:set_string("members_" .. partyname, json_members)
end
PartyManager.createParty = function (self, partyname)
-- getParty might be unreliable in case of a broken db
if self.storage_ref:get_string("party_" .. partyname) ~= "" then
return false, "such a party already exists"
end
local party, error = self.party_class(partyname)
if not party then return false, error end
self:setParty(party)
local json_partys = self.storage_ref:get_string("partylist")
local party_list = deserialize(json_partys)
table.insert(party_list, partyname)
json_partys = serialize(party_list)
self.storage_ref:set_string("partylist", json_partys)
return "OK"
end
PartyManager.deleteParty = function (self, partyname)
local party, error = self:getParty(partyname)
if not party then return false, error end
local sucess, error = party:delete()
if not sucess then return false, error end
local members = party:getMembers()
for member, _ in pairs(members) do
self.storage_ref:set_string("player_" .. member, "")
end
self.storage_ref:set_string("party_" .. partyname, "")
self.storage_ref:set_string("members_" .. partyname, "")
local json_partys = self.storage_ref:get_string("partylist")
local party_list = deserialize(json_partys)
local index = table.indexof(party_list, partyname)
table.remove(party_list, index)
json_partys = serialize(party_list)
self.storage_ref:set_string("partylist", json_partys)
return "OK"
end
PartyManager.renameParty = function (self, oldname, newname)
-- getParty might be unreliable in case of a broken db
if self.storage_ref:get_string("party_" .. newname) ~= "" then
return false, "such a party already exists"
end
local party, error = self:getParty(oldname)
if not party then return false, error end
local sucess, error = party:rename(newname)
if not sucess then return false, error end
for member, _ in pairs(party:getMembers()) do
self.storage_ref:set_string("player_" .. member, newname)
end
self:setParty(party)
local json_partys = self.storage_ref:get_string("partylist")
local party_list = deserialize(json_partys)
local index = table.indexof(party_list, oldname)
party_list[index] = newname
json_partys = serialize(party_list)
self.storage_ref:set_string("partylist", json_partys)
self.storage_ref:set_string("party_" .. oldname, "")
self.storage_ref:set_string("members_" .. oldname, "")
return "OK"
end
PartyManager.join = function (self, playername, partyname)
if self:getPlayersParty(playername) ~= "" then
return false, playername .. " is already in a party"
end
local party, error = self:getParty(partyname)
if not party then return false, error end
local sucess, error = party:join(playername)
if not sucess then return false, error end
self:setParty(party)
self.storage_ref:set_string("player_" .. playername, partyname)
return "OK"
end
PartyManager.leave = function (self, playername)
local partyname = self:getPlayersParty(playername)
local party, error = self:getParty(partyname)
if not party then return false, error end
local sucess, error = party:leave(playername)
if not sucess then return false, error end
self:setParty(party)
self.storage_ref:set_string("player_" .. playername, "")
return "OK"
end
-- -----------------------------------------------------------------------------------------------------------------
return function (kwargs)
if kwargs.storage_ref:get_string("partylist") == "" then
kwargs.storage_ref:set_string("partylist", serialize({}))
end
return setmetatable({
storage_ref = kwargs.storage_ref,
party_class = kwargs.party_class,
}, metatable)
end

86
party_api/PartyObject.lua Normal file
View File

@ -0,0 +1,86 @@
local core = minetest
-- members: {name = "serialized meta"}
-- init(partyname, data, members)
-- create(partyname)
-- delete() -- must guarantee that getMembers will still work afterwards
-- rename
-- GetName()
-- GetData()
-- GetMembers()
-- Join()
-- leave(playername)
-- core.write_json / core.parse_json has problems when called on {}
local serialize = core.serialize
local deserialize = core.deserialize
local PartyObject = {}
PartyObject.getName = function(self)
return self.name
end
PartyObject.getData = function(self)
local result = {}
result.created = self.created
return result
end
PartyObject.getMembers = function(self)
return self.members
end
PartyObject.delete = function()
return "OK"
end
PartyObject.rename = function() -- function(self, newname)
return "OK"
end
PartyObject.join = function(self, playername)
local metadata = {joined = os.time()}
self.members[playername] = serialize(metadata)
return "OK"
end
PartyObject.leave = function (self, playername)
self.members[playername] = nil
return "OK"
end
PartyObject.getPlayerData = function (self, playername)
if not self.members[playername] then
return false, "player is not part of the party"
end
return deserialize(self.members[playername])
end
local load = function (partyname, data, members)
local party = table.copy(data)
party.name = partyname
party.members = members
return setmetatable(party, {__index = PartyObject})
end
local create = function(partyname)
local data = {
created = os.time()
}
local members = {}
return load(partyname, data, members)
end
local call = function (_, ...)
if #{...} == 1 then return create(...) end
if #{...} == 3 then return load(...) end
end
return setmetatable({}, {
__call = call,
__index = PartyObject
})

View File

28
party_api/api.md Normal file
View File

@ -0,0 +1,28 @@
## Party API
### contents of vars:
- members: `{playername1 = "serialized_data", playername2 = "..."}`
- data: table with the data belonging to the party exept for the members
### PartyManager
- listPartys()
- getPlayersParty() "" means no party
- getParty(partyname)
- setParty(party)
- createParty(partyname) party obj. needs to be saved afterwards
- deleteParty(partyname)
- renameParty(oldname, newname)
- join(playername, partyname)
- leave(playername)
### PartyObject
- (partyname): creates a new party with the given name
- (partyname, data, members): loads a party with the given params
- getName()
- getData()
- getMembers()
- delete()
- rename(newname)
- join(playername)
- leave(playername)
- getPlayerData(playername)

14
party_api/init.lua Normal file
View File

@ -0,0 +1,14 @@
-- LGLP license, made by tour
-- TODO: better description
local core = minetest
party_api = {
modpath = core.get_modpath("party_api")
}
party_api.manager_classes = {}
party_api.party_classes = {}
party_api.manager_classes.default_manager = dofile(party_api.modpath .. "/PartyManager.lua")
party_api.party_classes.default_party = dofile(party_api.modpath .. "/PartyObject.lua")

4
party_api/mod.conf Normal file
View File

@ -0,0 +1,4 @@
name = party_api
title = party api
description = api for all kinds of player groups (party/faction/group)
author = tour