Added mail sending when stock is empty, only accept items that get sold by the shop
authorGabriel Pérez-Cerezo <gabriel@gpcf.eu>
Wed, 15 Nov 2017 13:27:17 +0000 (14:27 +0100)
committerGabriel Pérez-Cerezo <gabriel@gpcf.eu>
Wed, 15 Nov 2017 13:27:17 +0000 (14:27 +0100)
Readme.txt [new file with mode: 0644]
depends.txt [new file with mode: 0644]
init.lua [new file with mode: 0644]

diff --git a/Readme.txt b/Readme.txt
new file mode 100644 (file)
index 0000000..2ecdbfe
--- /dev/null
@@ -0,0 +1,16 @@
+Licenses: code and media CC0\r
+Version: 4r\r
+Name: smartshop\r
+Created by: UjEdwin\r
+\r
+\r
+Like the title says, this is a smart and easy shop, that will also fit everywhere.\r
+\r
+it is a mix of a vending machine, a shop, item frames and light.\r
+\r
+You can toogle it unlimited or limited if you have give or creative\r
+(unlimited will not take or add stuff to its inventory)\r
+\r
+The "All" button will lime your stock to the inventory or and the giveline, its on as default.\r
+\r
+It also works with pipeworks and aliveai
\ No newline at end of file
diff --git a/depends.txt b/depends.txt
new file mode 100644 (file)
index 0000000..d589024
--- /dev/null
@@ -0,0 +1,2 @@
+default
+mail?
diff --git a/init.lua b/init.lua
new file mode 100644 (file)
index 0000000..0969ead
--- /dev/null
+++ b/init.lua
@@ -0,0 +1,405 @@
+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
+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
+\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
+\r
+\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
+   item = ItemStack(item)\r
+   local spos = "("..pos.x..", "..pos.y..", "..pos.z..")"\r
+   mail.send("DO NOT REPLY", owner, "Out of stock at "..spos, "Your smartshop at "..spos.." is out of "..core.registered_items[item:get_name()].description..". 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.sellall 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("sellall")==0 then\r
+                               meta:set_int("sellall",1)\r
+                               minetest.chat_send_player(pname, "Sell your stock and give line")\r
+                       else\r
+                               meta:set_int("sellall",0)\r
+                               minetest.chat_send_player(pname, "Sell your stock only")\r
+                       end\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
+                       local meta=minetest.get_meta(pos)\r
+                       local type=meta:get_int("type")\r
+                       local sellall=meta:get_int("sellall")\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 owners stock is full, cant receive, exchange aborted.") return end\r
+                                       if type==1 and sellall==1 and inv:contains_item("main", stack)==false and inv:contains_item("give" .. n, stack)==true then\r
+                                               inv:add_item("main", stack)\r
+                                               inv:remove_item("give" .. n, stack)\r
+                                       end\r
+                                       if type==1 and inv:contains_item("main", stack)==false then\r
+                                          minetest.chat_send_player(pname, "Error: The owners stock is end.")\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, stack)\r
+                                          end\r
+                                          return\r
+                                       end\r
+                                       if not pinv:contains_item("main", pay) then minetest.chat_send_player(pname, "Error: You dont 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
+                                       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
+       local meta=minetest.get_meta(pos)\r
+       local inv = meta:get_inventory()\r
+       local owner=meta:get_string("owner")\r
+       local gve=0\r
+       if meta:get_int("sellall")==1 then gve=1 end\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]=gve*stuff["count" ..i]\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
+\r
+               if stuff["name" ..i]=="" or stuff["buy" ..i]==0 then\r
+                       stuff["buy" ..i]=""\r
+                       stuff["name" ..i]=""\r
+               else\r
+                       --if string.find(stuff["name" ..i],":")~=nil then\r
+                       --      stuff["name" ..i]=stuff["name" ..i].split(stuff["name" ..i],":")[2]\r
+                  --end\r
+                       stuff["name"..i] = core.registered_items[stuff["name"..i]].description\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
+               .."button[7.2,0;1,1;sellall;All]"\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
+                       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
+               meta:set_int("sellall",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
+                       meta:set_int("sellall",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
+       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
+               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
+               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
+               return count\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