]> git.lizzy.rs Git - skycraft.git/blob - trade.lua
Modularisation
[skycraft.git] / trade.lua
1 skycraft.last_trade_id = 0
2
3 skycraft.player_trades = {}
4
5 skycraft.trade = {}
6
7 skycraft.trade.__index = skycraft.trade
8
9 function skycraft.trade:new(name1, name2)
10         local o = {}
11         setmetatable(o, self)
12         o:start(name1, name2)
13         return o
14 end
15
16 function skycraft.trade:start(name1, name2)
17         skycraft.player_trades[name1] = self
18         skycraft.player_trades[name2] = self
19         self.players = {{name = name1, status = 1}, {name = name2, status = 1}}
20         self.id = skycraft.last_trade_id + 1
21         skycraft.last_trade_id = self.id
22         self.inventory = minetest.create_detached_inventory(self:get_inventory_name(), {
23                 allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
24                         local name = player:get_player_name()
25                         return (self:allow_access(from_list, name) and self:allow_access(to_list, name)) and count or 0
26                 end,
27                 allow_put = function(inv, listname, index, stack, player) return (self:allow_access(listname, player:get_player_name())) and stack:get_count() or 0 end,
28                 allow_take = function(inv, listname, index, stack, player) return (self:allow_access(listname, player:get_player_name())) and stack:get_count() or 0 end,
29         })
30         self.inventory:set_size("1", 12)
31         self.inventory:set_size("2", 12)
32         self:update_formspec()
33 end
34
35 function skycraft.trade:allow_access(list, name)
36         for i, p in pairs(self.players) do
37                 if p.name == name and tonumber(list) == i and p.status == 1 then return true end
38         end
39         return false
40 end
41
42 function skycraft.trade:get_inventory_name()
43         return "trade_" .. tostring(self.id)
44 end
45
46 function skycraft.trade:update_formspec()
47         local invname = "detached:" .. self:get_inventory_name()
48         local formspec = "size[10,9]list[current_player;main;1,5;8,4;]" .. mcl_formspec.get_itemslot_bg(1, 5, 8, 4)
49         if self.canceled then
50                 formspec = formspec
51                         .. "label[4,3;Canceled]"
52                         .. "button_exit[3,4;3,1;exit;Exit]"
53         elseif self.successfull then
54                 formspec = formspec
55                         .. "label[4,3;Successfull]"
56                         .. "button_exit[3,4;3,1;exit;Exit]"
57         else
58                 local status_buttons = {"Confirm", "Exchange"}
59                 for i, p in pairs(self.players) do
60                         local x = tostring(3 + (i - 1) * 2)
61                         formspec = formspec
62                                 .. "list[" .. invname .. ";" .. tostring(i) .. ";" .. tostring((i - 1) * 7) .. ",0;3,4;]"
63                                 .. mcl_formspec.get_itemslot_bg((i - 1) * 7, 0, 3, 4)
64                                 .. "label[" .. x .. ",0;" .. p.name .. "]"
65                                 .. "button[" .. x .. ",2;2,1;cancel_" .. tostring(i) .. ";" .. "Cancel" .. "]"
66                         if status_buttons[p.status] then
67                                 formspec = formspec
68                                 .. "button[" .. x .. ",1;2,1;accept_" .. tostring(i) .. ";" .. status_buttons[p.status] .. "]"
69                         end
70                 end
71         end
72         for _, p in pairs(self.players) do
73                 minetest.show_formspec(p.name, "skycraft:trade", formspec)
74         end
75 end
76
77 function skycraft.trade:give_inventory(name, list)
78         local player = minetest.get_player_by_name(name)
79         if not player then return end
80         local inventory = player:get_inventory()
81         local list_ref = self.inventory:get_list(list)
82         for _, itemstack in pairs(list_ref) do
83                 inventory:add_item("main", itemstack)
84                 self.inventory:remove_item(list, itemstack)
85         end
86 end
87
88 function skycraft.trade:cancel()
89         for i, p in pairs(self.players) do
90                 self:give_inventory( p.name, tostring(i))
91                 skycraft.player_trades[p.name] = nil
92         end
93         self.canceled = true
94 end
95
96 function skycraft.trade:success()
97         local list = {"2", "1"}
98         for i, p in pairs(self.players) do
99                 self:give_inventory(p.name, list[i])
100                 skycraft.player_trades[p.name] = nil
101         end
102         self.successfull = true
103 end
104
105 function skycraft.trade:click_button(name, button)
106         if button == "quit" then return self:cancel() end
107         local action = button:split("_")[1]
108         local num = tonumber(button:split("_")[2])
109         for i, p in pairs(self.players) do
110                 if name == p.name and num == i then
111                         if action == "accept" then
112                                 p.status = p.status + 1
113                         elseif action == "cancel" then
114                                 self:cancel()
115                         end
116                         break
117                 end
118         end
119         local success = true
120         for _, p in pairs(self.players) do
121                 if p.status < 3 then
122                         success = false
123                         break
124                 end
125         end
126         if success then self:success() end
127         self:update_formspec()
128 end
129
130 minetest.register_on_leaveplayer(function(player)
131         local t = skycraft.player_trades[player:get_player_name()]
132         if t then t:cancel() end
133 end)
134
135 minetest.register_on_player_receive_fields(function(player, formname, fields)
136         if formname == "skycraft:trade" then
137                 local name = player:get_player_name()
138                 local t = skycraft.player_trades[name]
139                 if not t then return end
140                 for field, _ in pairs(fields) do
141                         t:click_button(name, field)
142                 end
143         end
144 end)
145
146 skycraft.register_request_system("trade", "trade", "trading", "with", function(name1, name2)
147         skycraft.trade:new(name1, name2)
148 end)