From bf60a9f459da7cbf62ee1cdaf91acfe81f83b30b Mon Sep 17 00:00:00 2001
From: tchncs <tchncs@vivaldi.net>
Date: Mon, 17 Oct 2016 23:54:59 +0200
Subject: [PATCH] add mod smartshop

---
 mods/smartshop/Readme.txt  |  14 ++
 mods/smartshop/depends.txt |   1 +
 mods/smartshop/init.lua    | 267 +++++++++++++++++++++++++++++++++++++
 3 files changed, 282 insertions(+)
 create mode 100644 mods/smartshop/Readme.txt
 create mode 100644 mods/smartshop/depends.txt
 create mode 100644 mods/smartshop/init.lua

diff --git a/mods/smartshop/Readme.txt b/mods/smartshop/Readme.txt
new file mode 100644
index 00000000..e203519b
--- /dev/null
+++ b/mods/smartshop/Readme.txt
@@ -0,0 +1,14 @@
+Licenses: code LGPL 2.1 media CC BY-SA 3.0
+Version: 1r
+Name: smartshop
+Created by: UjEdwin
+
+
+Like the title says, this is a smart and easy shop, that will also fit everywhere.
+
+it is a mix of a vending machine, a shop, item frames and light.
+
+You can toogle it unlimited or limited if you have give or creative
+(unlimited will not take or add stuff to its inventory)
+
+It also works with pipeworks
\ No newline at end of file
diff --git a/mods/smartshop/depends.txt b/mods/smartshop/depends.txt
new file mode 100644
index 00000000..4ad96d51
--- /dev/null
+++ b/mods/smartshop/depends.txt
@@ -0,0 +1 @@
+default
diff --git a/mods/smartshop/init.lua b/mods/smartshop/init.lua
new file mode 100644
index 00000000..6e1d85f4
--- /dev/null
+++ b/mods/smartshop/init.lua
@@ -0,0 +1,267 @@
+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}}}
+}
+
+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.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,
+	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 re then owner=false end
+	smartshop.user[player:get_player_name()]=pos
+	if owner then
+		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 unlimeted becaouse you have creative or give]"
+			.."button[6,1;2.2,1;tooglelime;Toogle lime]"
+		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_on_player_receive_fields(function(player, form, pressed)
+	if form=="smartshop.showform" then
+		if pressed.customer  then
+			return smartshop.showform(smartshop.user[player:get_player_name()],player,true)
+		elseif pressed.tooglelime then
+			local pos=smartshop.user[player:get_player_name()]
+			local meta=minetest.get_meta(pos)
+			local pname=player:get_player_name()
+			if meta:get_int("type")==0 then
+				meta:set_int("type",1)
+				minetest.chat_send_player(pname, "Your stock is limeted")
+			else
+				meta:set_int("type",0)
+				minetest.chat_send_player(pname, "Your stock is unlimeted")
+			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 pos=smartshop.user[player:get_player_name()]
+			local meta=minetest.get_meta(pos)
+			local type=meta:get_int("type")
+			local inv = meta:get_inventory()
+			local pinv=player:get_inventory()
+			local pname=player:get_player_name()
+			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 owners stock is full, cant receive, exchange aborted.") return end
+					if type==1 and inv:contains_item("main", stack)==false then minetest.chat_send_player(pname, "Error: The owners stock is end.") return end
+					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
+					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)
+					end
+				end
+			end
+		else
+			if smartshop.user[player:get_player_name()] then
+				local meta=minetest.get_meta(smartshop.user[player:get_player_name()])
+				if meta:get_string("owner")==player:get_player_name() then
+					smartshop.update(smartshop.user[player:get_player_name()],"update")
+				end
+			end
+			smartshop.user[player:get_player_name()]=nil
+		end
+	end
+end)
+
+minetest.register_node("smartshop:shop", {
+	description = "Smartshop",
+	tiles = {"default_chest_top.png^[colorize:#ffffff77^default_obsidian_glass.png"},
+	groups = {tree = 1, 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)
+			return added
+		end,
+		can_insert = function(pos, node, stack, direction)
+			local meta = minetest.get_meta(pos)
+			local inv = meta:get_inventory()
+			return inv:room_for_item("main", stack)
+		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)
+	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() then
+		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() then
+		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() then
+		return count
+		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() 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,
+})
\ No newline at end of file
-- 
GitLab