added patch from SmallJoker
authorGabriel Pérez-Cerezo <gabriel@gpcf.eu>
Wed, 11 Jul 2018 14:30:44 +0000 (16:30 +0200)
committerGabriel Pérez-Cerezo <gabriel@gpcf.eu>
Wed, 11 Jul 2018 14:30:44 +0000 (16:30 +0200)
init.lua

index 2c3fc8d..b54edc7 100644 (file)
--- a/init.lua
+++ b/init.lua
-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={\r
-{{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}},\r
-{{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}},\r
-{{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}},\r
-{{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}}}\r
-}\r
-\r
--- table with itemname: number of items being traded\r
-smartshop.itemstats = {}\r
-smartshop.itemprices = {}\r
-smartshop.stuffsold = {}\r
-\r
-\r
-\r
-smartshop.itemsatpos = function(pos, item, count)\r
-   -- set number of items of type 'item' sold at position 'pos'\r
-   if smartshop.itemstats[item] == nil then\r
-      smartshop.itemstats[item] = {}\r
-   end\r
-   smartshop.itemstats[item][pos] = count\r
-   local file = io.open(minetest.get_worldpath().."/smartshop_itemcounts.txt", "w")\r
-   if file then\r
-      file:write(minetest.serialize(smartshop.itemstats))\r
-      file:close()\r
-   end\r
-end\r
-\r
-smartshop.itempriceatpos = function(pos, item, price)\r
-   -- set number of items of type 'item' sold at position 'pos'\r
-   if smartshop.itemprices[item] == nil then\r
-      smartshop.itemprices[item] = {}\r
-   end\r
-   local file = io.open(minetest.get_worldpath().."/smartshop_itemprices.txt", "w")\r
-   if file then\r
-      file:write(minetest.serialize(smartshop.itemprices))\r
-      file:close()\r
-   end\r
-   smartshop.itemprices[item][pos] = price\r
-end\r
-\r
-smartshop.minegeldtonumber = function(stack)\r
-   -- return number of minegeld in stack, returns nil if stack is not composed of minegeld\r
-   count = stack:get_count()\r
-   if count == 0 then\r
-      return 0\r
-   end\r
-   if stack:get_name() == "currency:minegeld" then\r
-      return count\r
-   elseif stack:get_name() == "currency:minegeld_5" then\r
-      return count * 5\r
-   elseif stack:get_name() == "currency:minegeld_10" then\r
-      return count * 10\r
-   else\r
-      return nil\r
-   end\r
-end\r
-\r
-\r
-minetest.register_craft({\r
-       output = "smartshop:shop",\r
-       recipe = {\r
-               {"default:chest_locked", "default:chest_locked", "default:chest_locked"},\r
-               {"default:sign_wall_wood", "default:chest_locked", "default:sign_wall_wood"},\r
-               {"default:sign_wall_wood", "default:torch", "default:sign_wall_wood"},\r
-       }\r
-})\r
-smartshop.get_human_name = function(item)\r
-   if core.registered_items[item] then\r
-      return core.registered_items[item].description\r
-   else\r
-      return "Unknown Item"\r
-   end\r
-end\r
-\r
-smartshop.use_offer=function(pos,player,n)\r
-       local pressed={}\r
-       pressed["buy" .. n]=true\r
-       smartshop.user[player:get_player_name()]=pos\r
-       smartshop.receive_fields(player,pressed)\r
-       smartshop.user[player:get_player_name()]=nil\r
-       smartshop.update(pos)\r
-end\r
-\r
-smartshop.get_offer=function(pos)\r
-       if not pos or not minetest.get_node(pos) then return end\r
-       if minetest.get_node(pos).name~="smartshop:shop" then return end\r
-       local meta=minetest.get_meta(pos)\r
-       local inv=meta:get_inventory()\r
-       local offer={}\r
-       for i=1,4,1 do\r
-               offer[i]={\r
-               give=inv:get_stack("give" .. i,1):get_name(),\r
-               give_count=inv:get_stack("give" .. i,1):get_count(),\r
-               pay=inv:get_stack("pay" .. i,1):get_name(),\r
-               pay_count=inv:get_stack("pay" .. i,1):get_count(),\r
-               }\r
-       end\r
-       return offer\r
-end\r
-\r
-smartshop.send_mail=function(owner, pos, item)\r
-   if not minetest.get_modpath( "mail" ) then\r
-      return\r
-   end\r
-   local spos = "("..pos.x..", "..pos.y..", "..pos.z..")"\r
-   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")\r
-end\r
-\r
-\r
-smartshop.receive_fields=function(player,pressed)\r
-               if pressed.customer then\r
-                       return smartshop.showform(smartshop.user[player:get_player_name()],player,true)\r
-               elseif pressed.tooglelime then\r
-                       local pos=smartshop.user[player:get_player_name()]\r
-                       local meta=minetest.get_meta(pos)\r
-                       local pname=player:get_player_name()\r
-                       if meta:get_int("type")==0 then\r
-                               meta:set_int("type",1)\r
-                               minetest.chat_send_player(pname, "Your stock is limited")\r
-                       else\r
-                               meta:set_int("type",0)\r
-                               minetest.chat_send_player(pname, "Your stock is unlimited")\r
-                       end\r
-               elseif not pressed.quit then\r
-                       local n=1\r
-                       for i=1,4,1 do\r
-                               n=i\r
-                               if pressed["buy" .. i] then break end\r
-                       end\r
-                       local pos=smartshop.user[player:get_player_name()]\r
-                       if not pos then\r
-                          return\r
-                       end\r
-                       local meta=minetest.get_meta(pos)\r
-                       local type=meta:get_int("type")\r
-                       local inv=meta:get_inventory()\r
-                       local pinv=player:get_inventory()\r
-                       local pname=player:get_player_name()\r
-                       if pressed["buy" .. n] then\r
-                               local name=inv:get_stack("give" .. n,1):get_name()\r
-                               local stack=name .." ".. inv:get_stack("give" .. n,1):get_count()\r
-                               local pay=inv:get_stack("pay" .. n,1):get_name() .." ".. inv:get_stack("pay" .. n,1):get_count()\r
-                               if name~="" then\r
-                                       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\r
-                                       if meta:get_int("ghost") ~=1 then\r
-                                          -- transition shops to ghost inventory.\r
-                                          for i=1,4 do\r
-                                             if inv:room_for_item("main", "pay"..i) and inv:room_for_item("main", "give"..i) then\r
-                                                meta:set_int("ghost", 1)\r
-                                                inv:add_item("main", inv:get_stack("pay"..i,1))\r
-                                                inv:add_item("main", inv:get_stack("give"..i,1))\r
-                                             end\r
-                                          end\r
-                                       end\r
-                                       if type==1 and inv:contains_item("main", stack)==false then\r
-                                          minetest.chat_send_player(pname, "Error: "..smartshop.get_human_name(name).." is sold out.")\r
-                                          if not meta:get_int("alerted") or meta:get_int("alerted") == 0 then\r
-                                             meta:set_int("alerted",1) -- Do not alert twice\r
-                                             smartshop.send_mail(meta:get_string("owner"), pos, name)\r
-                                          end\r
-                                          return\r
-                                       end\r
-                                       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\r
-                                       if not pinv:room_for_item("main", stack) then minetest.chat_send_player(pname, "Error: Your inventory is full, exchange aborted.") return end\r
-                                       pinv:remove_item("main", pay)\r
-                                       pinv:add_item("main", stack)\r
-                                       if type==1 then \r
-                                               inv:remove_item("main", stack)\r
-                                               inv:add_item("main", pay)\r
-                                               if not inv:contains_item("main", stack)  and (not meta:get_int("alerted") or meta:get_int("alerted") == 0) then\r
-                                                  meta:set_int("alerted",1) -- Do not alert twice\r
-                                                  smartshop.send_mail(meta:get_string("owner"), pos, name)\r
-                                               end\r
-                                       end\r
-                               end\r
-                       end\r
-               else\r
-                       local pos=smartshop.user[player:get_player_name()]\r
-                       smartshop.update_info(pos)\r
-                       if smartshop.user[player:get_player_name()] or minetest.check_player_privs(player:get_player_name(), {protection_bypass=true}) then\r
-                               local meta=minetest.get_meta(smartshop.user[player:get_player_name()])\r
-                               if meta:get_string("owner")==player:get_player_name() then\r
-                                       smartshop.update(smartshop.user[player:get_player_name()],"update")\r
-                               end\r
-                       end\r
-                       smartshop.user[player:get_player_name()]=nil\r
-               end\r
-end\r
-\r
-minetest.register_on_player_receive_fields(function(player, form, pressed)\r
-       if form=="smartshop.showform" then\r
-               smartshop.receive_fields(player,pressed)\r
-       end\r
-end)\r
-\r
-\r
-\r
-\r
-smartshop.update_info=function(pos)\r
-        if not pos then\r
-          return\r
-        end\r
-       local meta=minetest.get_meta(pos)\r
-       local spos=minetest.pos_to_string(pos)\r
-       local inv = meta:get_inventory()\r
-       local owner=meta:get_string("owner")\r
-       if meta:get_int("type")==0 then\r
-               meta:set_string("infotext","(Smartshop by " .. owner ..") Stock is unlimited")\r
-               return false\r
-       end\r
-       local name=""\r
-       local count=0\r
-       local stuff={}\r
-       for i=1,4,1 do\r
-               stuff["count" ..i]=inv:get_stack("give" .. i,1):get_count()\r
-               stuff["name" ..i]=inv:get_stack("give" .. i,1):get_name()\r
-               stuff["stock" ..i]=0 -- stuff["count" ..i]\r
-               local mg_price = smartshop.minegeldtonumber(inv:get_stack("pay" .. i,1))\r
-               if mg_price ~= nil then\r
-                  stuff["pay"..i] = mg_price/stuff["count" ..i]\r
-               end\r
-               stuff["buy" ..i]=0\r
-               for ii=1,32,1 do\r
-                       name=inv:get_stack("main",ii):get_name()\r
-                       count=inv:get_stack("main",ii):get_count()\r
-                       if name==stuff["name" ..i] then\r
-                               stuff["stock" ..i]=stuff["stock" ..i]+count\r
-                       end\r
-               end\r
-               local nstr=(stuff["stock" ..i]/stuff["count" ..i]) ..""\r
-               nstr=nstr.split(nstr, ".")\r
-               stuff["buy" ..i]=tonumber(nstr[1])\r
-               if stuff["name" ..i]=="" or stuff["buy" ..i]==0 then\r
-                       stuff["buy" ..i]=""\r
-                       stuff["name" ..i]=""\r
-                       if smartshop.stuffsold[spos..i] then\r
-                          smartshop.itemsatpos(spos, smartshop.stuffsold[spos..i], 0)\r
-                          smartshop.itempriceatpos(spos, smartshop.stuffsold[spos..i], nil)\r
-                          smartshop.stuffsold[spos..i] = nil\r
-                       end                                                \r
-               else\r
-                  smartshop.itemsatpos(spos, stuff["name"..i], stuff["buy"..i]*stuff["count" ..i])\r
-                  smartshop.itempriceatpos(spos, stuff["name"..i], stuff["pay"..i])\r
-                  smartshop.stuffsold[spos..i] = stuff["name"..i]\r
-                  stuff["name"..i] = smartshop.get_human_name(stuff["name"..i])\r
-                  stuff["buy" ..i]="(" ..stuff["buy" ..i] ..") "\r
-                  stuff["name" ..i]=stuff["name" ..i] .."\n"\r
-               end\r
-       end\r
-               meta:set_string("infotext",\r
-               "(Smartshop by " .. owner ..") Purchases left:\n"\r
-               .. stuff.buy1 ..  stuff.name1\r
-               .. stuff.buy2 ..  stuff.name2\r
-               .. stuff.buy3 ..  stuff.name3\r
-               .. stuff.buy4 ..  stuff.name4\r
-               )\r
-end\r
-\r
-\r
-\r
-\r
-smartshop.update=function(pos,stat)\r
---clear\r
-       local spos=minetest.pos_to_string(pos)\r
-       for _, ob in ipairs(minetest.env:get_objects_inside_radius(pos, 2)) do\r
-               if ob and ob:get_luaentity() and ob:get_luaentity().smartshop and ob:get_luaentity().pos==spos then\r
-                       ob:remove()     \r
-               end\r
-       end\r
-       if stat=="clear" then return end\r
---update\r
-       local meta=minetest.get_meta(pos)\r
-       local inv = meta:get_inventory()\r
-       local node=minetest.get_node(pos)\r
-       local dp = smartshop.dir[node.param2+1]\r
-       if not dp then return end\r
-       pos.x = pos.x + dp.x*0.01\r
-       pos.y = pos.y + dp.y*6.5/16\r
-       pos.z = pos.z + dp.z*0.01\r
-       for i=1,4,1 do\r
-               local item=inv:get_stack("give" .. i,1):get_name()\r
-               local pos2=smartshop.dpos[node.param2+1][i]\r
-               if item~="" then\r
-                       smartshop.tmp.item=item\r
-                       smartshop.tmp.pos=spos\r
-                       local e = minetest.env:add_entity({x=pos.x+pos2.x,y=pos.y+pos2.y,z=pos.z+pos2.z},"smartshop:item")\r
-                       e:setyaw(math.pi*2 - node.param2 * math.pi/2)\r
-               end\r
-       end\r
-end\r
-\r
-\r
-minetest.register_entity("smartshop:item",{\r
-       hp_max = 1,\r
-       visual="wielditem",\r
-       visual_size={x=.20,y=.20},\r
-       collisionbox = {0,0,0,0,0,0},\r
-       physical=false,\r
-       textures={"air"},\r
-       smartshop=true,\r
-       type="",\r
-       on_activate = function(self, staticdata)\r
-               if smartshop.tmp.item ~= nil then\r
-                       self.item=smartshop.tmp.item\r
-                       self.pos=smartshop.tmp.pos\r
-                       smartshop.tmp={}\r
-               else\r
-                       if staticdata ~= nil and staticdata ~= "" then\r
-                               local data = staticdata:split(';')\r
-                               if data and data[1] and data[2] then\r
-                                       self.item = data[1]\r
-                                       self.pos = data[2]\r
-                               end\r
-                       end\r
-               end\r
-               if self.item ~= nil then\r
-                       self.object:set_properties({textures={self.item}})\r
-               else\r
-                       self.object:remove()\r
-               end\r
-       end,\r
-       get_staticdata = function(self)\r
-               if self.item ~= nil and self.pos ~= nil then\r
-                       return self.item .. ';' ..  self.pos\r
-               end\r
-               return ""\r
-       end,\r
-})\r
-\r
-\r
-smartshop.showform=function(pos,player,re)\r
-       local meta=minetest.get_meta(pos)\r
-       local creative=meta:get_int("creative")\r
-       local inv = meta:get_inventory()\r
-       local gui=""\r
-       local spos=pos.x .. "," .. pos.y .. "," .. pos.z\r
-       local owner=meta:get_string("owner")==player:get_player_name()\r
-       if minetest.check_player_privs(player:get_player_name(), {protection_bypass=true}) then owner=true end\r
-       if re then owner=false end\r
-       smartshop.user[player:get_player_name()]=pos\r
-       if owner then\r
-               meta:set_int("alerted",0) -- Player has been there to refill\r
-               gui=""\r
-               .."size[8,10]"\r
-               .."button_exit[6,0;1.5,1;customer;Customer]"\r
-               .."label[0,0.2;Item:]"\r
-               .."label[0,1.2;Price:]"\r
-               .."list[nodemeta:" .. spos .. ";give1;2,0;1,1;]"\r
-               .."list[nodemeta:" .. spos .. ";pay1;2,1;1,1;]"\r
-               .."list[nodemeta:" .. spos .. ";give2;3,0;1,1;]"\r
-               .."list[nodemeta:" .. spos .. ";pay2;3,1;1,1;]"\r
-               .."list[nodemeta:" .. spos .. ";give3;4,0;1,1;]"\r
-               .."list[nodemeta:" .. spos .. ";pay3;4,1;1,1;]"\r
-               .."list[nodemeta:" .. spos .. ";give4;5,0;1,1;]"\r
-               .."list[nodemeta:" .. spos .. ";pay4;5,1;1,1;]"\r
-               if creative==1 then\r
-                       gui=gui .."label[0.5,-0.4;Your stock is unlimited becaouse you have creative or give]"\r
-                       .."button[6,1;2.2,1;tooglelime;Toggle limit]"\r
-               end\r
-               gui=gui\r
-               .."list[nodemeta:" .. spos .. ";main;0,2;8,4;]"\r
-               .."list[current_player;main;0,6.2;8,4;]"\r
-               .."listring[nodemeta:" .. spos .. ";main]"\r
-               .."listring[current_player;main]"\r
-       else\r
-               gui=""\r
-               .."size[8,6]"\r
-               .."list[current_player;main;0,2.2;8,4;]"\r
-               .."label[0,0.2;Item:]"\r
-               .."label[0,1.2;Price:]"\r
-               .."list[nodemeta:" .. spos .. ";give1;2,0;1,1;]"\r
-               .."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() .."]"\r
-               .."list[nodemeta:" .. spos .. ";give2;3,0;1,1;]"\r
-               .."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() .."]"\r
-               .."list[nodemeta:" .. spos .. ";give3;4,0;1,1;]"\r
-               .."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() .."]"\r
-               .."list[nodemeta:" .. spos .. ";give4;5,0;1,1;]"\r
-               .."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() .."]"\r
-       end\r
-       minetest.after((0.1), function(gui)\r
-               return minetest.show_formspec(player:get_player_name(), "smartshop.showform",gui)\r
-       end, gui)\r
-end\r
-\r
-minetest.register_node("smartshop:shop", {\r
-       description = "Smartshop",\r
-       tiles = {"default_chest_top.png^[colorize:#ffffff77^default_obsidian_glass.png"},\r
-       groups = {choppy = 2, oddly_breakable_by_hand = 1,tubedevice = 1, tubedevice_receiver = 1},\r
-       drawtype="nodebox",\r
-       node_box = {type="fixed",fixed={-0.5,-0.5,-0.0,0.5,0.5,0.5}},\r
-       paramtype2="facedir",\r
-       paramtype = "light",\r
-       sunlight_propagates = true,\r
-       light_source = 10,\r
-       tube = {insert_object = function(pos, node, stack, direction)\r
-                       local meta = minetest.get_meta(pos)\r
-                       local inv = meta:get_inventory()\r
-                       local added = inv:add_item("main", stack)\r
-                       smartshop.update_info(pos)\r
-                       return added\r
-               end,\r
-               can_insert = function(pos, node, stack, direction)\r
-                       local meta = minetest.get_meta(pos)\r
-                       local inv = meta:get_inventory()\r
-                       for i=1,4 do\r
-                          local sellitem = inv:get_stack("give"..i,1):get_name()\r
-                          if sellitem == stack:get_name() then\r
-                             return inv:room_for_item("main", stack)\r
-                          end\r
---                        minetest.chat_send_all(sellitem)\r
-                       end\r
-                       --                      \r
-                       return false\r
-               end,\r
-               input_inventory = "main",\r
-               connect_sides = {left = 1, right = 1, front = 1, back = 1, top = 1, bottom = 1}},\r
-after_place_node = function(pos, placer)\r
-               local meta=minetest.get_meta(pos)\r
-               meta:set_string("owner",placer:get_player_name())\r
-               meta:set_string("infotext", "Shop by: " .. placer:get_player_name())\r
-               meta:set_int("type",1)\r
-               if minetest.check_player_privs(placer:get_player_name(), {creative=true}) or minetest.check_player_privs(placer:get_player_name(), {give=true}) then\r
-                       meta:set_int("creative",1)\r
-                       meta:set_int("type",0)\r
-               end\r
-       end,\r
-on_construct = function(pos)\r
-               local meta=minetest.get_meta(pos)\r
-               meta:set_int("state", 0)\r
-               meta:get_inventory():set_size("main", 32)\r
-               meta:get_inventory():set_size("give1", 1)\r
-               meta:get_inventory():set_size("pay1", 1)\r
-               meta:get_inventory():set_size("give2", 1)\r
-               meta:get_inventory():set_size("pay2", 1)\r
-               meta:get_inventory():set_size("give3", 1)\r
-               meta:get_inventory():set_size("pay3", 1)\r
-               meta:get_inventory():set_size("give4", 1)\r
-               meta:get_inventory():set_size("pay4", 1)\r
-               meta:set_int("ghost", 1)\r
-       end,\r
-on_rightclick = function(pos, node, player, itemstack, pointed_thing)\r
-               smartshop.showform(pos,player)\r
-       end,\r
-allow_metadata_inventory_put = function(pos, listname, index, stack, player)\r
-   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\r
-      local meta = minetest.get_meta(pos)\r
-      if meta:get_int("ghost") == 1 and (string.find(listname, "pay") or string.find(listname, "give")) then\r
-        local inv = minetest.get_inventory({type="node", pos=pos})\r
---      minetest.chat_send_all( inv:get_stack(listname, index):get_name()..stack:get_name())\r
-        if inv:get_stack(listname, index):get_name() == stack:get_name() then\r
-           inv:add_item(listname, stack)\r
-        else\r
-           inv:set_stack(listname, index, stack)\r
-        end\r
-        return 0\r
-      end \r
-      return stack:get_count()\r
-   end\r
-   return 0\r
-end,\r
-allow_metadata_inventory_take = function(pos, listname, index, stack, player)\r
-   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\r
-      local meta = minetest.get_meta(pos)\r
-      if meta:get_int("ghost") == 1 and (string.find(listname, "pay") or string.find(listname, "give")) then\r
-        local inv = minetest.get_inventory({type="node", pos=pos})\r
-        inv:set_stack(listname, index, ItemStack(""))\r
-        return 0\r
-      end       \r
-      return stack:get_count()\r
-   end\r
-   return 0\r
-end,\r
-allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)\r
-   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\r
-      local meta = minetest.get_meta(pos)\r
-      local inv = minetest.get_inventory({type="node", pos=pos})\r
-      if meta:get_int("ghost") ~= 1 then\r
-        return count\r
-      end\r
-      if (string.find(from_list, "pay") or string.find(from_list, "give")) and to_list == "main" then\r
-        inv:set_stack(from_list, from_index, ItemStack(""))\r
-        return 0        \r
-      elseif (string.find(to_list, "pay") or string.find(to_list, "give")) and from_list == "main" then\r
-        if inv:get_stack(to_list, to_index):get_name() == inv:get_stack(from_list, from_index):get_name() then\r
-           inv:add_item(to_list, inv:get_stack(from_list, from_index))\r
-        else\r
-           inv:set_stack(to_list, to_index, inv:get_stack(from_list, from_index))\r
-           inv:set_stack(from_list, from_index, inv:get_stack(from_list, from_index))      \r
-        end\r
-        return 0\r
-      else\r
-        return count\r
-      end\r
-   end\r
-   return 0\r
-end,\r
-can_dig = function(pos, player)\r
-               local meta=minetest.get_meta(pos)\r
-               local inv=meta:get_inventory()\r
-               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\r
-                       smartshop.update(pos,"clear")\r
-                       return true\r
-               end\r
-       end,\r
-})\r
-\r
-smartshop.get_item_count = function(name)\r
-   sum = 0\r
-   if smartshop.itemstats[name] == nil then\r
-      return 0\r
-   end\r
-   for i, k in pairs(smartshop.itemstats[name]) do\r
-      sum = sum + k\r
-   end\r
-   return sum\r
-end\r
-\r
-smartshop.get_shop_count = function(name)\r
-   sum = 0\r
-   if smartshop.itemstats[name] == nil then\r
-      return 0\r
-   end\r
-   for i, k in pairs(smartshop.itemstats[name]) do\r
-      sum = sum + 1\r
-   end\r
-   return sum\r
-end\r
-\r
-smartshop.get_item_price = function(name)\r
-   sum = smartshop.get_item_count(name)\r
-   if smartshop.itemprices[name] == nil then\r
-      return 0\r
-   end\r
-   if sum == 0 then\r
-      return 0\r
-   end\r
-   psum = 0\r
-   for i, k in pairs(smartshop.itemprices[name]) do\r
-      psum = psum + k*smartshop.itemstats[name][i]\r
-   end\r
-   return psum/sum\r
-end\r
-\r
-\r
-minetest.register_chatcommand("smstats", {\r
-       description = "Get number of items sold",\r
-       params = "<item_name>",\r
-       func = function(plname, params)\r
-               local name = params:match("(%S+)")\r
-               if not (name) then\r
-                       return false, "Usage: /smstats <itemname>"\r
-               end\r
-               if not smartshop.itemstats[name] then\r
-                  return false, "No stats on "..name\r
-               end\r
-               sum = smartshop.get_item_count(name)\r
-               minetest.chat_send_player(plname, "Number of items: "..sum)\r
-               minetest.chat_send_player(plname, "Number of shops offering item: "..smartshop.get_shop_count(name))\r
-               if sum == 0 then\r
-                  return\r
-               end\r
-               price = smartshop.get_item_price(name)\r
-               minetest.chat_send_player(plname, "Average price: "..string.format("%.3f",price))\r
-               return true\r
---             local ok, e = xban.ban_player(plname, name, nil, reason)\r
---             return ok, ok and ("Banned %s."):format(plname) or e\r
-       end,\r
-})\r
-\r
-smartshop.report = function ()\r
-   local file = io.open(minetest.get_worldpath().."/smartshop_report.txt", "w")\r
-   if not file then\r
-      return false, "could not write to file"\r
-   end\r
-   for i,k in pairs(smartshop.itemstats) do\r
-      local count = smartshop.get_item_count(i)\r
-      local price = smartshop.get_item_price(i)\r
-      file:write(i.." "..count.." "..string.format("%.3f", price).." "..smartshop.get_shop_count(i).."\n")\r
-   end\r
-   file:close()\r
-end\r
-\r
-minetest.register_chatcommand("smreport", {                          \r
-       description = "Get number of items sold",\r
-       func = function(plname, params)\r
-          smartshop.report()\r
-       end,\r
-})\r
-\r
-local timer = 0\r
-minetest.register_globalstep(function(dtime)\r
-       timer = timer + dtime;\r
-       if timer >= 100 then\r
-          smartshop.report()\r
-          timer = 0\r
-       end\r
-end)\r
-\r
-\r
-if false then -- This lbm is used to add pre-update smartshops to the price database. Activate with care! Warning: very slow.\r
-   minetest.register_lbm({\r
-        name = "smartshop:update",\r
-        nodenames = {"smartshop:shop"},\r
-        action = function(pos, node)\r
-           smartshop.update_info(pos)     \r
-        end,\r
-   })\r
-end\r
-\r
--- load itemstats\r
-local file = io.open(minetest.get_worldpath().."/smartshop_itemcounts.txt", "r")\r
-if file then\r
-   local table = minetest.deserialize(file:read("*all"))\r
-   if type(table) == "table" then\r
-      smartshop.itemstats = table\r
-   end\r
-end\r
-local file = io.open(minetest.get_worldpath().."/smartshop_itemprices.txt", "r")\r
-if file then\r
-   local table = minetest.deserialize(file:read("*all"))\r
-   if type(table) == "table" then\r
-      smartshop.itemprices = table\r
-   end\r
-end\r
+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={
+{{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}},
+{{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}},
+{{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}},
+{{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}}}
+}
+
+-- table with itemname: number of items being traded
+smartshop.itemstats = {}
+smartshop.itemprices = {}
+smartshop.stuffsold = {}
+
+
+
+smartshop.itemsatpos = function(pos, item, count)
+   -- set number of items of type 'item' sold at position 'pos'
+   if smartshop.itemstats[item] == nil then
+      smartshop.itemstats[item] = {}
+   end
+   smartshop.itemstats[item][pos] = count
+   local file = io.open(minetest.get_worldpath().."/smartshop_itemcounts.txt", "w")
+   if file then
+      file:write(minetest.serialize(smartshop.itemstats))
+      file:close()
+   end
+end
+
+smartshop.itempriceatpos = function(pos, item, price)
+   -- set number of items of type 'item' sold at position 'pos'
+   if smartshop.itemprices[item] == nil then
+      smartshop.itemprices[item] = {}
+   end
+   local file = io.open(minetest.get_worldpath().."/smartshop_itemprices.txt", "w")
+   if file then
+      file:write(minetest.serialize(smartshop.itemprices))
+      file:close()
+   end
+   smartshop.itemprices[item][pos] = price
+end
+
+smartshop.minegeldtonumber = function(stack)
+   -- return number of minegeld in stack, returns nil if stack is not composed of minegeld
+   count = stack:get_count()
+   if count == 0 then
+      return 0
+   end
+   if stack:get_name() == "currency:minegeld" then
+      return count
+   elseif stack:get_name() == "currency:minegeld_5" then
+      return count * 5
+   elseif stack:get_name() == "currency:minegeld_10" then
+      return count * 10
+   else
+      return nil
+   end
+end
+
+
+minetest.register_craft({
+       output = "smartshop:shop",
+       recipe = {
+               {"default:chest_locked", "default:chest_locked", "default:chest_locked"},
+               {"default:sign_wall_wood", "default:chest_locked", "default:sign_wall_wood"},
+               {"default:sign_wall_wood", "default:torch", "default:sign_wall_wood"},
+       }
+})
+smartshop.get_human_name = function(item)
+   if core.registered_items[item] then
+      return core.registered_items[item].description
+   else
+      return "Unknown Item"
+   end
+end
+
+smartshop.use_offer=function(pos,player,n)
+       local pressed={}
+       pressed["buy" .. n]=true
+       smartshop.user[player:get_player_name()]=pos
+       smartshop.receive_fields(player,pressed)
+       smartshop.user[player:get_player_name()]=nil
+       smartshop.update(pos)
+end
+
+smartshop.get_offer=function(pos)
+       if not pos or not minetest.get_node(pos) then return end
+       if minetest.get_node(pos).name~="smartshop:shop" then return end
+       local meta=minetest.get_meta(pos)
+       local inv=meta:get_inventory()
+       local offer={}
+       for i=1,4,1 do
+               offer[i]={
+               give=inv:get_stack("give" .. i,1):get_name(),
+               give_count=inv:get_stack("give" .. i,1):get_count(),
+               pay=inv:get_stack("pay" .. i,1):get_name(),
+               pay_count=inv:get_stack("pay" .. i,1):get_count(),
+               }
+       end
+       return offer
+end
+
+smartshop.send_mail=function(owner, pos, item)
+   if not minetest.get_modpath( "mail" ) then
+      return
+   end
+   local spos = "("..pos.x..", "..pos.y..", "..pos.z..")"
+   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")
+end
+
+
+smartshop.receive_fields=function(player,pressed)
+       local pname = player:get_player_name()
+       local pos = smartshop.user[pname]
+       if not pos then
+               return
+       end
+               if pressed.customer then
+                       return smartshop.showform(pos, player, true)
+               elseif pressed.tooglelime then
+                       local meta=minetest.get_meta(pos)
+                       if meta:get_int("type")==0 then
+                               meta:set_int("type",1)
+                               minetest.chat_send_player(pname, "Your stock is limited")
+                       else
+                               meta:set_int("type",0)
+                               minetest.chat_send_player(pname, "Your stock is unlimited")
+                       end
+               elseif not pressed.quit then
+                       local n=1
+                       for i=1,4,1 do
+                               n=i
+                               if pressed["buy" .. i] then break end
+                       end
+                       local meta=minetest.get_meta(pos)
+                       local type=meta:get_int("type")
+                       local inv=meta:get_inventory()
+                       local pinv=player:get_inventory()
+                       if pressed["buy" .. n] then
+                               local name=inv:get_stack("give" .. n,1):get_name()
+                               local stack=name .." ".. inv:get_stack("give" .. n,1):get_count()
+                               local pay=inv:get_stack("pay" .. n,1):get_name() .." ".. inv:get_stack("pay" .. n,1):get_count()
+                               if name~="" then
+                                       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
+                                       if meta:get_int("ghost") ~=1 then
+                                          -- transition shops to ghost inventory.
+                                          for i=1,4 do
+                                             if inv:room_for_item("main", "pay"..i) and inv:room_for_item("main", "give"..i) then
+                                                meta:set_int("ghost", 1)
+                                                inv:add_item("main", inv:get_stack("pay"..i,1))
+                                                inv:add_item("main", inv:get_stack("give"..i,1))
+                                             end
+                                          end
+                                       end
+                                       if type==1 and inv:contains_item("main", stack)==false then
+                                          minetest.chat_send_player(pname, "Error: "..smartshop.get_human_name(name).." is sold out.")
+                                          if not meta:get_int("alerted") or meta:get_int("alerted") == 0 then
+                                             meta:set_int("alerted",1) -- Do not alert twice
+                                             smartshop.send_mail(meta:get_string("owner"), pos, name)
+                                          end
+                                          return
+                                       end
+                                       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
+                                       if not pinv:room_for_item("main", stack) then minetest.chat_send_player(pname, "Error: Your inventory is full, exchange aborted.") return end
+                                       pinv:remove_item("main", pay)
+                                       pinv:add_item("main", stack)
+                                       if type==1 then 
+                                               inv:remove_item("main", stack)
+                                               inv:add_item("main", pay)
+                                               if not inv:contains_item("main", stack)  and (not meta:get_int("alerted") or meta:get_int("alerted") == 0) then
+                                                  meta:set_int("alerted",1) -- Do not alert twice
+                                                  smartshop.send_mail(meta:get_string("owner"), pos, name)
+                                               end
+                                       end
+                               end
+                       end
+               else
+                       smartshop.update_info(pos)
+                       local meta = minetest.get_meta(pos)
+                       if meta:get_string("owner") == pname then
+                               smartshop.update(pos, "update")
+                       end
+                       smartshop.user[pname] = nil
+               end
+end
+
+minetest.register_on_player_receive_fields(function(player, form, pressed)
+       if form=="smartshop.showform" then
+               smartshop.receive_fields(player,pressed)
+       end
+end)
+
+
+
+
+smartshop.update_info=function(pos)
+        if not pos then
+          return
+        end
+       local meta=minetest.get_meta(pos)
+       local spos=minetest.pos_to_string(pos)
+       local inv = meta:get_inventory()
+       local owner=meta:get_string("owner")
+       if meta:get_int("type")==0 then
+               meta:set_string("infotext","(Smartshop by " .. owner ..") Stock is unlimited")
+               return false
+       end
+       local name=""
+       local count=0
+       local stuff={}
+       for i=1,4,1 do
+               stuff["count" ..i]=inv:get_stack("give" .. i,1):get_count()
+               stuff["name" ..i]=inv:get_stack("give" .. i,1):get_name()
+               stuff["stock" ..i]=0 -- stuff["count" ..i]
+               local mg_price = smartshop.minegeldtonumber(inv:get_stack("pay" .. i,1))
+               if mg_price ~= nil then
+                  stuff["pay"..i] = mg_price/stuff["count" ..i]
+               end
+               stuff["buy" ..i]=0
+               for ii=1,32,1 do
+                       name=inv:get_stack("main",ii):get_name()
+                       count=inv:get_stack("main",ii):get_count()
+                       if name==stuff["name" ..i] then
+                               stuff["stock" ..i]=stuff["stock" ..i]+count
+                       end
+               end
+               local nstr=(stuff["stock" ..i]/stuff["count" ..i]) ..""
+               nstr=nstr.split(nstr, ".")
+               stuff["buy" ..i]=tonumber(nstr[1])
+               if stuff["name" ..i]=="" or stuff["buy" ..i]==0 then
+                       stuff["buy" ..i]=""
+                       stuff["name" ..i]=""
+                       if smartshop.stuffsold[spos..i] then
+                          smartshop.itemsatpos(spos, smartshop.stuffsold[spos..i], 0)
+                          smartshop.itempriceatpos(spos, smartshop.stuffsold[spos..i], nil)
+                          smartshop.stuffsold[spos..i] = nil
+                       end                                                
+               else
+                  smartshop.itemsatpos(spos, stuff["name"..i], stuff["buy"..i]*stuff["count" ..i])
+                  smartshop.itempriceatpos(spos, stuff["name"..i], stuff["pay"..i])
+                  smartshop.stuffsold[spos..i] = stuff["name"..i]
+                  stuff["name"..i] = smartshop.get_human_name(stuff["name"..i])
+                  stuff["buy" ..i]="(" ..stuff["buy" ..i] ..") "
+                  stuff["name" ..i]=stuff["name" ..i] .."\n"
+               end
+       end
+               meta:set_string("infotext",
+               "(Smartshop by " .. owner ..") Purchases left:\n"
+               .. stuff.buy1 ..  stuff.name1
+               .. stuff.buy2 ..  stuff.name2
+               .. stuff.buy3 ..  stuff.name3
+               .. stuff.buy4 ..  stuff.name4
+               )
+end
+
+
+
+
+smartshop.update=function(pos,stat)
+--clear
+       local spos=minetest.pos_to_string(pos)
+       for _, ob in ipairs(minetest.env:get_objects_inside_radius(pos, 2)) do
+               if ob and ob:get_luaentity() and ob:get_luaentity().smartshop and ob:get_luaentity().pos==spos then
+                       ob:remove()     
+               end
+       end
+       if stat=="clear" then return end
+--update
+       local meta=minetest.get_meta(pos)
+       local inv = meta:get_inventory()
+       local node=minetest.get_node(pos)
+       local dp = smartshop.dir[node.param2+1]
+       if not dp then return end
+       pos.x = pos.x + dp.x*0.01
+       pos.y = pos.y + dp.y*6.5/16
+       pos.z = pos.z + dp.z*0.01
+       for i=1,4,1 do
+               local item=inv:get_stack("give" .. i,1):get_name()
+               local pos2=smartshop.dpos[node.param2+1][i]
+               if item~="" then
+                       smartshop.tmp.item=item
+                       smartshop.tmp.pos=spos
+                       local e = minetest.env:add_entity({x=pos.x+pos2.x,y=pos.y+pos2.y,z=pos.z+pos2.z},"smartshop:item")
+                       e:setyaw(math.pi*2 - node.param2 * math.pi/2)
+               end
+       end
+end
+
+
+minetest.register_entity("smartshop:item",{
+       hp_max = 1,
+       visual="wielditem",
+       visual_size={x=.20,y=.20},
+       collisionbox = {0,0,0,0,0,0},
+       physical=false,
+       textures={"air"},
+       smartshop=true,
+       type="",
+       on_activate = function(self, staticdata)
+               if smartshop.tmp.item ~= nil then
+                       self.item=smartshop.tmp.item
+                       self.pos=smartshop.tmp.pos
+                       smartshop.tmp={}
+               else
+                       if staticdata ~= nil and staticdata ~= "" then
+                               local data = staticdata:split(';')
+                               if data and data[1] and data[2] then
+                                       self.item = data[1]
+                                       self.pos = data[2]
+                               end
+                       end
+               end
+               if self.item ~= nil then
+                       self.object:set_properties({textures={self.item}})
+               else
+                       self.object:remove()
+               end
+       end,
+       get_staticdata = function(self)
+               if self.item ~= nil and self.pos ~= nil then
+                       return self.item .. ';' ..  self.pos
+               end
+               return ""
+       end,
+})
+
+
+smartshop.showform=function(pos,player,re)
+       local meta=minetest.get_meta(pos)
+       local creative=meta:get_int("creative")
+       local inv = meta:get_inventory()
+       local gui=""
+       local spos=pos.x .. "," .. pos.y .. "," .. pos.z
+       local owner=meta:get_string("owner")==player:get_player_name()
+       if minetest.check_player_privs(player:get_player_name(), {protection_bypass=true}) then owner=true end
+       if re then owner=false end
+       smartshop.user[player:get_player_name()]=pos
+       if owner then
+               meta:set_int("alerted",0) -- Player has been there to refill
+               gui=""
+               .."size[8,10]"
+               .."button_exit[6,0;1.5,1;customer;Customer]"
+               .."label[0,0.2;Item:]"
+               .."label[0,1.2;Price:]"
+               .."list[nodemeta:" .. spos .. ";give1;2,0;1,1;]"
+               .."list[nodemeta:" .. spos .. ";pay1;2,1;1,1;]"
+               .."list[nodemeta:" .. spos .. ";give2;3,0;1,1;]"
+               .."list[nodemeta:" .. spos .. ";pay2;3,1;1,1;]"
+               .."list[nodemeta:" .. spos .. ";give3;4,0;1,1;]"
+               .."list[nodemeta:" .. spos .. ";pay3;4,1;1,1;]"
+               .."list[nodemeta:" .. spos .. ";give4;5,0;1,1;]"
+               .."list[nodemeta:" .. spos .. ";pay4;5,1;1,1;]"
+               if creative==1 then
+                       gui=gui .."label[0.5,-0.4;Your stock is unlimited becaouse you have creative or give]"
+                       .."button[6,1;2.2,1;tooglelime;Toggle limit]"
+               end
+               gui=gui
+               .."list[nodemeta:" .. spos .. ";main;0,2;8,4;]"
+               .."list[current_player;main;0,6.2;8,4;]"
+               .."listring[nodemeta:" .. spos .. ";main]"
+               .."listring[current_player;main]"
+       else
+               gui=""
+               .."size[8,6]"
+               .."list[current_player;main;0,2.2;8,4;]"
+               .."label[0,0.2;Item:]"
+               .."label[0,1.2;Price:]"
+               .."list[nodemeta:" .. spos .. ";give1;2,0;1,1;]"
+               .."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() .."]"
+               .."list[nodemeta:" .. spos .. ";give2;3,0;1,1;]"
+               .."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() .."]"
+               .."list[nodemeta:" .. spos .. ";give3;4,0;1,1;]"
+               .."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() .."]"
+               .."list[nodemeta:" .. spos .. ";give4;5,0;1,1;]"
+               .."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() .."]"
+       end
+       minetest.after((0.1), function(gui)
+               return minetest.show_formspec(player:get_player_name(), "smartshop.showform",gui)
+       end, gui)
+end
+
+minetest.register_node("smartshop:shop", {
+       description = "Smartshop",
+       tiles = {"default_chest_top.png^[colorize:#ffffff77^default_obsidian_glass.png"},
+       groups = {choppy = 2, oddly_breakable_by_hand = 1,tubedevice = 1, tubedevice_receiver = 1},
+       drawtype="nodebox",
+       node_box = {type="fixed",fixed={-0.5,-0.5,-0.0,0.5,0.5,0.5}},
+       paramtype2="facedir",
+       paramtype = "light",
+       sunlight_propagates = true,
+       light_source = 10,
+       tube = {insert_object = function(pos, node, stack, direction)
+                       local meta = minetest.get_meta(pos)
+                       local inv = meta:get_inventory()
+                       local added = inv:add_item("main", stack)
+                       smartshop.update_info(pos)
+                       return added
+               end,
+               can_insert = function(pos, node, stack, direction)
+                       local meta = minetest.get_meta(pos)
+                       local inv = meta:get_inventory()
+                       for i=1,4 do
+                          local sellitem = inv:get_stack("give"..i,1):get_name()
+                          if sellitem == stack:get_name() then
+                             return inv:room_for_item("main", stack)
+                          end
+--                        minetest.chat_send_all(sellitem)
+                       end
+                       --                      
+                       return false
+               end,
+               input_inventory = "main",
+               connect_sides = {left = 1, right = 1, front = 1, back = 1, top = 1, bottom = 1}},
+after_place_node = function(pos, placer)
+               local meta=minetest.get_meta(pos)
+               meta:set_string("owner",placer:get_player_name())
+               meta:set_string("infotext", "Shop by: " .. placer:get_player_name())
+               meta:set_int("type",1)
+               if minetest.check_player_privs(placer:get_player_name(), {creative=true}) or minetest.check_player_privs(placer:get_player_name(), {give=true}) then
+                       meta:set_int("creative",1)
+                       meta:set_int("type",0)
+               end
+       end,
+on_construct = function(pos)
+               local meta=minetest.get_meta(pos)
+               meta:set_int("state", 0)
+               meta:get_inventory():set_size("main", 32)
+               meta:get_inventory():set_size("give1", 1)
+               meta:get_inventory():set_size("pay1", 1)
+               meta:get_inventory():set_size("give2", 1)
+               meta:get_inventory():set_size("pay2", 1)
+               meta:get_inventory():set_size("give3", 1)
+               meta:get_inventory():set_size("pay3", 1)
+               meta:get_inventory():set_size("give4", 1)
+               meta:get_inventory():set_size("pay4", 1)
+               meta:set_int("ghost", 1)
+       end,
+on_rightclick = function(pos, node, player, itemstack, pointed_thing)
+               smartshop.showform(pos,player)
+       end,
+allow_metadata_inventory_put = function(pos, listname, index, stack, player)
+   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
+      local meta = minetest.get_meta(pos)
+      if meta:get_int("ghost") == 1 and (string.find(listname, "pay") or string.find(listname, "give")) then
+        local inv = minetest.get_inventory({type="node", pos=pos})
+--      minetest.chat_send_all( inv:get_stack(listname, index):get_name()..stack:get_name())
+        if inv:get_stack(listname, index):get_name() == stack:get_name() then
+           inv:add_item(listname, stack)
+        else
+           inv:set_stack(listname, index, stack)
+        end
+        return 0
+      end 
+      return stack:get_count()
+   end
+   return 0
+end,
+allow_metadata_inventory_take = function(pos, listname, index, stack, player)
+   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
+      local meta = minetest.get_meta(pos)
+      if meta:get_int("ghost") == 1 and (string.find(listname, "pay") or string.find(listname, "give")) then
+        local inv = minetest.get_inventory({type="node", pos=pos})
+        inv:set_stack(listname, index, ItemStack(""))
+        return 0
+      end       
+      return stack:get_count()
+   end
+   return 0
+end,
+allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
+   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
+      local meta = minetest.get_meta(pos)
+      local inv = minetest.get_inventory({type="node", pos=pos})
+      if meta:get_int("ghost") ~= 1 then
+        return count
+      end
+      if (string.find(from_list, "pay") or string.find(from_list, "give")) and to_list == "main" then
+        inv:set_stack(from_list, from_index, ItemStack(""))
+        return 0        
+      elseif (string.find(to_list, "pay") or string.find(to_list, "give")) and from_list == "main" then
+        if inv:get_stack(to_list, to_index):get_name() == inv:get_stack(from_list, from_index):get_name() then
+           inv:add_item(to_list, inv:get_stack(from_list, from_index))
+        else
+           inv:set_stack(to_list, to_index, inv:get_stack(from_list, from_index))
+           inv:set_stack(from_list, from_index, inv:get_stack(from_list, from_index))      
+        end
+        return 0
+      else
+        return count
+      end
+   end
+   return 0
+end,
+can_dig = function(pos, player)
+               local meta=minetest.get_meta(pos)
+               local inv=meta:get_inventory()
+               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
+                       smartshop.update(pos,"clear")
+                       return true
+               end
+       end,
+})
+
+smartshop.get_item_count = function(name)
+   sum = 0
+   if smartshop.itemstats[name] == nil then
+      return 0
+   end
+   for i, k in pairs(smartshop.itemstats[name]) do
+      sum = sum + k
+   end
+   return sum
+end
+
+smartshop.get_shop_count = function(name)
+   sum = 0
+   if smartshop.itemstats[name] == nil then
+      return 0
+   end
+   for i, k in pairs(smartshop.itemstats[name]) do
+      sum = sum + 1
+   end
+   return sum
+end
+
+smartshop.get_item_price = function(name)
+   sum = smartshop.get_item_count(name)
+   if smartshop.itemprices[name] == nil then
+      return 0
+   end
+   if sum == 0 then
+      return 0
+   end
+   psum = 0
+   for i, k in pairs(smartshop.itemprices[name]) do
+      psum = psum + k*smartshop.itemstats[name][i]
+   end
+   return psum/sum
+end
+
+
+minetest.register_chatcommand("smstats", {
+       description = "Get number of items sold",
+       params = "<item_name>",
+       func = function(plname, params)
+               local name = params:match("(%S+)")
+               if not (name) then
+                       return false, "Usage: /smstats <itemname>"
+               end
+               if not smartshop.itemstats[name] then
+                  return false, "No stats on "..name
+               end
+               sum = smartshop.get_item_count(name)
+               minetest.chat_send_player(plname, "Number of items: "..sum)
+               minetest.chat_send_player(plname, "Number of shops offering item: "..smartshop.get_shop_count(name))
+               if sum == 0 then
+                  return
+               end
+               price = smartshop.get_item_price(name)
+               minetest.chat_send_player(plname, "Average price: "..string.format("%.3f",price))
+               return true
+--             local ok, e = xban.ban_player(plname, name, nil, reason)
+--             return ok, ok and ("Banned %s."):format(plname) or e
+       end,
+})
+
+smartshop.report = function ()
+   local file = io.open(minetest.get_worldpath().."/smartshop_report.txt", "w")
+   if not file then
+      return false, "could not write to file"
+   end
+   for i,k in pairs(smartshop.itemstats) do
+      local count = smartshop.get_item_count(i)
+      local price = smartshop.get_item_price(i)
+      file:write(i.." "..count.." "..string.format("%.3f", price).." "..smartshop.get_shop_count(i).."\n")
+   end
+   file:close()
+end
+
+minetest.register_chatcommand("smreport", {                          
+       description = "Get number of items sold",
+       func = function(plname, params)
+          smartshop.report()
+       end,
+})
+
+local timer = 0
+minetest.register_globalstep(function(dtime)
+       timer = timer + dtime;
+       if timer >= 100 then
+          smartshop.report()
+          timer = 0
+       end
+end)
+
+
+if false then -- This lbm is used to add pre-update smartshops to the price database. Activate with care! Warning: very slow.
+   minetest.register_lbm({
+        name = "smartshop:update",
+        nodenames = {"smartshop:shop"},
+        action = function(pos, node)
+           smartshop.update_info(pos)     
+        end,
+   })
+end
+
+-- load itemstats
+local file = io.open(minetest.get_worldpath().."/smartshop_itemcounts.txt", "r")
+if file then
+   local table = minetest.deserialize(file:read("*all"))
+   if type(table) == "table" then
+      smartshop.itemstats = table
+   end
+end
+local file = io.open(minetest.get_worldpath().."/smartshop_itemprices.txt", "r")
+if file then
+   local table = minetest.deserialize(file:read("*all"))
+   if type(table) == "table" then
+      smartshop.itemprices = table
+   end
+end