135 lines
3.2 KiB
Lua
135 lines
3.2 KiB
Lua
--[[
|
|
|
|
sqlite backend for insidethebox
|
|
|
|
This backend stores various persistent world data bits that are
|
|
not properly stored by the minetest engine. This mod provides both
|
|
persistent and performant data storage for the itb game until a
|
|
better solution exists.
|
|
|
|
Major data storage parts in this db:
|
|
|
|
- players, player scores
|
|
No player metadata storage exists currently. Only HP and air
|
|
are stored in player data. We lack storage for things like
|
|
skin choice, stamina, RPG points and skills, etc.
|
|
|
|
- box data
|
|
|
|
--]]
|
|
|
|
local world_path = minetest.get_worldpath()
|
|
-- local sqlite3 = require("lsqlite3")
|
|
local insecure_env = minetest.request_insecure_environment()
|
|
local sqlite3 = insecure_env.require("lsqlite3")
|
|
local itb_db = sqlite3.open(world_path .. "/itb.sqlite")
|
|
|
|
if not itb_db then
|
|
assert("lsqlite3 not available or non-functional. Please use e.g. luarocks to install lsqlite3")
|
|
end
|
|
|
|
-- we require these tables to exist:
|
|
assert(itb_db:exec[[
|
|
CREATE TABLE box (id INTEGER PRIMARY KEY, data BLOB);
|
|
CREATE TABLE series (id INTEGER PRIMARY KEY, name TEXT, meta BLOB);
|
|
CREATE TABLE series_box (series_id INTEGER, box_id INTEGER);
|
|
CREATE TABLE player (id INTEGER PRIMARY KEY, name TEXT, meta BLOB);
|
|
CREATE TABLE points (player_id INTEGER, score REAL, type TEXT, box_id INTEGER);
|
|
]])
|
|
|
|
-- table structure and content
|
|
--[[
|
|
|
|
box table: Contain the storage of the box content (not metadata) so all blocks. (one-to-one)
|
|
- id: box identifier
|
|
- data: box contents (nodes)
|
|
|
|
series: Contains existing series
|
|
- id: series ID
|
|
- name: name of the series
|
|
- meta: misc data
|
|
|
|
series_box: maps boxes into series (many-to-many)
|
|
- series_id: series ID
|
|
- box_id: box ID
|
|
|
|
player: player info
|
|
- id: player number
|
|
- name: player name
|
|
- meta: random player data bits
|
|
|
|
score: player and box score data
|
|
- player_id: player id
|
|
- score: score value
|
|
- type: score type (e.g. reviewed a box)
|
|
- box: associated box ID
|
|
--]]
|
|
|
|
db = {}
|
|
|
|
function db.player_get_meta(name)
|
|
local stmt = itb_db:prepare[[
|
|
SELECT meta FROM player WHERE name = :name
|
|
]]
|
|
stmt:bind_names{name = name}
|
|
for row in stmt:nrows() do
|
|
stmt:finalize()
|
|
return minetest.parse_json(row.meta)
|
|
end
|
|
stmt:finalize()
|
|
|
|
print("no such player in db", name)
|
|
return nil
|
|
end
|
|
|
|
function db.player_put_meta(name, meta)
|
|
local stmt = itb_db:prepare[[
|
|
REPLACE INTO player_meta (name, meta) VALUES (:name, :meta)
|
|
]]
|
|
stmt:bind_names{name = name, meta = minetest.write_json(meta)}
|
|
local r = stmt:step()
|
|
stmt:finalize()
|
|
if not r then
|
|
print("error writing")
|
|
return false
|
|
else
|
|
return true
|
|
end
|
|
end
|
|
|
|
function db.box_get_data(box_id)
|
|
local stmt = itb_db:prepare[[
|
|
SELECT data FROM box WHERE id = :box_id
|
|
]]
|
|
stmt:bind_names{box_id = box_id}
|
|
for row in stmt:nrows() do
|
|
stmt:finalize()
|
|
return row.data
|
|
end
|
|
stmt:finalize()
|
|
|
|
print("no such box in db", box_id)
|
|
return nil
|
|
|
|
end
|
|
|
|
function db.box_set_data(box_id, data)
|
|
local stmt = itb_db:prepare[[
|
|
INSERT INTO box (id, data) VALUES(:box_id, :box_data)
|
|
]]
|
|
stmt:bind_names{box_id = box_id, box_data = data}
|
|
local r = stmt:step()
|
|
stmt:finalize()
|
|
if not r then
|
|
print("error writing")
|
|
return false
|
|
else
|
|
return true
|
|
end
|
|
end
|
|
|
|
|
|
minetest.register_on_shutdown(function()
|
|
itb_db:close()
|
|
end)
|