diff options
Diffstat (limited to 'src/main')
-rwxr-xr-x | src/main/commands.lua | 56 | ||||
-rw-r--r-- | src/main/flower_spread.lua | 13 | ||||
-rw-r--r-- | src/main/lobby.lua | 72 | ||||
-rw-r--r-- | src/main/lucky_block.lua | 13 | ||||
-rw-r--r-- | src/main/mapgen.lua | 33 | ||||
-rw-r--r-- | src/main/money.lua | 41 | ||||
-rw-r--r-- | src/main/plots.lua | 180 | ||||
-rwxr-xr-x | src/main/ranks.lua | 113 | ||||
-rw-r--r-- | src/main/spawns.lua | 49 | ||||
-rw-r--r-- | src/main/tpa.lua | 8 | ||||
-rw-r--r-- | src/main/trade.lua | 148 |
11 files changed, 726 insertions, 0 deletions
diff --git a/src/main/commands.lua b/src/main/commands.lua new file mode 100755 index 0000000..892df8f --- /dev/null +++ b/src/main/commands.lua @@ -0,0 +1,56 @@ +minetest.register_chatcommand("message", { + params = "<message>[|<color>[|<player>]]", + description = "Send a optional colored message as the server to one or all players.", + privs = {server = true}, + func = function(name, param) + local param_list = param:split("|") + param_list[1] = minetest.colorize(param_list[2] or "#FFFFFF", param_list[1]) + if param_list[3] then + minetest.chat_send_player(param_list[3], param_list[1]) + else + minetest.chat_send_all(param_list[1]) + end + end, +}) + +minetest.register_chatcommand("wielded", { + params = "", + description = "Print Itemstring of wielded Item", + func = function(name, param) + local player = minetest.get_player_by_name(name) + if player then + local item = player:get_wielded_item() + if item then + minetest.chat_send_player(name, item:get_name()) + end + end + end, +}) + +minetest.register_chatcommand("sudo", { + description = "Force other players to run commands", + params = "<player> <command> <arguments...>", + privs = {server = true}, + func = function(name, param) + local target = param:split(" ")[1] + local command = param:split(" ")[2] + local argumentsdisp + local cmddef = minetest.chatcommands + local _, _, arguments = string.match(param, "([^ ]+) ([^ ]+) (.+)") + if not arguments then arguments = "" end + if target and command then + if cmddef[command] then + if minetest.get_player_by_name(target) then + if arguments == "" then argumentsdisp = arguments else argumentsdisp = " " .. arguments end + cmddef[command].func(target, arguments) + else + minetest.chat_send_player(name, minetest.colorize("#FF0000", "Invalid Player.")) + end + else + minetest.chat_send_player(name, minetest.colorize("#FF0000", "Nonexistant Command.")) + end + else + minetest.chat_send_player(name, minetest.colorize("#FF0000", "Invalid Usage.")) + end + end +}) diff --git a/src/main/flower_spread.lua b/src/main/flower_spread.lua new file mode 100644 index 0000000..cf7bf22 --- /dev/null +++ b/src/main/flower_spread.lua @@ -0,0 +1,13 @@ +minetest.register_abm({ + nodenames = {"mcl_core:dirt_with_grass"}, + interval = 300, + chance = 100, + action = function(pos, node) + pos.y = pos.y + 1 + local light = minetest.get_node_light(pos) or 0 + if minetest.get_node(pos).name == "air" and light > 12 and not minetest.find_node_near(pos, 2, {"group:flora"}) then + local flowers = {"mcl_flowers:blue_orchid", "mcl_flowers:azure_bluet", "mcl_flowers:allium", "mcl_flowers:tulip_white", "mcl_flowers:tulip_red", "mcl_flowers:tulip_pink", "mcl_flowers:tulip_orange", "mcl_flowers:oxeye_daisy", "mcl_flowers:dandelion", "mcl_flowers:poppy", "mcl_flowers:fern", "mcl_flowers:tallgrass", "mcl_flowers:double_tallgrass"} + minetest.set_node(pos, {name = flowers[math.random(#flowers)]}) + end + end +}) diff --git a/src/main/lobby.lua b/src/main/lobby.lua new file mode 100644 index 0000000..791149e --- /dev/null +++ b/src/main/lobby.lua @@ -0,0 +1,72 @@ +skycraft.lobby_pos = {x = 0, y = 10000, z = 0} + +function skycraft.join_lobby(name) + local player = minetest.get_player_by_name(name) + if not player then return false, "You have to be online to use this command" end + minetest.chat_send_all(skycraft.get_player_name(name) .. " joined the Lobby") + local pos = player:get_pos() + if pos.y < 5000 and (pos.y > 1000 or pos.y < -100) then player:get_meta():set_string("skycraft:skyblock_pos", minetest.pos_to_string(pos)) end + player:set_pos(skycraft.lobby_pos) +end + +function skycraft.join_skyblock(name) + local player = minetest.get_player_by_name(name) + if not player then return false, "You have to be online to use this command" end + local old_pos = player:get_pos() + if old_pos.y < 5000 then return false, "You are already on the Skyblock map." end + minetest.chat_send_all(skycraft.get_player_name(name) .. " joined Skyblock") + local pos = minetest.string_to_pos(player:get_meta():get_string("skycraft:skyblock_pos")) + if pos then + player:set_pos(pos) + else + skycraft.spawn_player(player) + end +end + +function skycraft.lobby_tick() + local players = minetest.get_connected_players() + for _, player in pairs(players) do + local name = player:get_player_name() + local privs = minetest.get_player_privs(name) + local pos = player:get_pos() + privs.skycraft = (pos.y < 5000 or privs.protection_bypass) and true or nil + minetest.set_player_privs(name, privs) + end + minetest.after(0.5, skycraft.lobby_tick) +end + +minetest.register_chatcommand("lobby", { + description = "Warp to the Lobby", + func = skycraft.join_lobby +}) + +minetest.register_chatcommand("skyblock", { + description = "Join Skyblock", + func = skycraft.join_skyblock +}) + +minetest.register_chatcommand("shop", { + description = "Join Skyblock", + func = function(name) + skycraft.join_lobby(name) + local player = minetest.get_player_by_name(name) + if player then + player:set_pos({x = 25, y = 10000, z = 25}) + end + end +}) + +minetest.register_on_joinplayer(function(player) + minetest.after(0.5, skycraft.join_lobby, player:get_player_name()) +end) + +minetest.register_on_punchplayer(function(player, hitter, time_from_last_punch, tool_capabilities, dir, damage) + if player:get_pos().y > 5000 then + minetest.chat_send_player(hitter:get_player_name(), minetest.colorize("#FF6737", "You can not do PvP here!")) + return true + end +end) + +minetest.register_on_player_hpchange(function(player, hp_change) + return (player:get_pos().y > 5000) and 0 or hp_change +end, true) diff --git a/src/main/lucky_block.lua b/src/main/lucky_block.lua new file mode 100644 index 0000000..93cc4c6 --- /dev/null +++ b/src/main/lucky_block.lua @@ -0,0 +1,13 @@ +minetest.override_item("lucky_block:lucky_block", { + tiles = {"skycraft_lucky_block.png"}, + inventory_image = minetest.inventorycube("skycraft_lucky_block.png"), + light_source = nil, +}) + +minetest.override_item("lucky_block:void_mirror", { + tiles = {"default_glass.png^[brighten"}, +}) + +minetest.register_alias_force("lucky_block:super_lucky_block", "lucky_block:lucky_block") + +minetest.clear_craft({output = "lucky_block:lucky_block"}) diff --git a/src/main/mapgen.lua b/src/main/mapgen.lua new file mode 100644 index 0000000..4375831 --- /dev/null +++ b/src/main/mapgen.lua @@ -0,0 +1,33 @@ +minetest.register_on_generated(function(minp, maxp) + if maxp.y < 1000 or minp.y > 5000 then return end + local vm, emin, emax = minetest.get_mapgen_object("voxelmanip") + local data = vm:get_data() + local area = VoxelArea:new({MinEdge=emin, MaxEdge=emax}) + local void_id = minetest.get_content_id("mcl_core:void") + local barrier_id = minetest.get_content_id("mcl_core:barrier") + for x = minp.x, maxp.x do + for z = minp.z, maxp.z do + local barrier = (math.mod(x, 62) == 0 or math.mod(z, 62) == 0) + local void = (maxp.y < 1500) + if barrier or void then + for y = minp.y, maxp.y do + local p_pos = area:index(x, y, z) + data[p_pos] = barrier and barrier_id or void_id + end + end + end + end + if maxp.y > 5000 or minp.y < 1000 then + for x = minp.x, maxp.x do + for z = minp.z, maxp.z do + local y = (maxp.y > 5000) and 1000 or 5000 + local p_pos = area:index(x, y, z) + data[p_pos] = barrier_id + end + end + end + vm:set_data(data) + vm:calc_lighting() + vm:update_liquids() + vm:write_to_map() +end) diff --git a/src/main/money.lua b/src/main/money.lua new file mode 100644 index 0000000..cf720b1 --- /dev/null +++ b/src/main/money.lua @@ -0,0 +1,41 @@ +function skycraft.get_money(player) + return player:get_meta():get_int("skycraft:money") +end + +function skycraft.set_money(player, value) + player:get_meta():set_int("skycraft:money", value) +end + +function skycraft.take_money(player, amount) + local name = player:get_player_name() + local money = skycraft.get_money(player) + if amount > money then + return false, minetest.chat_send_player(name, "You don't have enough money!") + end + skycraft.set_money(player, money - amount) + minetest.chat_send_player(name, minetest.colorize("#009EFF", "$" .. tostring(amount)) .. " taken from your account.") + return true +end + +function skycraft.give_money(player, amount) + skycraft.set_money(player, skycraft.get_money(player) + amount) + minetest.chat_send_player(player:get_player_name(), minetest.colorize("#009EFF", "$" .. tostring(amount)) .. " added to your account.") +end + +local money_chatcommand_def = { + description = "Show your balance", + func = function(name) + local player = minetest.get_player_by_name(name) + if not player then return false, "You need to be online to use this command" end + return true, "You have " .. minetest.colorize("#009EFF", "$" .. tostring(skycraft.get_money(player))) .. "." + end +} + +minetest.register_chatcommand("money", money_chatcommand_def) + +minetest.register_chatcommand("balance", money_chatcommand_def) + +minetest.register_on_newplayer(function(player) + skycraft.give_money(player, 200) +end) + diff --git a/src/main/plots.lua b/src/main/plots.lua new file mode 100644 index 0000000..9162879 --- /dev/null +++ b/src/main/plots.lua @@ -0,0 +1,180 @@ +skycraft.savedata.plots = skycraft.savedata.plots or {} + +skycraft.savedata.player_plotids = skycraft.savedata.player_plotids or {} + +skycraft.savedata.pos_plotids = skycraft.savedata.pos_plotids or {} + +skycraft.savedata.spiral = skycraft.savedata.spiral or { + x = 0, + y = 0, + d = 1, + m = 1, + s = true, +} + +function skycraft.get_new_spiral_pos() + local sp = skycraft.savedata.spiral + local rpos = {x = sp.x, z = sp.y} + if sp.s then + sp.x = sp.x + sp.d + if not (2 * sp.x * sp.d < sp.m) then + sp.s = false + end + else + sp.y = sp.y + sp.d + if not (2 * sp.y * sp.d < sp.m) then + sp.s = true + sp.d = -1 * sp.d + sp.m = sp.m + 1 + end + end + return rpos +end + +function skycraft.get_plot_pos_string(pos) + return tostring(pos.x) .. "," .. tostring(pos.z) +end + +function skycraft.get_plot_at_pos(pos) + return skycraft.savedata.plots[skycraft.savedata.pos_plotids[skycraft.get_plot_pos_string(vector.floor(vector.divide(pos, 62)))]] +end + +function skycraft.get_plot_by_player(name) + return skycraft.savedata.plots[skycraft.savedata.player_plotids[name]] +end + +function skycraft.claim_plot(name) + local plots = skycraft.savedata.plots + local plot = skycraft.get_new_spiral_pos() + plot.owner = name + plot.members = {} + plots[#plots + 1] = plot + skycraft.savedata.player_plotids[name] = #plots + skycraft.savedata.pos_plotids[skycraft.get_plot_pos_string(plot)] = #plots + return plot +end + +local plot_commands = { + gui = function(name, message) + message = message or "" + local plot = skycraft.get_plot_by_player(name) + local esc = minetest.formspec_escape + local formspec = "size[8,10]" + .. "label[2.5,0;" .. esc("-- Plot interface --") .. "]" + .. "label[0,1;" .. esc(message or "") .. "]" + .. "label[0,2;" .. esc("Members:") .. "]" + .. "button_exit[2.5,9.2;3,0.5;close;" .. esc("Close") .. "]" + .. "field_close_on_enter[add_member_input;false]" + + local n = 0 + for i, member in pairs(plot.members) do + formspec = formspec + .. "button[" .. (n % 4 * 2) + .. "," .. math.floor(n / 4 + 3) + .. ";1.5,.5;;" .. esc(member) .. "]" + .. "button[" .. (n % 4 * 2 + 1.25) .. "," + .. math.floor(n / 4 + 3) + .. ";.75,.5;remove_member_" .. tostring(i) .. ";X]" + n = i + end + formspec = formspec + .. "field[" .. (n % 4 * 2 + 1 / 3) .. "," + .. (math.floor(n / 4 + 3) + 1 / 3 - 0.02) + .. ";1.433,.5;add_member_input;;]" + .."button[" .. (n % 4 * 2 + 1.25) .. "," + .. math.floor(n / 4 + 3) .. ";.75,.5;add_member;+]" + minetest.show_formspec(name, "skycraft:plot_gui", formspec) + end, + help = function(name) + local c = { + {"", "Open the GUI"}, + {"gui", "Open the GUI"}, + {"help", "Show this help"}, + {"add_member <member>", "Add a player to your plot's members (Grant him/her permission to build on your island)"}, + {"remove_member <member>", "Remove a player from your plot's members (Revoke him/her permission to build on your island)"}, + {"list_members <member>", "List the members of your plot"}, + {"home", "Warp to your home plot (Only works if you aren't there already)"}, + } + for k, v in pairs(c) do c[k] = minetest.colorize("#FFF83D", "/plot " .. v[1]) .. ": " .. v[2] end + return true, table.concat(c, "\n") + end, + add_member = function(name, member) + if not member then return false, "Usage: /plot add_member <member>" end + local plot = skycraft.get_plot_by_player(name) + if not plot then return false, "You don't have a plot yet" end + local index = table.indexof(plot.members, member) + if index ~= -1 then return false, member .. " is already a member of your plot" end + table.insert(plot.members, member) + return true, member .. " added to plot members" + end, + remove_member = function(name, member) + if not member then return false, "Usage: /plot remove_member <member>" end + local plot = skycraft.get_plot_by_player(name) + if not plot then return false, "You don't have a plot yet" end + local index = table.indexof(plot.members, member) + if index == -1 then return false, member .. " isn't a member of your plot" end + table.remove(plot.members, index) + return true, member .. " removed from plot members" + end, + list_members = function(name, member) + local plot = skycraft.get_plot_by_player(name) + if not plot then return false, "You don't have a plot yet" end + if #plot.members == 0 then return true, "You plot has no members" end + return true, "Plot members: " .. table.concat(plot.members, ", ") + end, + home = function(name) + local player = minetest.get_player_by_name(name) + if not player then return false, "You have to be online to use this command" end + local pos = player:get_pos() + if pos.y > 5000 then return false, "You are not on the Skyblock map. Use /skyblock to get there" end + if pos.y < -100 then return false, "You can only use this command in the Overworld" end + local plot = skycraft.get_plot_at_pos(pos) + if plot and plot.owner == name then return false, "You are already on your home plot" end + skycraft.spawn_player(name) + return true, "Warped to your home plot" + end +} + +local plot_chatcommand_def = { + description = "Manage your plot. See /plot help for help", + param = "[<command> [...]]", + privs = {skycraft = true}, + func = function(name, param) + local cmd = param:split(" ")[1] or "gui" + local cmd_param = param:split(" ")[2] + local cmd_func = plot_commands[cmd] + if not cmd_func then return false, "Invalid command /plot " .. param .. ". See /plot help for help" end + return cmd_func(name, cmd_param) + end +} + +minetest.register_chatcommand("p", plot_chatcommand_def) + +minetest.register_chatcommand("plot", plot_chatcommand_def) + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname ~= "skycraft:plot_gui" then return end + local name = player:get_player_name() + local _, message + for i, member in pairs(skycraft.get_plot_by_player(name).members) do + if fields["remove_member_" .. tostring(i)] then + _, message = plot_commands.remove_member(name, member) + end + end + if fields.add_member and fields.add_member_input ~= "" then + _, message = plot_commands.add_member(name, fields.add_member_input) + end + if not fields.close and not fields.quit then + plot_commands.gui(name, message) + end +end) + +local old_is_protected = minetest.is_protected +function minetest.is_protected(pos, name) + local plot = skycraft.get_plot_at_pos(pos) or {members = {}} + if pos.y > 5000 or (pos.y < 1000 and pos.y > -100) or plot.owner ~= name and table.indexof(plot.members, name) == -1 then + return not minetest.check_player_privs(name, {protection_bypass = true}) + else + return old_is_protected(pos, name) + end +end diff --git a/src/main/ranks.lua b/src/main/ranks.lua new file mode 100755 index 0000000..5869edb --- /dev/null +++ b/src/main/ranks.lua @@ -0,0 +1,113 @@ +skycraft.ranks = { + player = { + privs = {"interact", "shout", "skycraft"}, + color = "#FFFFFF", + tag = "", + }, + vip = { + color = "#4FFF00", + tag = "[VIP]", + }, + mvp = { + color = "#00B6B3", + tag = "[MVP]", + }, + creative = { + privs = {"give", "fly", "fast"}, + color = "#FF9C00", + tag = "[Creative]", + }, + mod = { + privs = {"kick", "ban", "noclip", "settime", "teleport", "bring", "protection_bypass", "worldedit"}, + color = "#006BFF", + tag = "[Mod]", + }, + dev = { + privs = {"server", "privs"}, + color = "#9D00FF", + tag = "[Dev]", + }, + admin = { + color = "#FF001C", + tag = "[Admin]", + }, + owner = { + color = "#D90059", + tag = "[Owner]", + }, +} + +skycraft.offline_ranks = { + offline = { + color = "#969696", + tag = "[Offline]", + }, + console = { + color = "#000000", + tag = "[Console]", + }, +} + +function skycraft.get_rank(name) + local player = minetest.get_player_by_name(name) + if not player then + return skycraft.offline_ranks[(minetest.settings:get("name") == name) and "console" or "offline"] + end + local rank = player:get_meta():get_string("rank") + rank = (rank == "") and "player" or rank + return skycraft.ranks[rank] +end + +function skycraft.get_player_name(name, brackets) + local rank = skycraft.get_rank(name) + local rank_tag = minetest.colorize(rank.color, rank.tag) + if not brackets then + brackets = {"",""} + end + return rank_tag .. brackets[1] .. name .. brackets[2] +end + +function skycraft.update_nametag(player) + player:set_nametag_attributes({color = skycraft.get_rank(player:get_player_name()).color}) +end + +minetest.register_on_leaveplayer(function(player) + minetest.chat_send_all(skycraft.get_player_name(player:get_player_name()) .. " left the Server") + skycraft.update_nametag(player) +end) + +minetest.register_on_chat_message(function(name, message) + minetest.chat_send_all(skycraft.get_player_name(name, {"<", ">"}) .. " " .. message) + return true +end) + +minetest.register_chatcommand("rank", { + params = "<player> <rank>", + description = "Set a player's rank (owner|admin|dev|mod|creative|mvp|vip|player)", + privs = {privs = true}, + func = function(name, param) + local target = param:split(" ")[1] or "" + local target_ref = minetest.get_player_by_name(target) + local rank = param:split(" ")[2] or "" + local rank_ref = skycraft.ranks[rank] + if not rank_ref then + return false, "Invalid Rank '" .. rank .. "'." + elseif not target_ref then + return false, "Player '" .. target .. "' is not online." + else + local privs = {} + for k, v in pairs(skycraft.ranks) do + for _, priv in pairs(v.privs or {}) do + privs[priv] = true + end + if k == rank then + break + end + end + target_ref:get_meta():set_string("rank", rank) + minetest.set_player_privs(target, privs) + skycraft.update_nametag(target_ref) + return true, "The rank of '" .. target .. "' has been updated to '" .. rank .. "'." + end + end, +}) diff --git a/src/main/spawns.lua b/src/main/spawns.lua new file mode 100644 index 0000000..b389160 --- /dev/null +++ b/src/main/spawns.lua @@ -0,0 +1,49 @@ +skycraft.spawn_offset = {x = 3, y = 2, z = 0} + +skycraft.starter_mobs = {"mobs_mc:cow", "mobs_mc:sheep", "mobs_mc:pig"} + +do + local file = io.open(minetest.get_modpath("skycraft") .. "/schems/island.we", "r") + skycraft.island_schem = file:read() + file:close() +end + +skycraft.savedata.spawns = skycraft.savedata.spawns or {} + +function skycraft.get_spawn(player) + local strpos = player:get_meta():get_string("skycraft:spawn") + if not strpos == "" then return end + return minetest.string_to_pos(strpos) +end + +function skycraft.set_spawn(player, pos) + player:get_meta():set_string("skycraft:spawn", minetest.pos_to_string(pos)) +end + +function skycraft.spawn_player(player) + local spawn = skycraft.get_spawn(player) + local name = player:get_player_name() + if not spawn then + local plot = skycraft.claim_plot(name) + spawn = {x = plot.x * 62 + 31, z = plot.z * 62 + 31, y = math.random(1600, 2000)} + minetest.chat_send_player(name, "Creating Island ...") + skycraft.set_spawn(player, spawn) + local physics = player:get_physics_override() + player:set_physics_override({gravity = 0}) + minetest.after(5, function() + worldedit.deserialize(vector.add(spawn, {x = -6, y = -6, z = -4}), skycraft.island_schem) + local nametag = name .. "'s Friend" + local entity = minetest.add_entity(vector.add(spawn, {x = -4.5, y = 1, z = 1.5}), skycraft.starter_mobs[math.random(#skycraft.starter_mobs)]) + entity:get_luaentity().nametag = nametag + entity:set_properties({nametag = nametag}) + player:set_physics_override(physics) + end) + end + player:set_pos(vector.add(spawn, skycraft.spawn_offset)) +end + +minetest.register_on_respawnplayer(function(player) + local spawn = mcl_spawn.get_spawn_pos(player) + player:set_pos(spawn) + return true +end) diff --git a/src/main/tpa.lua b/src/main/tpa.lua new file mode 100644 index 0000000..5489d96 --- /dev/null +++ b/src/main/tpa.lua @@ -0,0 +1,8 @@ +skycraft.register_request_system("tpa", "teleport", "teleporting", "to", function(target, name) + local player = minetest.get_player_by_name(name) + local pos = player:get_pos() + local target_pos = minetest.get_player_by_name(target):get_pos() + minetest.sound_play("whoosh", {pos = pos, gain = 0.5, max_hear_distance = 10}) + minetest.sound_play("whoosh", {pos = target_pos, gain = 0.5, max_hear_distance = 10}) + player:set_pos(skycraft.find_free_position_near(target_pos)) +end) diff --git a/src/main/trade.lua b/src/main/trade.lua new file mode 100644 index 0000000..dcd3ae7 --- /dev/null +++ b/src/main/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) |