aboutsummaryrefslogtreecommitdiff
path: root/src/main/trade.lua
blob: dcd3ae7b326547527032168686b0b72fd4f7b79b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
skycraft.last_trade_id = 0

skycraft.player_trades = {}

skycraft.trade = {}

skycraft.trade.__index = skycraft.trade

function skycraft.trade:new(name1, name2)
	local o = {}
	setmetatable(o, self)
	o:start(name1, name2)
	return o
end

function skycraft.trade:start(name1, name2)
	skycraft.player_trades[name1] = self
	skycraft.player_trades[name2] = self
	self.players = {{name = name1, status = 1}, {name = name2, status = 1}}
	self.id = skycraft.last_trade_id + 1
	skycraft.last_trade_id = self.id
	self.inventory = minetest.create_detached_inventory(self:get_inventory_name(), {
		allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
			local name = player:get_player_name()
			return (self:allow_access(from_list, name) and self:allow_access(to_list, name)) and count or 0
		end,
		allow_put = function(inv, listname, index, stack, player) return (self:allow_access(listname, player:get_player_name())) and stack:get_count() or 0 end,
		allow_take = function(inv, listname, index, stack, player) return (self:allow_access(listname, player:get_player_name())) and stack:get_count() or 0 end,
	})
	self.inventory:set_size("1", 12)
	self.inventory:set_size("2", 12)
	self:update_formspec()
end

function skycraft.trade:allow_access(list, name)
	for i, p in pairs(self.players) do
		if p.name == name and tonumber(list) == i and p.status == 1 then return true end
	end
	return false
end

function skycraft.trade:get_inventory_name()
	return "trade_" .. tostring(self.id)
end

function skycraft.trade:update_formspec()
	local invname = "detached:" .. self:get_inventory_name()
	local formspec = "size[10,9]list[current_player;main;1,5;8,4;]" .. mcl_formspec.get_itemslot_bg(1, 5, 8, 4)
	if self.canceled then
		formspec = formspec
			.. "label[4,3;Canceled]"
			.. "button_exit[3,4;3,1;exit;Exit]"
	elseif self.successfull then
		formspec = formspec
			.. "label[4,3;Successfull]"
			.. "button_exit[3,4;3,1;exit;Exit]"
	else
		local status_buttons = {"Confirm", "Exchange"}
		for i, p in pairs(self.players) do
			local x = tostring(3 + (i - 1) * 2)
			formspec = formspec
				.. "list[" .. invname .. ";" .. tostring(i) .. ";" .. tostring((i - 1) * 7) .. ",0;3,4;]"
				.. mcl_formspec.get_itemslot_bg((i - 1) * 7, 0, 3, 4)
				.. "label[" .. x .. ",0;" .. p.name .. "]"
				.. "button[" .. x .. ",2;2,1;cancel_" .. tostring(i) .. ";" .. "Cancel" .. "]"
			if status_buttons[p.status] then
				formspec = formspec
				.. "button[" .. x .. ",1;2,1;accept_" .. tostring(i) .. ";" .. status_buttons[p.status] .. "]"
			end
		end
	end
	for _, p in pairs(self.players) do
		minetest.show_formspec(p.name, "skycraft:trade", formspec)
	end
end

function skycraft.trade:give_inventory(name, list)
	local player = minetest.get_player_by_name(name)
	if not player then return end
	local inventory = player:get_inventory()
	local list_ref = self.inventory:get_list(list)
	for _, itemstack in pairs(list_ref) do
		inventory:add_item("main", itemstack)
		self.inventory:remove_item(list, itemstack)
	end
end

function skycraft.trade:cancel()
	for i, p in pairs(self.players) do
		self:give_inventory( p.name, tostring(i))
		skycraft.player_trades[p.name] = nil
	end
	self.canceled = true
end

function skycraft.trade:success()
	local list = {"2", "1"}
	for i, p in pairs(self.players) do
		self:give_inventory(p.name, list[i])
		skycraft.player_trades[p.name] = nil
	end
	self.successfull = true
end

function skycraft.trade:click_button(name, button)
	if button == "quit" then return self:cancel() end
	local action = button:split("_")[1]
	local num = tonumber(button:split("_")[2])
	for i, p in pairs(self.players) do
		if name == p.name and num == i then
			if action == "accept" then
				p.status = p.status + 1
			elseif action == "cancel" then
				self:cancel()
			end
			break
		end
	end
	local success = true
	for _, p in pairs(self.players) do
		if p.status < 3 then
			success = false
			break
		end
	end
	if success then self:success() end
	self:update_formspec()
end

minetest.register_on_leaveplayer(function(player)
	local t = skycraft.player_trades[player:get_player_name()]
	if t then t:cancel() end
end)

minetest.register_on_player_receive_fields(function(player, formname, fields)
	if formname == "skycraft:trade" then
		local name = player:get_player_name()
		local t = skycraft.player_trades[name]
		if not t then return end
		for field, _ in pairs(fields) do
			t:click_button(name, field)
		end
	end
end)

skycraft.register_request_system("trade", "trade", "trading", "with", function(name1, name2)
	skycraft.trade:new(name1, name2)
end)