diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common/common.lua | 24 | ||||
-rw-r--r-- | src/common/random.lua | 40 | ||||
-rw-r--r-- | src/common/request.lua | 61 | ||||
-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 | ||||
-rw-r--r-- | src/onload/lava_cooling.lua | 23 | ||||
-rw-r--r-- | src/onload/lobby_load.lua | 1 | ||||
-rw-r--r-- | src/onload/nether_portal.lua | 9 | ||||
-rw-r--r-- | src/onload/sapling_mutation.lua | 1 | ||||
-rw-r--r-- | src/onload/shop.lua | 49 | ||||
-rw-r--r-- | src/onload/spawn.lua | 34 | ||||
-rw-r--r-- | src/onload/void.lua | 4 |
21 files changed, 972 insertions, 0 deletions
diff --git a/src/common/common.lua b/src/common/common.lua new file mode 100644 index 0000000..2288a4d --- /dev/null +++ b/src/common/common.lua @@ -0,0 +1,24 @@ +function skycraft.get_far_node(pos) + local node = minetest.get_node(pos) + if node.name ~= "ignore" then + return node + end + minetest.get_voxel_manip():read_from_map(pos, pos) + return minetest.get_node(pos) +end + +function skycraft.find_free_position_near(pos) + local tries = { + {x = 1, y = 0, z = 0}, + {x = -1, y = 0, z = 0}, + {x = 0, y = 0, z = 1}, + {x = 0, y = 0, z = -1}, + } + for _, d in pairs(tries) do + local p = vector.add(pos, d) + if not minetest.registered_nodes[minetest.get_node(p).name].walkable then + return p, true + end + end + return pos, false +end diff --git a/src/common/random.lua b/src/common/random.lua new file mode 100644 index 0000000..4fbbed3 --- /dev/null +++ b/src/common/random.lua @@ -0,0 +1,40 @@ +skycraft.random = { + choices = {}, + probabilities = {}, + csum = {}, + sum = 0 +} + +skycraft.random.__index = skycraft.random + +function skycraft.random:new(o) + o = o or {} + setmetatable(o, self) + o.choices = {} + o.probabilities = {} + o.csum = {} + o.sum = 0 + return o +end + +function skycraft.random:calc_csum() + self.sum = 0 + for i, choice in ipairs(self.choices) do + self.sum = self.sum + self.probabilities[choice] + self.csum[choice] = self.sum + end +end + +function skycraft.random:choose() + local r = math.random() + math.random(0, self.sum - 1) + for i, choice in pairs(self.choices) do + if r < self.csum[choice] then + return choice + end + end +end + +function skycraft.random:add_choice(choice, probability) + table.insert(self.choices, choice) + self.probabilities[choice] = probability +end diff --git a/src/common/request.lua b/src/common/request.lua new file mode 100644 index 0000000..0b11163 --- /dev/null +++ b/src/common/request.lua @@ -0,0 +1,61 @@ +function skycraft.register_request_system(sysname, action, progressive, preposition, func) + local action_capital = (action:sub(1, 1)):upper() .. action:sub(2) + + local request_list = {} + + minetest.register_on_leaveplayer(function(name) + request_list[name] = nil + end) + + minetest.register_chatcommand(sysname, { + description = "Request to " .. action .. " " .. preposition .. " another player", + params = "<player>", + privs = {skycraft = true}, + func = function(name, param) + if param == "" then + return false, "Usage: /" .. sysname .. " <player>" + end + if not minetest.get_player_by_name(param) then + return false, "There is no player by that name. Keep in mind this is case-sensitive, and the player must be online" + end + request_list[param] = name + minetest.after(60, function() + if request_list[param] then + minetest.chat_send_player(name, "Request timed-out.") + minetest.chat_send_player(param, "Request timed-out.") + request_list[param] = nil + end + end) + minetest.chat_send_player(param, name .. " is requesting to " .. action .. " " .. preposition .. " you. /" .. sysname .. "accept to accept") + return true, action_capital .. " request sent! It will timeout in 60 seconds." + end + }) + + minetest.register_chatcommand(sysname .. "accept", { + description = "Accept " .. action .. " request from another player", + privs = {skycraft = true}, + func = function(name) + if not minetest.get_player_by_name(name) then return false, "You have to be online to use this command" end + local other = request_list[name] + if not other then return false, "Usage: /" .. sysname .. "accept allows you to accept " .. action .. " requests sent to you by other players" end + if not minetest.get_player_by_name(other) then return false, other .. " doesn't exist, or just disconnected/left (by timeout)." end + minetest.chat_send_player(other, action_capital .. " request accepted!") + func(name, other) + request_list[name] = nil + return true, other .. " is " .. progressive .. " " .. preposition .. " you." + end + }) + + minetest.register_chatcommand(sysname .. "deny", { + description = "Deny " .. action .." request from another player", + privs = {skycraft = true}, + func = function(name) + local other = request_list[name] + if not other then return false, "Usage: /" .. sysname .. "deny allows you to deny " .. action .. " requests sent to you by other players." end + minetest.chat_send_player(other, action_capital .. " request denied.") + request_list[name] = nil + return false, "You denied the " .. action .. " request " .. other .. " sent you." + end + }) + +end 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) diff --git a/src/onload/lava_cooling.lua b/src/onload/lava_cooling.lua new file mode 100644 index 0000000..92700af --- /dev/null +++ b/src/onload/lava_cooling.lua @@ -0,0 +1,23 @@ +skycraft.ores = skycraft.random:new() +skycraft.ores:add_choice("mcl_core:cobble", 1000) +skycraft.ores:add_choice("mcl_core:stone", 200) +skycraft.ores:add_choice("mcl_core:stone_with_coal", 31) +skycraft.ores:add_choice("mcl_core:stone_with_iron", 25) +skycraft.ores:add_choice("mcl_core:stone_with_gold", 10) +skycraft.ores:add_choice("mcl_core:stone_with_lapis", 10) +skycraft.ores:add_choice("mcl_core:stone_with_redstone", 10) +skycraft.ores:add_choice("mcl_core:stone_with_diamond", 5) +skycraft.ores:calc_csum() + +for k, v in pairs(minetest.registered_abms) do + if v.label == "Lava cooling" then + local old_func = v.action + v.action = function(pos, node, active_object_count, active_object_count_wider) + old_func(pos, node, active_object_count, active_object_count_wider) + if minetest.get_node(pos).name == "mcl_core:cobble" then + minetest.set_node(pos, {name = skycraft.ores:choose()}) + end + end + break + end +end diff --git a/src/onload/lobby_load.lua b/src/onload/lobby_load.lua new file mode 100644 index 0000000..0236e46 --- /dev/null +++ b/src/onload/lobby_load.lua @@ -0,0 +1 @@ +skycraft.lobby_tick() diff --git a/src/onload/nether_portal.lua b/src/onload/nether_portal.lua new file mode 100644 index 0000000..28a861b --- /dev/null +++ b/src/onload/nether_portal.lua @@ -0,0 +1,9 @@ +local old_light_nether_portal = mcl_portals.light_nether_portal +function mcl_portals.light_nether_portal(pos) + if mcl_worlds.pos_to_dimension(pos) == "nether" then + return false + else + return old_light_nether_portal(pos) + end +end + diff --git a/src/onload/sapling_mutation.lua b/src/onload/sapling_mutation.lua new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/onload/sapling_mutation.lua @@ -0,0 +1 @@ + diff --git a/src/onload/shop.lua b/src/onload/shop.lua new file mode 100644 index 0000000..cffafcf --- /dev/null +++ b/src/onload/shop.lua @@ -0,0 +1,49 @@ +function skycraft.sell(player, item, money) + local inv = player:get_inventory() + if not inv:contains_item("main", item) then return minetest.chat_send_player(player:get_player_name(), "You don't have enough items!") end + inv:remove_item("main", item) + skycraft.give_money(player, money) +end + +function skycraft.buy(player, item, money) + local inv = player:get_inventory() + if not inv:room_for_item("main", item) then return minetest.chat_send_player(player:get_player_name(), "You don't have enough space in your inventory!") end + if not skycraft.take_money(player, money) then return end + inv:add_item("main", item) +end + +for nodename, nodedef in pairs(minetest.registered_nodes) do + if nodename:find("mcl_signs:") then + minetest.override_item(nodename, { + on_rightclick = function(pos, node, player, itemstack, pointed_thing) + if pos.y < 5000 then return end + local text = minetest.get_meta(pos):get_string("text") or "" + local lines = text:split("\n") + local action, amount, price = lines[1], lines[2], lines[3] + print(action, amount, price) + if not (action and amount and price) then return end + price = string.gsub(price, "%$", "") + price = tonumber(price) + amount = string.gsub(amount, "x", "") + amount = tonumber(amount) + print(action, amount, price) + if not (amount and price) then return end + local func, frameoffset + if action == "Buy" then + func, frameoffset = skycraft.buy, -1 + elseif action == "Sell" then + func, frameoffset = skycraft.sell, 1 + else + return + end + local framepos = vector.add(pos, {x = 0, y = frameoffset, z = 0}) + if minetest.get_node(framepos).name ~= "mcl_itemframes:item_frame" then return end + local inv = minetest.get_meta(framepos):get_inventory() + if inv:is_empty("main") then return end + local itemstack = inv:get_stack("main", 1) + func(player, itemstack:get_name() .. " " .. tostring(amount), price) + end, + }) + end +end + diff --git a/src/onload/spawn.lua b/src/onload/spawn.lua new file mode 100644 index 0000000..547b331 --- /dev/null +++ b/src/onload/spawn.lua @@ -0,0 +1,34 @@ +function mcl_spawn.get_world_spawn_pos() + return skycraft.lobby_pos +end +function mcl_spawn.get_spawn_pos(player) + local name = player:get_player_name() + local spawn, custom_spawn + local bed_spawn = player:get_meta():get_string("mcl_beds:spawn") + if bed_spawn and bed_spawn ~= "" then + spawn, custom_spawn = minetest.string_to_pos(bed_spawn), true + end + if spawn and custom_spawn then + local node_bed = skycraft.get_far_node(spawn) + local node_up1 = skycraft.get_far_node(vector.add(spawn, {x = 0, y = 1, z = 0})) + local node_up2 = skycraft.get_far_node(vector.add(spawn, {x = 0, y = 2, z = 0})) + local bgroup = minetest.get_item_group(node_bed.name, "bed") + local def1 = minetest.registered_nodes[node_up1.name] + local def2 = minetest.registered_nodes[node_up2.name] + if bgroup ~= 1 and bgroup ~= 2 or def1.walkable or def2.walkable or def1.damage_per_second and def1.damage_per_second > 0 or def2.damage_per_second and def2.damage_per_second > 0 then + if bgroup ~= 1 and bgroup ~= 2 then + mcl_spawn.set_spawn_pos(player, nil) + end + spawn, custom_spawn = nil, false + minetest.chat_send_player(name, minetest.get_translator("mcl_beds")("Your spawn bed was missing or blocked.")) + end + end + if not spawn then + spawn = mcl_spawn.get_world_spawn_pos(), false + end + local island_spawn = skycraft.get_spawn(player) + if not custom_spawn and island_spawn then + spawn = vector.add(island_spawn, skycraft.spawn_offset) + end + return spawn, custom_spawn +end diff --git a/src/onload/void.lua b/src/onload/void.lua new file mode 100644 index 0000000..c5e67df --- /dev/null +++ b/src/onload/void.lua @@ -0,0 +1,4 @@ +function mcl_worlds.is_in_void(pos) + local res = minetest.get_node(vector.floor(pos)).name == "mcl_core:void" + return res, res +end |