aboutsummaryrefslogtreecommitdiff
path: root/trade.lua
diff options
context:
space:
mode:
Diffstat (limited to 'trade.lua')
-rw-r--r--trade.lua148
1 files changed, 148 insertions, 0 deletions
diff --git a/trade.lua b/trade.lua
new file mode 100644
index 0000000..dcd3ae7
--- /dev/null
+++ b/trade.lua
@@ -0,0 +1,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)