• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

BuckarooBanzay / mapblock_lib / 8748710497

19 Apr 2024 05:09AM UTC coverage: 19.22% (-35.6%) from 54.827%
8748710497

Pull #3

github

BuckarooBanzay
remove (failing) ldoc
Pull Request #3: mtt action

202 of 1051 relevant lines covered (19.22%)

16.77 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

23.17
/data.lua
1
---------
2
-- off-world storage for position-dependent data (data in mapblocks, tilenames, etc)
3
-- indexed in 10^3 groups and saved in the mod-storage
4

5
------
6
-- World data storage object
7
-- @type DataStorage
8
local DataStorage = {}
1✔
9
local DataStorage_mt = { __index = DataStorage }
1✔
10

11
-- metrics
12
local cache_hit_callback = function() end
1✔
13
local cache_miss_callback = function() end
1✔
14

15
--- create a new world data storage object
16
-- @param storage the mod_storage object from "minetest.get_mod_storage()"
17
-- @return @{DataStorage} the storage object
18
function mapblock_lib.create_data_storage(storage, opts)
2✔
19
    opts = opts or {}
×
20

21
    local self = {
×
22
        -- mod_storage ref
23
        storage = storage,
24
        -- group_index -> data
25
        cache = {},
26
        -- group_index -> bool
27
        stale_data = {},
28

29
        serialize = opts.serialize or minetest.serialize,
30
        deserialize = opts.deserialize or minetest.deserialize
×
31
    }
32
    local ref = setmetatable(self, DataStorage_mt)
×
33

34
    -- start initial save_worker run
35
    self:save_worker()
×
36
    -- start periodic data purge worker
37
    self:purge_worker()
×
38
    -- save stale data on shutdown
39
    minetest.register_on_shutdown(function() self:save_stale_data() end)
×
40

41
    return ref
×
42
end
43

44
--- Creates a data link to the target position
45
-- @param target_pos the position to link to
46
-- @return the link object
47
function mapblock_lib.create_data_link(target_pos)
2✔
48
    return {
×
49
        _link = target_pos
×
50
    }
51
end
52

53
--- Checks if the data is a link
54
-- @param the data object
55
-- @return true if the data object is a link
56
function mapblock_lib.is_data_link(data)
2✔
57
    return data and data._link
×
58
end
59

60
--- Resolves a data link from the storage
61
-- @param storage the @{DataStorage} object
62
-- @param pos the first position to resolve
63
-- @param max_recursions[opt] maximum recursion count before aborting (defaults to 10)
64
-- @return the resolved data object or nil if none found
65
-- @return the target position of the link
66
function mapblock_lib.resolve_data_link(storage, pos, max_recursions)
2✔
67
    local recursions = 0
×
68
    local data = storage:get(pos)
×
69
    local target_pos = pos
×
70

71
    while true do
72
        if mapblock_lib.is_data_link(data) then
×
73
            target_pos = data._link
×
74
            data = storage:get(data._link)
×
75
        else
76
            break
77
        end
78

79
        recursions = recursions + 1
×
80
        if recursions > (max_recursions or 10) then
×
81
            return
×
82
        end
83
    end
84

85
    return data, target_pos
×
86
end
87

88
-- "group" is a bundle of mapblock-positions
89
local function get_group_pos(pos)
90
    -- 10^3 pos-datasets are in a group for better lookup, indexing and caching
91
    return vector.floor(vector.divide(pos, 10))
×
92
end
93

94
function DataStorage:get_group_data(pos)
1✔
95
    local index = minetest.pos_to_string(get_group_pos(pos))
×
96
    if not self.cache[index] then
×
97
        local serialized_data = self.storage:get_string(index)
×
98
        if serialized_data == "" then
×
99
            -- no data, add empty table
100
            self.cache[index] = {}
×
101
        else
102
            -- deserialize data
103
            self.cache[index] = self.deserialize(serialized_data) or {}
×
104
        end
105
        cache_miss_callback()
×
106
    else
107
        cache_hit_callback()
×
108
    end
109
    return self.cache[index]
×
110
end
111

112
-- store grouped data for async save
113
function DataStorage:set_group_data(pos, data)
1✔
114
    local index = minetest.pos_to_string(get_group_pos(pos))
×
115
    self.cache[index] = data
×
116
    self.stale_data[index] = true
×
117
end
118

119
-- saves all stale data
120
function DataStorage:save_stale_data()
1✔
121
    for index in pairs(self.stale_data) do
×
122
        local data = self.cache[index]
×
123
        local serialized_data = self.serialize(data)
×
124
        self.storage:set_string(index, serialized_data)
×
125
        self.stale_data[index] = nil
×
126
    end
127
end
128

129
-- async save worker
130
function DataStorage:save_worker()
1✔
131
    self:save_stale_data()
×
132
    minetest.after(2, function() self:save_worker() end)
×
133
end
134

135
function DataStorage:purge()
1✔
136
    self:save_stale_data()
×
137
    self.cache = {}
×
138
end
139

140
-- periodic data purge
141
function DataStorage:purge_worker()
1✔
142
    self:purge()
×
143
    minetest.after(600, function() self:purge_worker() end)
×
144
end
145

146
-- exposed functions below here
147

148
--- Returns the data at given position
149
-- @param pos @{util.node_pos} the position of the data
150
function DataStorage:get(pos)
1✔
151
    local index = minetest.pos_to_string(pos)
×
152
    local group_data = self:get_group_data(pos)
×
153
    return group_data[index]
×
154
end
155

156
--- Sets the data at given position
157
-- @param pos @{util.node_pos} the position of the data
158
-- @param data the data to save at the position or nil to clear
159
function DataStorage:set(pos, data)
1✔
160
    local index = minetest.pos_to_string(pos)
×
161
    local group_data = self:get_group_data(pos)
×
162
    group_data[index] = data
×
163
    self:set_group_data(pos, group_data)
×
164
end
165

166
--- Merges the data at given position with the existing data
167
-- @param pos @{util.node_pos} the position of the data
168
-- @param data the data to merge at the position, only top-level fields will be merged together
169
function DataStorage:merge(pos, merge_data)
1✔
170
    local data = self:get(pos) or {}
×
171
    for k,v in pairs(merge_data) do
×
172
        data[k] = v
×
173
    end
174
    self:set(pos, data)
×
175
end
176

177
--- Clears all data from the storage
178
function DataStorage:clear()
1✔
179
    -- remove disk data
180
    self.storage:from_table()
×
181
    -- remove cache
182
    self.cache = {}
×
183
    -- purge stale data
184
    self.stale_data = {}
×
185
end
186

187
-- monitoring stuff
188
if minetest.get_modpath("monitoring") then
1✔
189
    -- cache hit stats
190
    local cache_hits = monitoring.counter("mapblock_lib_data_cache_hits", "number of cache hits")
×
191
    cache_hit_callback = cache_hits.inc
×
192

193
    local cache_miss = monitoring.counter("mapblock_lib_data_cache_miss", "number of cache misses")
×
194
    cache_miss_callback = cache_miss.inc
×
195

196
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc