added report on globalstep, add sample munin plugin
[smartshop.git] / init.lua
1 smartshop={user={},tmp={},dir={{x=0,y=0,z=-1},{x=-1,y=0,z=0},{x=0,y=0,z=1},{x=1,y=0,z=0}},dpos={
2 {{x=0.2,y=0.2,z=0},{x=-0.2,y=0.2,z=0},{x=0.2,y=-0.2,z=0},{x=-0.2,y=-0.2,z=0}},
3 {{x=0,y=0.2,z=0.2},{x=0,y=0.2,z=-0.2},{x=0,y=-0.2,z=0.2},{x=0,y=-0.2,z=-0.2}},
4 {{x=-0.2,y=0.2,z=0},{x=0.2,y=0.2,z=0},{x=-0.2,y=-0.2,z=0},{x=0.2,y=-0.2,z=0}},
5 {{x=0,y=0.2,z=-0.2},{x=0,y=0.2,z=0.2},{x=0,y=-0.2,z=-0.2},{x=0,y=-0.2,z=0.2}}}
6 }
7
8 -- table with itemname: number of items being traded
9 smartshop.itemstats = {}
10 smartshop.itemprices = {}
11 smartshop.stuffsold = {}
12
13
14
15 smartshop.itemsatpos = function(pos, item, count)
16 -- set number of items of type 'item' sold at position 'pos'
17 if smartshop.itemstats[item] == nil then
18 smartshop.itemstats[item] = {}
19 end
20 smartshop.itemstats[item][pos] = count
21 local file = io.open(minetest.get_worldpath().."/smartshop_itemcounts.txt", "w")
22 if file then
23 file:write(minetest.serialize(smartshop.itemstats))
24 file:close()
25 end
26 end
27
28 smartshop.itempriceatpos = function(pos, item, price)
29 -- set number of items of type 'item' sold at position 'pos'
30 if smartshop.itemprices[item] == nil then
31 smartshop.itemprices[item] = {}
32 end
33 local file = io.open(minetest.get_worldpath().."/smartshop_itemprices.txt", "w")
34 if file then
35 file:write(minetest.serialize(smartshop.itemprices))
36 file:close()
37 end
38 smartshop.itemprices[item][pos] = price
39 end
40
41 smartshop.minegeldtonumber = function(stack)
42 -- return number of minegeld in stack, returns nil if stack is not composed of minegeld
43 count = stack:get_count()
44 if count == 0 then
45 return 0
46 end
47 if stack:get_name() == "currency:minegeld" then
48 return count
49 elseif stack:get_name() == "currency:minegeld_5" then
50 return count * 5
51 elseif stack:get_name() == "currency:minegeld_10" then
52 return count * 10
53 else
54 return nil
55 end
56 end
57
58
59 minetest.register_craft({
60 output = "smartshop:shop",
61 recipe = {
62 {"default:chest_locked", "default:chest_locked", "default:chest_locked"},
63 {"default:sign_wall_wood", "default:chest_locked", "default:sign_wall_wood"},
64 {"default:sign_wall_wood", "default:torch", "default:sign_wall_wood"},
65 }
66 })
67 smartshop.get_human_name = function(item)
68 if core.registered_items[item] then
69 return core.registered_items[item].description
70 else
71 return "Unknown Item"
72 end
73 end
74
75 smartshop.use_offer=function(pos,player,n)
76 local pressed={}
77 pressed["buy" .. n]=true
78 smartshop.user[player:get_player_name()]=pos
79 smartshop.receive_fields(player,pressed)
80 smartshop.user[player:get_player_name()]=nil
81 smartshop.update(pos)
82 end
83
84 smartshop.get_offer=function(pos)
85 if not pos or not minetest.get_node(pos) then return end
86 if minetest.get_node(pos).name~="smartshop:shop" then return end
87 local meta=minetest.get_meta(pos)
88 local inv=meta:get_inventory()
89 local offer={}
90 for i=1,4,1 do
91 offer[i]={
92 give=inv:get_stack("give" .. i,1):get_name(),
93 give_count=inv:get_stack("give" .. i,1):get_count(),
94 pay=inv:get_stack("pay" .. i,1):get_name(),
95 pay_count=inv:get_stack("pay" .. i,1):get_count(),
96 }
97 end
98 return offer
99 end
100
101 smartshop.send_mail=function(owner, pos, item)
102 if not minetest.get_modpath( "mail" ) then
103 return
104 end
105 local spos = "("..pos.x..", "..pos.y..", "..pos.z..")"
106 mail.send("DO NOT REPLY", owner, "Out of "..smartshop.get_human_name(item).." at "..spos, "Your smartshop at "..spos.." is out of "..smartshop.get_human_name(item)..". Please restock")
107 end
108
109
110 smartshop.receive_fields=function(player,pressed)
111 if pressed.customer then
112 return smartshop.showform(smartshop.user[player:get_player_name()],player,true)
113 elseif pressed.tooglelime then
114 local pos=smartshop.user[player:get_player_name()]
115 local meta=minetest.get_meta(pos)
116 local pname=player:get_player_name()
117 if meta:get_int("type")==0 then
118 meta:set_int("type",1)
119 minetest.chat_send_player(pname, "Your stock is limited")
120 else
121 meta:set_int("type",0)
122 minetest.chat_send_player(pname, "Your stock is unlimited")
123 end
124 elseif not pressed.quit then
125 local n=1
126 for i=1,4,1 do
127 n=i
128 if pressed["buy" .. i] then break end
129 end
130 local pos=smartshop.user[player:get_player_name()]
131 if not pos then
132 return
133 end
134 local meta=minetest.get_meta(pos)
135 local type=meta:get_int("type")
136 local inv=meta:get_inventory()
137 local pinv=player:get_inventory()
138 local pname=player:get_player_name()
139 if pressed["buy" .. n] then
140 local name=inv:get_stack("give" .. n,1):get_name()
141 local stack=name .." ".. inv:get_stack("give" .. n,1):get_count()
142 local pay=inv:get_stack("pay" .. n,1):get_name() .." ".. inv:get_stack("pay" .. n,1):get_count()
143 if name~="" then
144 if type==1 and inv:room_for_item("main", pay)==false then minetest.chat_send_player(pname, "Error: The owner's stock is full, can't receive, exchange aborted.") return end
145 if meta:get_int("ghost") ~=1 then
146 -- transition shops to ghost inventory.
147 for i=1,4 do
148 if inv:room_for_item("main", "pay"..i) and inv:room_for_item("main", "give"..i) then
149 meta:set_int("ghost", 1)
150 inv:add_item("main", inv:get_stack("pay"..i,1))
151 inv:add_item("main", inv:get_stack("give"..i,1))
152 end
153 end
154 end
155 if type==1 and inv:contains_item("main", stack)==false then
156 minetest.chat_send_player(pname, "Error: "..smartshop.get_human_name(name).." is sold out.")
157 if not meta:get_int("alerted") or meta:get_int("alerted") == 0 then
158 meta:set_int("alerted",1) -- Do not alert twice
159 smartshop.send_mail(meta:get_string("owner"), pos, name)
160 end
161 return
162 end
163 if not pinv:contains_item("main", pay) then minetest.chat_send_player(pname, "Error: You don't have enough in your inventory to buy this, exchange aborted.") return end
164 if not pinv:room_for_item("main", stack) then minetest.chat_send_player(pname, "Error: Your inventory is full, exchange aborted.") return end
165 pinv:remove_item("main", pay)
166 pinv:add_item("main", stack)
167 if type==1 then
168 inv:remove_item("main", stack)
169 inv:add_item("main", pay)
170 if not inv:contains_item("main", stack) and (not meta:get_int("alerted") or meta:get_int("alerted") == 0) then
171 meta:set_int("alerted",1) -- Do not alert twice
172 smartshop.send_mail(meta:get_string("owner"), pos, name)
173 end
174 end
175 end
176 end
177 else
178 local pos=smartshop.user[player:get_player_name()]
179 smartshop.update_info(pos)
180 if smartshop.user[player:get_player_name()] or minetest.check_player_privs(player:get_player_name(), {protection_bypass=true}) then
181 local meta=minetest.get_meta(smartshop.user[player:get_player_name()])
182 if meta:get_string("owner")==player:get_player_name() then
183 smartshop.update(smartshop.user[player:get_player_name()],"update")
184 end
185 end
186 smartshop.user[player:get_player_name()]=nil
187 end
188 end
189
190 minetest.register_on_player_receive_fields(function(player, form, pressed)
191 if form=="smartshop.showform" then
192 smartshop.receive_fields(player,pressed)
193 end
194 end)
195
196
197
198
199 smartshop.update_info=function(pos)
200 if not pos then
201 return
202 end
203 local meta=minetest.get_meta(pos)
204 local spos=minetest.pos_to_string(pos)
205 local inv = meta:get_inventory()
206 local owner=meta:get_string("owner")
207 if meta:get_int("type")==0 then
208 meta:set_string("infotext","(Smartshop by " .. owner ..") Stock is unlimited")
209 return false
210 end
211 local name=""
212 local count=0
213 local stuff={}
214 for i=1,4,1 do
215 stuff["count" ..i]=inv:get_stack("give" .. i,1):get_count()
216 stuff["name" ..i]=inv:get_stack("give" .. i,1):get_name()
217 stuff["stock" ..i]=0 -- stuff["count" ..i]
218 local mg_price = smartshop.minegeldtonumber(inv:get_stack("pay" .. i,1))
219 if mg_price ~= nil then
220 stuff["pay"..i] = mg_price/stuff["count" ..i]
221 end
222 stuff["buy" ..i]=0
223 for ii=1,32,1 do
224 name=inv:get_stack("main",ii):get_name()
225 count=inv:get_stack("main",ii):get_count()
226 if name==stuff["name" ..i] then
227 stuff["stock" ..i]=stuff["stock" ..i]+count
228 end
229 end
230 local nstr=(stuff["stock" ..i]/stuff["count" ..i]) ..""
231 nstr=nstr.split(nstr, ".")
232 stuff["buy" ..i]=tonumber(nstr[1])
233 if stuff["name" ..i]=="" or stuff["buy" ..i]==0 then
234 stuff["buy" ..i]=""
235 stuff["name" ..i]=""
236 if smartshop.stuffsold[spos..i] then
237 smartshop.itemsatpos(spos, smartshop.stuffsold[spos..i], 0)
238 smartshop.itempriceatpos(spos, smartshop.stuffsold[spos..i], nil)
239 smartshop.stuffsold[spos..i] = nil
240 end
241 else
242 smartshop.itemsatpos(spos, stuff["name"..i], stuff["buy"..i]*stuff["count" ..i])
243 smartshop.itempriceatpos(spos, stuff["name"..i], stuff["pay"..i])
244 smartshop.stuffsold[spos..i] = stuff["name"..i]
245 stuff["name"..i] = smartshop.get_human_name(stuff["name"..i])
246 stuff["buy" ..i]="(" ..stuff["buy" ..i] ..") "
247 stuff["name" ..i]=stuff["name" ..i] .."\n"
248 end
249 end
250 meta:set_string("infotext",
251 "(Smartshop by " .. owner ..") Purchases left:\n"
252 .. stuff.buy1 .. stuff.name1
253 .. stuff.buy2 .. stuff.name2
254 .. stuff.buy3 .. stuff.name3
255 .. stuff.buy4 .. stuff.name4
256 )
257 end
258
259
260
261
262 smartshop.update=function(pos,stat)
263 --clear
264 local spos=minetest.pos_to_string(pos)
265 for _, ob in ipairs(minetest.env:get_objects_inside_radius(pos, 2)) do
266 if ob and ob:get_luaentity() and ob:get_luaentity().smartshop and ob:get_luaentity().pos==spos then
267 ob:remove()
268 end
269 end
270 if stat=="clear" then return end
271 --update
272 local meta=minetest.get_meta(pos)
273 local inv = meta:get_inventory()
274 local node=minetest.get_node(pos)
275 local dp = smartshop.dir[node.param2+1]
276 if not dp then return end
277 pos.x = pos.x + dp.x*0.01
278 pos.y = pos.y + dp.y*6.5/16
279 pos.z = pos.z + dp.z*0.01
280 for i=1,4,1 do
281 local item=inv:get_stack("give" .. i,1):get_name()
282 local pos2=smartshop.dpos[node.param2+1][i]
283 if item~="" then
284 smartshop.tmp.item=item
285 smartshop.tmp.pos=spos
286 local e = minetest.env:add_entity({x=pos.x+pos2.x,y=pos.y+pos2.y,z=pos.z+pos2.z},"smartshop:item")
287 e:setyaw(math.pi*2 - node.param2 * math.pi/2)
288 end
289 end
290 end
291
292
293 minetest.register_entity("smartshop:item",{
294 hp_max = 1,
295 visual="wielditem",
296 visual_size={x=.20,y=.20},
297 collisionbox = {0,0,0,0,0,0},
298 physical=false,
299 textures={"air"},
300 smartshop=true,
301 type="",
302 on_activate = function(self, staticdata)
303 if smartshop.tmp.item ~= nil then
304 self.item=smartshop.tmp.item
305 self.pos=smartshop.tmp.pos
306 smartshop.tmp={}
307 else
308 if staticdata ~= nil and staticdata ~= "" then
309 local data = staticdata:split(';')
310 if data and data[1] and data[2] then
311 self.item = data[1]
312 self.pos = data[2]
313 end
314 end
315 end
316 if self.item ~= nil then
317 self.object:set_properties({textures={self.item}})
318 else
319 self.object:remove()
320 end
321 end,
322 get_staticdata = function(self)
323 if self.item ~= nil and self.pos ~= nil then
324 return self.item .. ';' .. self.pos
325 end
326 return ""
327 end,
328 })
329
330
331 smartshop.showform=function(pos,player,re)
332 local meta=minetest.get_meta(pos)
333 local creative=meta:get_int("creative")
334 local inv = meta:get_inventory()
335 local gui=""
336 local spos=pos.x .. "," .. pos.y .. "," .. pos.z
337 local owner=meta:get_string("owner")==player:get_player_name()
338 if minetest.check_player_privs(player:get_player_name(), {protection_bypass=true}) then owner=true end
339 if re then owner=false end
340 smartshop.user[player:get_player_name()]=pos
341 if owner then
342 meta:set_int("alerted",0) -- Player has been there to refill
343 gui=""
344 .."size[8,10]"
345 .."button_exit[6,0;1.5,1;customer;Customer]"
346 .."label[0,0.2;Item:]"
347 .."label[0,1.2;Price:]"
348 .."list[nodemeta:" .. spos .. ";give1;2,0;1,1;]"
349 .."list[nodemeta:" .. spos .. ";pay1;2,1;1,1;]"
350 .."list[nodemeta:" .. spos .. ";give2;3,0;1,1;]"
351 .."list[nodemeta:" .. spos .. ";pay2;3,1;1,1;]"
352 .."list[nodemeta:" .. spos .. ";give3;4,0;1,1;]"
353 .."list[nodemeta:" .. spos .. ";pay3;4,1;1,1;]"
354 .."list[nodemeta:" .. spos .. ";give4;5,0;1,1;]"
355 .."list[nodemeta:" .. spos .. ";pay4;5,1;1,1;]"
356 if creative==1 then
357 gui=gui .."label[0.5,-0.4;Your stock is unlimited becaouse you have creative or give]"
358 .."button[6,1;2.2,1;tooglelime;Toggle limit]"
359 end
360 gui=gui
361 .."list[nodemeta:" .. spos .. ";main;0,2;8,4;]"
362 .."list[current_player;main;0,6.2;8,4;]"
363 .."listring[nodemeta:" .. spos .. ";main]"
364 .."listring[current_player;main]"
365 else
366 gui=""
367 .."size[8,6]"
368 .."list[current_player;main;0,2.2;8,4;]"
369 .."label[0,0.2;Item:]"
370 .."label[0,1.2;Price:]"
371 .."list[nodemeta:" .. spos .. ";give1;2,0;1,1;]"
372 .."item_image_button[2,1;1,1;".. inv:get_stack("pay1",1):get_name() ..";buy1;\n\n\b\b\b\b\b" .. inv:get_stack("pay1",1):get_count() .."]"
373 .."list[nodemeta:" .. spos .. ";give2;3,0;1,1;]"
374 .."item_image_button[3,1;1,1;".. inv:get_stack("pay2",1):get_name() ..";buy2;\n\n\b\b\b\b\b" .. inv:get_stack("pay2",1):get_count() .."]"
375 .."list[nodemeta:" .. spos .. ";give3;4,0;1,1;]"
376 .."item_image_button[4,1;1,1;".. inv:get_stack("pay3",1):get_name() ..";buy3;\n\n\b\b\b\b\b" .. inv:get_stack("pay3",1):get_count() .."]"
377 .."list[nodemeta:" .. spos .. ";give4;5,0;1,1;]"
378 .."item_image_button[5,1;1,1;".. inv:get_stack("pay4",1):get_name() ..";buy4;\n\n\b\b\b\b\b" .. inv:get_stack("pay4",1):get_count() .."]"
379 end
380 minetest.after((0.1), function(gui)
381 return minetest.show_formspec(player:get_player_name(), "smartshop.showform",gui)
382 end, gui)
383 end
384
385 minetest.register_node("smartshop:shop", {
386 description = "Smartshop",
387 tiles = {"default_chest_top.png^[colorize:#ffffff77^default_obsidian_glass.png"},
388 groups = {choppy = 2, oddly_breakable_by_hand = 1,tubedevice = 1, tubedevice_receiver = 1},
389 drawtype="nodebox",
390 node_box = {type="fixed",fixed={-0.5,-0.5,-0.0,0.5,0.5,0.5}},
391 paramtype2="facedir",
392 paramtype = "light",
393 sunlight_propagates = true,
394 light_source = 10,
395 tube = {insert_object = function(pos, node, stack, direction)
396 local meta = minetest.get_meta(pos)
397 local inv = meta:get_inventory()
398 local added = inv:add_item("main", stack)
399 smartshop.update_info(pos)
400 return added
401 end,
402 can_insert = function(pos, node, stack, direction)
403 local meta = minetest.get_meta(pos)
404 local inv = meta:get_inventory()
405 for i=1,4 do
406 local sellitem = inv:get_stack("give"..i,1):get_name()
407 if sellitem == stack:get_name() then
408 return inv:room_for_item("main", stack)
409 end
410 -- minetest.chat_send_all(sellitem)
411 end
412 --
413 return false
414 end,
415 input_inventory = "main",
416 connect_sides = {left = 1, right = 1, front = 1, back = 1, top = 1, bottom = 1}},
417 after_place_node = function(pos, placer)
418 local meta=minetest.get_meta(pos)
419 meta:set_string("owner",placer:get_player_name())
420 meta:set_string("infotext", "Shop by: " .. placer:get_player_name())
421 meta:set_int("type",1)
422 if minetest.check_player_privs(placer:get_player_name(), {creative=true}) or minetest.check_player_privs(placer:get_player_name(), {give=true}) then
423 meta:set_int("creative",1)
424 meta:set_int("type",0)
425 end
426 end,
427 on_construct = function(pos)
428 local meta=minetest.get_meta(pos)
429 meta:set_int("state", 0)
430 meta:get_inventory():set_size("main", 32)
431 meta:get_inventory():set_size("give1", 1)
432 meta:get_inventory():set_size("pay1", 1)
433 meta:get_inventory():set_size("give2", 1)
434 meta:get_inventory():set_size("pay2", 1)
435 meta:get_inventory():set_size("give3", 1)
436 meta:get_inventory():set_size("pay3", 1)
437 meta:get_inventory():set_size("give4", 1)
438 meta:get_inventory():set_size("pay4", 1)
439 meta:set_int("ghost", 1)
440 end,
441 on_rightclick = function(pos, node, player, itemstack, pointed_thing)
442 smartshop.showform(pos,player)
443 end,
444 allow_metadata_inventory_put = function(pos, listname, index, stack, player)
445 if minetest.get_meta(pos):get_string("owner")==player:get_player_name() or minetest.check_player_privs(player:get_player_name(), {protection_bypass=true}) then
446 local meta = minetest.get_meta(pos)
447 if meta:get_int("ghost") == 1 and (string.find(listname, "pay") or string.find(listname, "give")) then
448 local inv = minetest.get_inventory({type="node", pos=pos})
449 -- minetest.chat_send_all( inv:get_stack(listname, index):get_name()..stack:get_name())
450 if inv:get_stack(listname, index):get_name() == stack:get_name() then
451 inv:add_item(listname, stack)
452 else
453 inv:set_stack(listname, index, stack)
454 end
455 return 0
456 end
457 return stack:get_count()
458 end
459 return 0
460 end,
461 allow_metadata_inventory_take = function(pos, listname, index, stack, player)
462 if minetest.get_meta(pos):get_string("owner")==player:get_player_name() or minetest.check_player_privs(player:get_player_name(), {protection_bypass=true}) then
463 local meta = minetest.get_meta(pos)
464 if meta:get_int("ghost") == 1 and (string.find(listname, "pay") or string.find(listname, "give")) then
465 local inv = minetest.get_inventory({type="node", pos=pos})
466 inv:set_stack(listname, index, ItemStack(""))
467 return 0
468 end
469 return stack:get_count()
470 end
471 return 0
472 end,
473 allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
474 if minetest.get_meta(pos):get_string("owner")==player:get_player_name() or minetest.check_player_privs(player:get_player_name(), {protection_bypass=true}) then
475 local meta = minetest.get_meta(pos)
476 local inv = minetest.get_inventory({type="node", pos=pos})
477 if meta:get_int("ghost") ~= 1 then
478 return count
479 end
480 if (string.find(from_list, "pay") or string.find(from_list, "give")) and to_list == "main" then
481 inv:set_stack(from_list, from_index, ItemStack(""))
482 return 0
483 elseif (string.find(to_list, "pay") or string.find(to_list, "give")) and from_list == "main" then
484 if inv:get_stack(to_list, to_index):get_name() == inv:get_stack(from_list, from_index):get_name() then
485 inv:add_item(to_list, inv:get_stack(from_list, from_index))
486 else
487 inv:set_stack(to_list, to_index, inv:get_stack(from_list, from_index))
488 inv:set_stack(from_list, from_index, inv:get_stack(from_list, from_index))
489 end
490 return 0
491 else
492 return count
493 end
494 end
495 return 0
496 end,
497 can_dig = function(pos, player)
498 local meta=minetest.get_meta(pos)
499 local inv=meta:get_inventory()
500 if ((meta:get_string("owner")==player:get_player_name() or minetest.check_player_privs(player:get_player_name(), {protection_bypass=true})) and inv:is_empty("main") and inv:is_empty("pay1") and inv:is_empty("pay2") and inv:is_empty("pay3") and inv:is_empty("pay4") and inv:is_empty("give1") and inv:is_empty("give2") and inv:is_empty("give3") and inv:is_empty("give4")) or meta:get_string("owner")=="" then
501 smartshop.update(pos,"clear")
502 return true
503 end
504 end,
505 })
506
507 smartshop.get_item_count = function(name)
508 sum = 0
509 if smartshop.itemstats[name] == nil then
510 return 0
511 end
512 for i, k in pairs(smartshop.itemstats[name]) do
513 sum = sum + k
514 end
515 return sum
516 end
517
518 smartshop.get_shop_count = function(name)
519 sum = 0
520 if smartshop.itemstats[name] == nil then
521 return 0
522 end
523 for i, k in pairs(smartshop.itemstats[name]) do
524 sum = sum + 1
525 end
526 return sum
527 end
528
529 smartshop.get_item_price = function(name)
530 sum = smartshop.get_item_count(name)
531 if smartshop.itemprices[name] == nil then
532 return 0
533 end
534 if sum == 0 then
535 return 0
536 end
537 psum = 0
538 for i, k in pairs(smartshop.itemprices[name]) do
539 psum = psum + k*smartshop.itemstats[name][i]
540 end
541 return psum/sum
542 end
543
544
545 minetest.register_chatcommand("smstats", {
546 description = "Get number of items sold",
547 params = "<item_name>",
548 func = function(plname, params)
549 local name = params:match("(%S+)")
550 if not (name) then
551 return false, "Usage: /smstats <itemname>"
552 end
553 if not smartshop.itemstats[name] then
554 return false, "No stats on "..name
555 end
556 sum = smartshop.get_item_count(name)
557 minetest.chat_send_player(plname, "Number of items: "..sum)
558 minetest.chat_send_player(plname, "Number of shops offering item: "..smartshop.get_shop_count(name))
559 if sum == 0 then
560 return
561 end
562 price = smartshop.get_item_price(name)
563 minetest.chat_send_player(plname, "Average price: "..string.format("%.3f",price))
564 return true
565 -- local ok, e = xban.ban_player(plname, name, nil, reason)
566 -- return ok, ok and ("Banned %s."):format(plname) or e
567 end,
568 })
569
570 smartshop.report = function ()
571 local file = io.open(minetest.get_worldpath().."/smartshop_report.txt", "w")
572 if not file then
573 return false, "could not write to file"
574 end
575 for i,k in pairs(smartshop.itemstats) do
576 local count = smartshop.get_item_count(i)
577 local price = smartshop.get_item_price(i)
578 file:write(i.." "..count.." "..string.format("%.3f", price).." "..smartshop.get_shop_count(i).."\n")
579 end
580 file:close()
581 end
582
583 minetest.register_chatcommand("smreport", {
584 description = "Get number of items sold",
585 func = function(plname, params)
586 smartshop.report()
587 end,
588 })
589
590 local timer = 0
591 minetest.register_globalstep(function(dtime)
592 timer = timer + dtime;
593 if timer >= 100 then
594 smartshop.report()
595 timer = 0
596 end
597 end)
598
599
600 if false then -- This lbm is used to add pre-update smartshops to the price database. Activate with care! Warning: very slow.
601 minetest.register_lbm({
602 name = "smartshop:update",
603 nodenames = {"smartshop:shop"},
604 action = function(pos, node)
605 smartshop.update_info(pos)
606 end,
607 })
608 end
609
610 -- load itemstats
611 local file = io.open(minetest.get_worldpath().."/smartshop_itemcounts.txt", "r")
612 if file then
613 local table = minetest.deserialize(file:read("*all"))
614 if type(table) == "table" then
615 smartshop.itemstats = table
616 end
617 end
618 local file = io.open(minetest.get_worldpath().."/smartshop_itemprices.txt", "r")
619 if file then
620 local table = minetest.deserialize(file:read("*all"))
621 if type(table) == "table" then
622 smartshop.itemprices = table
623 end
624 end