Cleanup code

e.g. do not use table.insert because it's slow
This commit is contained in:
HybridDog 2016-03-05 11:47:35 +01:00
parent a00ab96251
commit 7fbd63a180
5 changed files with 283 additions and 342 deletions

115
atm.lua
View File

@ -14,8 +14,7 @@ button[1,1;4,1;transaction_log;Transaction Log]
local function logout(x,y)
return "button[" .. x .. "," .. y ..
";2,1;logout;Log Out]"
return "button[" .. x .. "," .. y .. ";2,1;logout;Log Out]"
end
@ -41,58 +40,48 @@ end
local function new_account_fs(p_name)
local fs = "size[4,3]"
local act_suc, err = exchange:new_account(p_name)
local fs
if not act_suc then
fs = fs .. label(0.5,0.5, "Error: " .. err)
fs = label(0.5,0.5, "Error: " .. err)
else
fs = fs .. label(0.5,0.5, "Congratulations on \nyour new account.")
fs = label(0.5,0.5, "Congratulations on \nyour new account.")
end
fs = fs .. logout(0.5,2)
return fs
return "size[4,3]" .. fs .. logout(0.5,2)
end
local function info_fs(p_name)
local balance = exchange:get_balance(p_name)
local fs = "size[4,3]"
local fs
if not balance then
fs = fs .. label(0.5,0.5, "You don't have an account.")
fs = label(0.5,0.5, "You don't have an account.")
else
fs = fs .. label(0.5,0.5, "Balance: " .. balance)
fs = label(0.5,0.5, "Balance: " .. balance)
end
fs = fs .. logout(0.5,2)
return fs
return "size[4,3]" .. fs .. logout(0.5,2)
end
local function wire_fs(p_name)
local balance = exchange:get_balance(p_name)
local fs = "size[4,5]"
fs = fs .. logout(0,4)
local fs = "size[4,5]" .. logout(0,4)
if not balance then
fs = fs .. label(0.5,0.5, "You don't have an account.")
return fs
return fs .. label(0.5,0.5, "You don't have an account.")
end
-- To prevent duplicates
fs = fs .. field(-100, -100, 0,0, "trans_id", "", unique())
fs = fs .. label(0.5,0.5, "Balance: " .. balance)
fs = fs .. field(0.5,1.5, 2,1, "recipient", "Send to:", "")
fs = fs .. field(0.5,2.5, 2,1, "amount", "Amount", "")
fs = fs .. "button[2,4;2,1;send;Send]"
return fs
return fs .. field(-100, -100, 0,0, "trans_id", "", unique()) ..
label(0.5,0.5, "Balance: " .. balance) ..
field(0.5,1.5, 2,1, "recipient", "Send to:", "") ..
field(0.5,2.5, 2,1, "amount", "Amount", "") ..
"button[2,4;2,1;send;Send]"
end
@ -101,42 +90,39 @@ local function send_fs(p_name, receiver, amt_str)
local amt = tonumber(amt_str)
if not amt or amt <= 0 then
fs = fs .. label(0.5,0.5, "Invalid transfer amount.")
fs = fs .. "button[0.5,2;2,1;wire;Back]"
return fs
if not amt
or amt <= 0 then
return fs .. label(0.5,0.5, "Invalid transfer amount.") ..
"button[0.5,2;2,1;wire;Back]"
end
local succ, err = exchange:transfer_credits(p_name, receiver, amt)
if not succ then
fs = fs .. label(0.5,0.5, "Error: " .. err)
fs = fs .. "button[0.5,2;2,1;wire;Back]"
else
fs = fs.. label(0.5,0.5, "Successfully sent "
.. amt .. " credits to " .. receiver)
fs = fs .. "button[0.5,2;2,1;wire;Back]"
return fs .. label(0.5,0.5, "Error: " .. err) ..
"button[0.5,2;2,1;wire;Back]"
end
return fs
return fs.. label(0.5,0.5, "Successfully sent " ..
amt .. " credits to " .. receiver) ..
"button[0.5,2;2,1;wire;Back]"
end
local function log_fs(p_name)
local res = { "size[8,8]label[0,0;Transaction Log]button[0,7;2,1;logout;Log Out]",
"tablecolumns[text;text]",
"table[0,1;8,6;log_table;Time,Message",
local res = {
"size[8,8]label[0,0;Transaction Log]button[0,7;2,1;logout;Log Out]",
"tablecolumns[text;text]",
"table[0,1;8,6;log_table;Time,Message",
}
local log = exchange:player_log(p_name)
for i, entry in ipairs(log) do
table.insert(res, ",")
table.insert(res, tostring(entry.Time))
table.insert(res, ",")
table.insert(res, entry.Message)
for i, entry in ipairs(exchange:player_log(p_name)) do
i = i*4
res[i] = ","
res[i+1] = tostring(entry.Time)
res[i+2] = ","
res[i+3] = entry.Message
end
table.insert(res, "]")
res[#res+1] ="]"
return table.concat(res)
end
@ -145,9 +131,9 @@ end
local trans_ids = {}
local function handle_fields(player, formname, fields)
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= atm_form then return end
if fields["quit"] then return true end
if fields.quit then return true end
local p_name = player:get_player_name()
@ -159,36 +145,33 @@ local function handle_fields(player, formname, fields)
trans_ids[p_name] = this_id
if fields["logout"] then
if fields.logout then
minetest.show_formspec(p_name, atm_form, main_menu)
end
if fields["new_account"] then
if fields.new_account then
minetest.show_formspec(p_name, atm_form, new_account_fs(p_name))
end
if fields["info"] then
if fields.info then
minetest.show_formspec(p_name, atm_form, info_fs(p_name))
end
if fields["wire"] then
if fields.wire then
minetest.show_formspec(p_name, atm_form, wire_fs(p_name))
end
if fields["send"] then
if fields.send then
minetest.show_formspec(p_name, atm_form,
send_fs(p_name, fields.recipient, fields.amount))
end
if fields["transaction_log"] then
if fields.transaction_log then
minetest.show_formspec(p_name, atm_form, log_fs(p_name))
end
return true
end
minetest.register_on_player_receive_fields(handle_fields)
end)
minetest.register_node("global_exchange:atm", {
@ -198,10 +181,8 @@ minetest.register_node("global_exchange:atm", {
"global_exchange_atm_side.png",
},
groups = {cracky=2},
on_rightclick = function(pos, node, clicker)
local p_name = clicker:get_player_name()
minetest.show_formspec(p_name, atm_form, main_menu)
on_rightclick = function(pos, _, clicker)
minetest.show_formspec(clicker:get_player_name(), atm_form, main_menu)
end,
})

View File

@ -19,37 +19,37 @@ end
local function mk_inbox_list(results, x, y, w, h)
local res = {}
table.insert(res, "textlist[")
table.insert(res, tostring(x))
table.insert(res, ",")
table.insert(res, tostring(y))
table.insert(res, ";")
table.insert(res, tostring(w))
table.insert(res, ",")
table.insert(res, tostring(h))
table.insert(res, ";result_list;")
local res = {
"textlist[",
tostring(x),
",",
tostring(y),
";",
tostring(w),
",",
tostring(h),
";result_list;"
}
for i, row in ipairs(results) do
table.insert(res, row.Amount .. " " .. row.Item)
table.insert(res, ",")
res[i*2+8] = row.Amount .. " " .. row.Item
res[i*2+9] = ","
end
table.insert(res, "]")
res[#res+1] = "]"
return table.concat(res)
end
local function mk_mail_fs(p_name, results, err_str)
fs = "size[6,8]"
fs = fs .. "label[0,0;Inbox]"
fs = "size[6,8]" ..
"label[0,0;Inbox]"
if err_str then
fs = fs .. "label[3,0;Error: " .. err_str .. "]"
end
fs = fs .. mk_inbox_list(results, 0, 1, 6, 6)
fs = fs .. "button[0,7;2,1;claim;Claim]"
return fs
return fs .. mk_inbox_list(results, 0, 1, 6, 6) ..
"button[0,7;2,1;claim;Claim]"
end
@ -58,14 +58,15 @@ local function show_mail(p_name, results, err_str)
end
local function handle_fields(player, formname, fields)
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= mailbox_form then return end
if fields["quit"] then return true end
if fields.quit then return true end
local p_name = player:get_player_name()
local idx = selected_index[p_name]
if fields["claim"] and idx then
if fields.claim
and idx then
local row = get_mail(p_name)[idx]
if row then
@ -77,7 +78,7 @@ local function handle_fields(player, formname, fields)
show_mail(p_name, get_mail(p_name), "Not enough room.")
return true
end
local succ, res = exchange:take_inbox(row.Id, row.Amount)
if not succ then
show_mail(p_name, get_mail(p_name), res)
@ -92,8 +93,8 @@ local function handle_fields(player, formname, fields)
end
end
if fields["result_list"] then
local event = minetest.explode_textlist_event(fields["result_list"])
if fields.result_list then
local event = minetest.explode_textlist_event(fields.result_list)
if event.type == "CHG" then
selected_index[p_name] = event.index
@ -101,10 +102,7 @@ local function handle_fields(player, formname, fields)
end
return true
end
minetest.register_on_player_receive_fields(handle_fields)
end)
minetest.register_node("global_exchange:mailbox", {
@ -116,7 +114,7 @@ minetest.register_node("global_exchange:mailbox", {
groups = {cracky=2},
on_rightclick = function(pos, node, clicker)
local p_name = clicker:get_player_name()
local succ, res = exchange:view_inbox(p_name)
local _,res = exchange:view_inbox(p_name)
mailbox_contents[p_name] = res
minetest.show_formspec(p_name, mailbox_form, mk_mail_fs(p_name, res))
end,

View File

@ -77,7 +77,7 @@ SELECT
AND Orders.Type = "sell"
)
FROM distinct_items;
END TRANSACTION;
]=]
@ -239,7 +239,7 @@ end
local function is_integer(num)
return math.floor(num) == num
return num%1 == 0
end
@ -248,7 +248,7 @@ local function exec_stmt(db, stmt, names)
local res = stmt:step()
stmt:reset()
if res == sqlite3.BUSY then
return false, "Database Busy."
elseif res ~= sqlite3.DONE then
@ -292,7 +292,7 @@ function exports.open_exchange(path)
transaction_log_stmt = assert(db:prepare(transaction_log_query)),
}
local ret = { db = db,
stmts = stmts,
}
@ -332,7 +332,7 @@ function ex_methods.log(self, message, recipient)
return true
end
end
-- Returns success boolean and error.
function ex_methods.new_account(self, p_name, amt)
@ -346,7 +346,7 @@ function ex_methods.new_account(self, p_name, amt)
end
db:exec("BEGIN TRANSACTION;")
local stmt = self.stmts.new_act_stmt
stmt:bind_names({
@ -385,7 +385,7 @@ function ex_methods.new_account(self, p_name, amt)
end
db:exec("COMMIT;")
return true
end
@ -394,7 +394,7 @@ end
function ex_methods.get_balance(self, p_name)
local db = self.db
local stmt = self.stmts.get_balance_stmt
stmt:bind_values(p_name)
local res = stmt:step()
@ -534,11 +534,6 @@ end
-- Returns a list of orders, sorted by price.
function ex_methods.search_orders(self, ex_name, order_type, item_name)
local params = { ex_name = ex_name,
order_type = order_type,
item_name = item_name,
}
local stmt
if order_type == "buy" then
stmt = self.stmts.search_asc_stmt
@ -546,12 +541,17 @@ function ex_methods.search_orders(self, ex_name, order_type, item_name)
stmt = self.stmts.search_desc_stmt
end
stmt:bind_names(params)
stmt:bind_names({
ex_name = ex_name,
order_type = order_type,
item_name = item_name,
})
local orders = {}
local orders,n = {},1
for tab in stmt:nrows() do
table.insert(orders, tab)
orders[n] = tab
n = n+1
end
stmt:reset()
@ -561,17 +561,15 @@ end
-- Same as above, except not sorted in any particular order.
function ex_methods.search_player_orders(self, p_name)
local params = { p_name = p_name,
}
local stmt = self.stmts.search_own_stmt
stmt:bind_names(params)
stmt:bind_names({p_name = p_name})
local orders = {}
local orders,n = {},1
for tab in stmt:nrows() do
table.insert(orders, tab)
orders[n] = tab
n = n+1
end
stmt:reset()
@ -692,31 +690,31 @@ end
-- remaining desired amount. Returns success. If succeeded, also returns amount
-- bought. If failed, returns an error message
function ex_methods.buy(self, p_name, ex_name, item_name, amount, rate)
if math.floor(amount) ~= amount then
if not is_integer(amount) then
return false, "Noninteger quantity"
elseif amount <= 0 then
return false, "Nonpositive quantity"
elseif math.floor(rate) ~= rate then
elseif not is_integer(rate) then
return false, "Noninteger rate"
elseif rate <= 0 then
return false, "Nonpositive rate"
end
local db = self.db
local bal = self:get_balance(p_name)
if not bal then
return false, "Nonexistent account."
end
if bal < amount * rate then
return false, "Not enough money."
end
db:exec("BEGIN TRANSACTION");
local remaining = amount
local del_stmt = self.stmts.del_order_stmt
@ -748,7 +746,7 @@ function ex_methods.buy(self, p_name, ex_name, item_name, amount, rate)
end
del_stmt:reset()
local ch_succ, ch_err =
local ch_succ, ch_err =
self:change_balance(poster, rate * row_amount)
if not ch_succ then
search_stmt:reset()
@ -756,7 +754,7 @@ function ex_methods.buy(self, p_name, ex_name, item_name, amount, rate)
return false, ch_err
end
local log_succ, log_err =
local log_succ, log_err =
self:log(p_name .. " bought " .. row_amount .. " "
.. item_name .. " from you. (+"
.. rate * row_amount .. ")", poster)
@ -793,7 +791,7 @@ function ex_methods.buy(self, p_name, ex_name, item_name, amount, rate)
end
red_stmt:reset()
local ch_succ, ch_err =
local ch_succ, ch_err =
self:change_balance(poster, rate * remaining)
if not ch_succ then
search_stmt:reset()
@ -801,7 +799,7 @@ function ex_methods.buy(self, p_name, ex_name, item_name, amount, rate)
return false, ch_err
end
local log_succ, log_err =
local log_succ, log_err =
self:log(p_name .. " bought " .. remaining .. " "
.. item_name .. " from you. (+"
.. rate * remaining .. ")", poster)
@ -821,7 +819,7 @@ function ex_methods.buy(self, p_name, ex_name, item_name, amount, rate)
return false, log2_err
end
remaining = 0
break
end
if remaining == 0 then break end
@ -867,20 +865,20 @@ end
-- Tries to sell to orders at the provided rate, and posts an offer with any
-- remaining desired amount. Returns success. If failed, returns an error message.
function ex_methods.sell(self, p_name, ex_name, item_name, amount, rate)
if math.floor(amount) ~= amount then
if not is_integer(amount) then
return false, "Noninteger quantity"
elseif amount <= 0 then
return false, "Nonpositive quantity"
elseif math.floor(rate) ~= rate then
elseif not is_integer(rate) then
return false, "Noninteger rate"
elseif rate <= 0 then
return false, "Nonpositive rate"
end
local db = self.db
db:exec("BEGIN TRANSACTION");
local remaining = amount
local revenue = 0
@ -913,7 +911,7 @@ function ex_methods.sell(self, p_name, ex_name, item_name, amount, rate)
end
del_stmt:reset()
local in_succ, in_err =
local in_succ, in_err =
self:put_in_inbox(poster, item_name, row_amount)
if not in_succ then
search_stmt:reset()
@ -921,7 +919,7 @@ function ex_methods.sell(self, p_name, ex_name, item_name, amount, rate)
return false, in_err
end
local log_succ, log_err =
local log_succ, log_err =
self:log(p_name .. " sold " .. row_amount .. " "
.. item_name .. " to you." , poster)
if not log_succ then
@ -958,7 +956,7 @@ function ex_methods.sell(self, p_name, ex_name, item_name, amount, rate)
end
red_stmt:reset()
local in_succ, in_err =
local in_succ, in_err =
self:put_in_inbox(poster, item_name, remaining)
if not in_succ then
search_stmt:reset()
@ -966,7 +964,7 @@ function ex_methods.sell(self, p_name, ex_name, item_name, amount, rate)
return false, in_err
end
local log_succ, log_err =
local log_succ, log_err =
self:log(p_name .. " sold " .. remaining .. " "
.. item_name .. " to you.", poster)
if not log_succ then
@ -985,8 +983,8 @@ function ex_methods.sell(self, p_name, ex_name, item_name, amount, rate)
return false, log2_err
end
remaining = 0
revenue = revenue + remaining * row.Rate
break
--revenue = revenue + remaining * row.Rate
end
if remaining == 0 then break end
@ -1018,17 +1016,17 @@ end
-- On success, returns true and a list of inbox entries.
-- On failure, returns false and an error message.
-- On failure, an error message.
function ex_methods.view_inbox(self, p_name)
local db = self.db
local stmt = self.stmts.view_inbox_stmt
stmt:bind_values(p_name)
local res = {}
local res,n = {},1
for row in stmt:nrows() do
table.insert(res, row)
res[n] = row
n = n+1
end
stmt:reset()
@ -1049,7 +1047,7 @@ function ex_methods.take_inbox(self, id, amount)
id = id,
change = amount
})
local res = get_stmt:step()
if res == sqlite3.BUSY then
@ -1066,7 +1064,7 @@ function ex_methods.take_inbox(self, id, amount)
get_stmt:reset()
db:exec("BEGIN TRANSACTION;")
if available > amount then
red_stmt:bind_names({
id = id,
@ -1115,18 +1113,18 @@ end
-- sell_volume: Number of items for sale
-- sell_min: Minimum sell rate
function ex_methods.market_summary(self)
local db = self.db
local stmt = self.stmts.summary_stmt
local res = {}
local res,n = {},1
for a in stmt:rows() do
table.insert(res, {
res[n] = {
item_name = a[1],
buy_volume = a[2],
buy_max = a[3],
sell_volume = a[4],
sell_min = a[5],
})
}
n = n+1
end
stmt:reset()
@ -1138,11 +1136,12 @@ end
function ex_methods.player_log(self, p_name)
local stmt = self.stmts.transaction_log_stmt
stmt:bind_names({ p_name = p_name })
local res = {}
local res,n = {},1
for row in stmt:nrows() do
table.insert(res, row)
res[n] = row
n = n+1
end
stmt:reset()
@ -1162,7 +1161,7 @@ function exports.test()
print("Bob: ", ex:get_balance("Bob"))
end
-- Initialize balances
if alice_bal then
ex:set_balance("Alice", 420)
@ -1178,7 +1177,7 @@ function exports.test()
print_balances()
-- Transfer a valid amount
print("Transfering 1000 credits from Bob to Alice")
@ -1207,7 +1206,7 @@ function exports.test()
local succ, err = ex:sell("Bob", "", "default:cobble", 20, 1)
print("Success: ", succ, " ", err)
print_balances()
ex:close()
end

View File

@ -3,46 +3,41 @@ local exchange = ...
local search_cooldown = 2
local summary_interval = 600
local summary_fs = ""
local function mk_summary_fs()
local summary = exchange:market_summary()
local res = {}
table.insert(res, "size[8,8]")
table.insert(res, "label[0,0;Updated Periodically]")
table.insert(res, "tablecolumns[text;text;text;text;text;text]")
table.insert(res, "table[0,1;8,6;summary_table;")
table.insert(res, "Item,Description,Buy Vol,Buy Max,Sell Vol,Sell Min")
local res = {
"size[8,8]",
"label[0,0;Updated Periodically]",
"tablecolumns[text;text;text;text;text;text]",
"table[0,1;8,6;summary_table;",
"Item,Description,Buy Vol,Buy Max,Sell Vol,Sell Min"
}
local all_items = minetest.registered_items
for i, row in ipairs(summary) do
table.insert(res, "," .. row.item_name)
local def = all_items[row.item_name]
if def then
table.insert(res, "," .. def.description)
else
table.insert(res, "," .. "Unknown Item")
end
table.insert(res, "," .. (row.buy_volume or 0))
table.insert(res, "," .. (row.buy_max or "N/A"))
table.insert(res, "," .. (row.sell_volume or 0))
table.insert(res, "," .. (row.sell_min or "N/A"))
for i, row in ipairs(exchange:market_summary()) do
local n = #res+1
res[n] = "," .. row.item_name
local def = all_items[row.item_name] or {}
res[n+1] = "," .. (def.description or "Unknown Item")
res[n+2] = "," .. (row.buy_volume or 0)
res[n+3] = "," .. (row.buy_max or "N/A")
res[n+4] = "," .. (row.sell_volume or 0)
res[n+5] = "," .. (row.sell_min or "N/A")
end
table.insert(res, "]")
table.insert(res, "button[3,7;2,1;back;Back]")
return table.concat(res)
res[#res+1] = "]"
res[#res+1] = "button[3,7;2,1;back;Back]"
summary_fs = table.concat(res)
end
local summary_fs = ""
minetest.after(0, function()
summary_fs = mk_summary_fs()
end)
minetest.after(0, mk_summary_fs)
local elapsed = 0
minetest.register_globalstep(function(dtime)
elapsed = elapsed + dtime
if elapsed >= summary_interval then
summary_fs = mk_summary_fs()
mk_summary_fs()
elapsed = 0
end
end)
@ -61,17 +56,12 @@ local main_state = {}
-- a cooldown on searches
-- sell: A boolean whether the player has sell selected
local function default_main_state()
return { old_fields = {},
search_results = {},
last_search_time = 0,
}
end
minetest.register_on_joinplayer(function(player)
main_state[player:get_player_name()] = default_main_state()
main_state[player:get_player_name()] = {
old_fields = {},
search_results = {},
last_search_time = 0,
}
end)
minetest.register_on_leaveplayer(function(player)
@ -87,16 +77,18 @@ local tablecolumns =
local function table_from_results(results, x, y, w, h, selected)
local fs_tab = {}
local fs_tab
local function insert(str)
table.insert(fs_tab, str)
fs_tab[#fs_tab+1] = str
end
insert(tablecolumns)
insert("table[" .. x .. "," .. y .. ";" .. w .. "," .. h .. ";")
insert("result_table;")
insert("Poster,Type,Item,Description,Amount,Rate")
fs_tab = {
tablecolumns,
"table[" .. x .. "," .. y .. ";" .. w .. "," .. h .. ";",
"result_table;",
"Poster,Type,Item,Description,Amount,Rate"
}
local all_items = minetest.registered_items
@ -108,11 +100,8 @@ local function table_from_results(results, x, y, w, h, selected)
insert(",")
insert(tostring(row.Item))
insert(",")
if all_items[row.Item] then
insert(all_items[row.Item].description)
else
insert("Unknown Item")
end
local def = all_items[row.Item] or {}
insert(def.description or "Unknown Item")
insert(",")
insert(tostring(row.Amount))
insert(",")
@ -130,8 +119,6 @@ end
local function mk_main_fs(p_name, new_item, err_str, success)
local fs = "size[8,9]"
local state = main_state[p_name]
if not state then return end -- Should have been initialized on player join
@ -145,21 +132,22 @@ local function mk_main_fs(p_name, new_item, err_str, success)
local bal = exchange:get_balance(p_name)
local fs
if bal then
fs = fs .. "label[0,0;Balance: " .. bal .. "]"
fs = "label[0,0;Balance: " .. bal .. "]"
else
fs = fs .. "label[0.2,0.5;Use an ATM to make your account.]"
fs = "label[0.2,0.5;Use an ATM to make your account.]"
end
fs = fs .. "button[4,0;2,1;summary;Market Summary]"
fs = fs .. "button[6,0;2,1;your_orders;Your Orders]"
fs = fs .. "field[0.2,1.5;3,1;item;Item: ;" .. item_def .. "]"
fs = fs .. "field[3.2,1.5;3,1;amount;Amount: ;" .. amount_def .. "]"
fs = fs .. "button[6,1;2,1.4;select_item;Select Item]"
fs = fs .. "checkbox[5,3;sell;Sell;" .. tostring(sell_def) .. "]"
fs = fs .. "field[0.2,2.5;2,1;rate;Rate: ;" .. rate_def .. "]"
fs = fs .. "button[2,2;2,1.4;search;Search]"
fs = fs .. "button[4,2;3,1.4;post_order;Post Order]"
fs = fs .. "button[4,0;2,1;summary;Market Summary]" ..
"button[6,0;2,1;your_orders;Your Orders]" ..
"field[0.2,1.5;3,1;item;Item: ;" .. item_def .. "]" ..
"field[3.2,1.5;3,1;amount;Amount: ;" .. amount_def .. "]" ..
"button[6,1;2,1.4;select_item;Select Item]" ..
"checkbox[5,3;sell;Sell;" .. tostring(sell_def) .. "]" ..
"field[0.2,2.5;2,1;rate;Rate: ;" .. rate_def .. "]" ..
"button[2,2;2,1.4;search;Search]" ..
"button[4,2;3,1.4;post_order;Post Order]"
if err_str then
fs = fs .. "label[0,3;Error: " .. err_str .. "]"
@ -169,27 +157,26 @@ local function mk_main_fs(p_name, new_item, err_str, success)
fs = fs .. "label[0,3;Success!]"
end
fs = fs .. table_from_results(results, 0, 4, 8, 5, selected_def)
return fs
return "size[8,9]" .. fs .. table_from_results(results, 0, 4, 8, 5, selected_def)
end
local function show_main(p_name, new_item, err_str, success)
minetest.show_formspec(p_name, main_form, mk_main_fs(p_name, new_item, err_str, success))
local function show_main(p_name, ...)
minetest.show_formspec(p_name, main_form, mk_main_fs(p_name, ...))
end
-- Something similar to creative inventory
local selectable_inventory_size = 0
local pagemax = 1
-- Create detached inventory after loading all mods
minetest.after(0, function()
local inv = minetest.create_detached_inventory("global_exchange", {
allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
allow_move = function(inv, from_list, _, to_list, _,_, player)
local p_name = player:get_player_name()
if from_list == "main" and to_list == "p_" .. p_name then
if from_list == "main"
and to_list == "p_" .. p_name then
return 1
else
return 0
@ -201,7 +188,7 @@ minetest.after(0, function()
allow_take = function()
return 0
end,
on_move = function(inv, from_list, from_index, to_list, to_index, count, player)
on_move = function(inv, _,_,_,_,_, player)
local p_name = player:get_player_name()
local p_list = "p_" .. p_name
@ -212,11 +199,14 @@ minetest.after(0, function()
end,
})
local selectable_list = {}
local selectable_list,n = {},1
for name, def in pairs(minetest.registered_items) do
if (not def.groups.not_in_creative_inventory or def.groups.not_in_creative_inventory == 0)
and def.description and def.description ~= "" then
table.insert(selectable_list, name)
if (not def.groups.not_in_creative_inventory
or def.groups.not_in_creative_inventory == 0)
and def.description
and def.description ~= "" then
selectable_list[n] = name
n = n+1
end
end
table.sort(selectable_list)
@ -225,32 +215,28 @@ minetest.after(0, function()
inv:add_item("main", ItemStack(itemstring))
end
selectable_inventory_size = #selectable_list
pagemax = math.ceil((#selectable_list - 1) / (8 * 4))
end)
minetest.register_on_joinplayer(function(player)
local big_inv = minetest.get_inventory({type="detached", name="global_exchange"})
local p_list = "p_" .. player:get_player_name()
big_inv:set_size(p_list, 1)
minetest.get_inventory({
type="detached",
name="global_exchange"
}):set_size("p_" .. player:get_player_name(), 1)
end)
local select_form = "global_exchange:select_form"
local function mk_select_formspec(p_name, start_i, pagenum)
pagenum = math.floor(pagenum)
local pagemax = math.floor((selectable_inventory_size - 1) / (8 * 4) + 1)
local p_list = "p_" .. p_name
return "size[9.3,8]" ..
"list[detached:global_exchange;main;0.3,0.5;8,4;" .. tostring(start_i) .. "]" ..
"button[0.3,4.5;1.6,1;select_prev;<<]"..
"button[6.7,4.5;1.6,1;select_next;>>]"..
"label[2.0,5.55;"..tostring(pagenum).."/"..tostring(pagemax).."]"..
"list[detached:global_exchange;" .. p_list .. ";0.3,7;1,1;]"
"label[2.0,5.55;"..tostring(math.floor(pagenum)).."/"..tostring(pagemax).."]"..
"list[detached:global_exchange;p_" .. p_name .. ";0.3,7;1,1;]"
end
@ -274,17 +260,12 @@ local own_state = {}
-- own_results: Results for own orders.
local function mk_own_orders_fs(p_name, results, selected)
local fs = "size[8,8]"
local state = main_state[p_name]
fs = fs .. "label[0.5,0.2;Your Orders]"
fs = fs .. "button[6,0;2,1;refresh;Refresh]"
fs = fs .. table_from_results(results, 0, 2, 8, 4.5, selected or "")
fs = fs .. "button[0,7;2,1;cancel;Cancel]"
fs = fs .. "button[3,7;2,1;back;Back]"
return fs
return "size[8,8]" ..
"label[0.5,0.2;Your Orders]" ..
"button[6,0;2,1;refresh;Refresh]" ..
table_from_results(results, 0, 2, 8, 4.5, selected or "") ..
"button[0,7;2,1;cancel;Cancel]" ..
"button[3,7;2,1;back;Back]"
end
@ -296,11 +277,11 @@ end
-- Returns success, and also returns an error message if failed.
local function post_order(player, ex_name, order_type, item_name, amount_str, rate_str)
local p_name = player:get_player_name()
if item_name == "" then
return false, "You must input an item"
end
if not minetest.registered_items[item_name] then
return false, "That item does not exist."
end
@ -319,7 +300,7 @@ local function post_order(player, ex_name, order_type, item_name, amount_str, ra
local p_inv = player:get_inventory()
local stack = ItemStack(item_name)
stack:set_count(amount)
if order_type == "buy" then
if not p_inv:room_for_item("main", stack) then
return false, "Not enough space in inventory."
@ -349,8 +330,7 @@ local function post_order(player, ex_name, order_type, item_name, amount_str, ra
end
local function handle_main(player, formname, fields)
if formname ~= main_form then return end
local function handle_main(player, fields)
local p_name = player:get_player_name()
local state = main_state[p_name]
local old_fields = state.old_fields
@ -359,17 +339,17 @@ local function handle_main(player, formname, fields)
old_fields[k] = v
end
if fields["select_item"] then
if fields.select_item then
show_select(p_name)
end
if fields["search"] then
if fields.search then
local now = os.time()
local last_search = state.last_search_time
if now - last_search < search_cooldown then
show_main(p_name, nil, "Please wait before searching again.")
return true
return
end
-- If the player is selling, she wants "buy" type offers.
@ -388,22 +368,18 @@ local function handle_main(player, formname, fields)
show_main(p_name)
end
if fields["sell"] then
if fields["sell"] == "true" then
state.sell = true
else
state.sell = false
end
if fields.sell then
state.sell = fields.sell == "true"
end
if fields["post_order"] then
if fields.post_order then
local now = os.time()
local last_search = state.last_search_time
if now - last_search < search_cooldown then
show_main(p_name, nil, "Please wait before posting.")
return true
return
end
local order_type
@ -412,12 +388,9 @@ local function handle_main(player, formname, fields)
else
order_type = "buy"
end
local item_name = fields["item"]
local amount_str = fields["amount"]
local rate_str = fields["rate"]
local succ, err =
post_order(player, "", order_type, item_name, amount_str, rate_str)
post_order(player, "", order_type, fields.item, fields.amount, fields.rate)
if succ then
state.search_results = {}
@ -428,17 +401,17 @@ local function handle_main(player, formname, fields)
end
if fields["result_table"] then
if fields.result_table then
local results = state.search_results
local event = minetest.explode_table_event(fields["result_table"])
local event = minetest.explode_table_event(fields.result_table)
if event.type ~= "CHG" then
return true
return
end
local index = event.row - 1
result = results[index]
if result then
old_fields.amount = tostring(result.Amount)
old_fields.rate = tostring(result.Rate)
@ -447,11 +420,11 @@ local function handle_main(player, formname, fields)
show_main(p_name)
end
if fields["summary"] then
if fields.summary then
show_summary(p_name)
end
if fields["your_orders"] then
if fields.your_orders then
if not own_state[p_name] then
own_state[p_name] = {}
end
@ -461,46 +434,37 @@ local function handle_main(player, formname, fields)
show_own_orders(p_name, o_state.own_results)
end
return true
end
local function handle_select(player, formname, fields)
if formname ~= select_form then return end
local function handle_select(player, fields)
local p_name = player:get_player_name()
local pagemax = math.floor((selectable_inventory_size - 1) / (8 * 4) + 1)
local pagenum = player_pages[p_name] or 1
if fields["select_prev"] then
if fields.select_prev then
player_pages[p_name] = math.max(1, pagenum - 1)
show_select(p_name)
elseif fields["select_next"] then
elseif fields.select_next then
player_pages[p_name] = math.min(pagemax, pagenum + 1)
show_select(p_name)
end
return true
end
local function handle_own_orders(player, formname, fields)
if formname ~= own_form then return end
local function handle_own_orders(player, fields)
local p_name = player:get_player_name()
local state = own_state[p_name] or {}
local results = state.own_results or {}
local idx = state.selected_index
if fields["refresh"] then
if fields.refresh then
state.own_results = exchange:search_player_orders(p_name) or {}
show_own_orders(p_name, state.own_results)
end
if fields["cancel"] and idx then
if fields.cancel and idx then
local row = results[idx]
if not row then return true end
local p_inv = player:get_inventory()
@ -531,39 +495,41 @@ local function handle_own_orders(player, formname, fields)
show_own_orders(p_name, state.own_results)
end
if fields["result_table"] then
local event = minetest.explode_table_event(fields["result_table"])
if fields.result_table then
local event = minetest.explode_table_event(fields.result_table)
if event.type == "CHG" then
state.selected_index = event.row - 1
show_own_orders(p_name, results, event.row)
end
end
if fields["back"] then
if fields.back then
show_main(p_name)
end
return true
end
local function handle_summary(player, formname, fields)
if formname ~= summary_form then return end
local p_name = player:get_player_name()
if fields["back"] then
show_main(p_name)
local function handle_summary(player, fields)
if fields.back then
show_main(player:get_player_name())
end
return true
end
minetest.register_on_player_receive_fields(handle_main)
minetest.register_on_player_receive_fields(handle_select)
minetest.register_on_player_receive_fields(handle_own_orders)
minetest.register_on_player_receive_fields(handle_summary)
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname == main_form then
handle_main(player, fields)
elseif formname == select_form then
handle_select(player, fields)
elseif formname == own_form then
handle_own_orders(player, fields)
elseif formname == summary_form then
handle_summary(player, fields)
else
return
end
return true
end)
minetest.register_node("global_exchange:exchange", {
@ -573,7 +539,7 @@ minetest.register_node("global_exchange:exchange", {
"global_exchange_exchange_side.png",
},
groups = {cracky=2},
on_rightclick = function(pos, node, clicker)
on_rightclick = function(_,_, clicker)
local p_name = clicker:get_player_name()
local state = main_state[p_name]
if state then

View File

@ -1,9 +1,7 @@
local modpath = minetest.get_modpath(minetest.get_current_modname()) .. "/"
local savepath = minetest.get_worldpath() .. "/global_exchange.db"
local income_str = minetest.setting_get("citizens_income")
local income = income_str and tonumber(income_str) or 10
local income = tonumber(minetest.setting_get("citizens_income")) or 10
local income_interval = 1200
@ -11,41 +9,40 @@ local income_msg = "You receive your citizen's income (+" .. income .. ")"
local next_payout = os.time() + income_interval
local ex = dofile(modpath .. "exchange.lua")
local exchange = ex.open_exchange(savepath)
local exchange = (dofile(modpath .. "exchange.lua")).open_exchange(
minetest.get_worldpath() .. "/global_exchange.db"
)
minetest.register_on_shutdown(function()
exchange:close()
exchange:close()
end)
-- Only check once in a while
local elapsed = 0
local function check_giving()
local now = os.time()
if now < next_payout then
return
end
minetest.register_globalstep(function(dtime)
elapsed = elapsed + dtime
if elapsed <= 5 then return end
next_payout = now + income_interval
elapsed = 0
for _, player in ipairs(minetest.get_connected_players()) do
local p_name = player:get_player_name()
local now = os.time()
if now < next_payout then return end
local succ = exchange:give_credits(p_name, income,
"Citizen's Income (+" .. income .. ")")
next_payout = now + income_interval
for i, player in ipairs(minetest.get_connected_players()) do
local p_name = player:get_player_name()
local succ =
exchange:give_credits(p_name, income,
"Citizen's Income (+" .. income .. ")")
if succ then
minetest.chat_send_player(p_name, income_msg)
end
if succ then
minetest.chat_send_player(p_name, income_msg)
end
end)
end
minetest.after(5, check_giving)
end
minetest.after(5, check_giving)
assert(loadfile(modpath .. "atm.lua"))(exchange)