1 elidragon.skyblock = {}
5 -- http://rosettacode.org/wiki/Spiral_matrix#Lua
6 av, sn = math.abs, function(s) return s~=0 and s/av(s) or 0 end
7 local function sindex(y, x)
8 if y == -x and y >= x then return (2*y+1)^2 end
9 local l = math.max(av(y), av(x))
10 return (2*l-1)^2+4*l+2*l*sn(x+y)+sn(y^2-x^2)*(l-(av(y)==l and sn(y)*x or sn(x)*y))
12 local function spiralt(side)
13 local ret, id, start, stop = {}, 0, math.floor((-side+1)/2), math.floor((side-1)/2)
16 local id = side^2 - sindex(stop - i + 1,start + j - 1)
23 local function ripairs(t)
24 local function ripairs_it(t,i)
27 if v==nil then return v end
30 return ripairs_it, t, #t+1
35 function elidragon.skyblock.load_legacy_start_positions()
36 local file = io.open(minetest.get_worldpath() .. "/skyblock.start_positions", "r")
38 local start_positions = {}
40 local x = file:read("*n")
44 local y = file:read("*n")
45 local z = file:read("*n")
46 table.insert(start_positions, {x = x, y = y, z = z})
49 return start_positions
53 function elidragon.skyblock.load_start_positions()
54 local file = io.open(minetest.get_worldpath() .. "/start_positions", "r")
56 local start_positions = minetest.deserialize(file:read())
58 return start_positions
62 function elidragon.skyblock.save_start_positions(start_positions)
63 local file = io.open(minetest.get_worldpath() .. "/start_positions", "w")
64 file:write(minetest.serialize(start_positions))
68 function elidragon.skyblock.generate_start_positions()
69 local start_positions = {}
70 for _, v in ripairs(spiralt(1000)) do
71 local pos = {x = v.x * 32, y = math.random(4 - 8, 4 + 8), z = v.z * 32}
72 table.insert(start_positions, pos)
74 return start_positions
77 elidragon.skyblock.start_positions = elidragon.skyblock.load_start_positions()
79 if not elidragon.skyblock.start_positions then
80 elidragon.skyblock.start_positions = elidragon.skyblock.load_legacy_start_positions() or elidragon.skyblock.generate_start_positions()
81 elidragon.skyblock.save_start_positions(elidragon.skyblock.start_positions)
84 function elidragon.skyblock.load_legacy_last_start_id()
85 local file = io.open(minetest.get_worldpath() .. "/skyblock.last_start_id", "r")
87 local last_start_id = tonumber(file:read())
93 elidragon.savedata.last_start_id = elidragon.savedata.last_start_id or elidragon.skyblock.load_legacy_last_start_id() or 0
97 function elidragon.skyblock.get_spawn(name)
98 return elidragon.savedata.spawns[name]
101 function elidragon.skyblock.set_spawn(name, pos)
102 elidragon.savedata.spawns[name] = pos
105 function elidragon.skyblock.spawn_player(player)
106 if not player then return end
107 local name = player:get_player_name()
108 local spawn = elidragon.skyblock.get_spawn(name) or elidragon.skyblock.new_spawn(name)
109 player:set_pos({x = spawn.x + 2, y = spawn.y + 2, z = spawn.z + 2})
112 function elidragon.skyblock.new_spawn(name)
115 elidragon.savedata.last_start_id = elidragon.savedata.last_start_id + 1
116 spawn = elidragon.skyblock.start_positions[elidragon.savedata.last_start_id]
117 until not minetest.is_protected(spawn, name)
118 elidragon.skyblock.set_spawn(name, spawn)
119 local file = io.open(minetest.get_modpath("elidragon") .. "/schems/island.we", "r")
120 local schem = file:read()
122 worldedit.deserialize(vector.add(spawn, {x = -3, y = -4, z = -3}), schem)
126 function elidragon.skyblock.load_legacy_spawns()
127 local file = io.open(minetest.get_worldpath() .. "/skyblock.spawn", "r")
131 local x = file:read("*n")
135 local y = file:read("*n")
136 local z = file:read("*n")
137 local name = file:read("*l")
138 spawns[name:sub(2)] = {x = x, y = y, z = z}
145 elidragon.savedata.spawns = elidragon.savedata.spawns or elidragon.skyblock.load_legacy_spawns() or {}
150 minetest.register_chatcommand("level", {
151 description = "Get/set the current level of a player",
152 params = "<player> [<level>]",
153 func = function(name, param)
154 local target = param:split(" ")[1]
155 local level = tonumber(param:split(" ")[2])
157 minetest.chat_send_player(name, target .. " is on level " .. elidragon.skyblock.get_level(target))
158 elseif minetest.check_player_privs(name, {server = true}) and elidragon.skyblock.set_level(target, level) then
159 minetest.chat_send_player(name, target .. " has been set to level " .. level)
161 minetest.chat_send_player(name, "Cannot change " .. target .. " to level " .. level)
169 minetest.register_node("elidragon:skyblock", {
170 description = "Skyblock",
171 tiles = {"elidragon_quest.png"},
174 groups = {crumbly=2, cracky=2},
177 minetest.register_alias("skyblock:quest", "elidragon:skyblock")
181 minetest.register_on_mapgen_init(function(mgparams)
182 minetest.set_mapgen_params({mgname = "singlenode", water_level = -32000})
187 minetest.register_on_respawnplayer(function(player)
188 elidragon.skyblock.spawn_player(player)
192 -- remove legacy cloud layer
194 minetest.register_lbm({
195 nodenames = {"default:cloud"},
196 name = "elidragon:remove_cloud_layer",
197 action = function(pos)
199 minetest.set_node(pos, { name = "air"})
204 -- remove inventory from quest block
206 minetest.register_lbm({
207 nodenames = {"elidragon:skyblock", "skyblock:quest"},
208 name = "elidragon:remove_inventory_from_quest_block",
209 action = function(pos)
210 minetest.get_meta(pos):set_string("formspec", "")
211 minetest.get_meta(pos):set_string("infotext", "")
217 minetest.after(0, function()
218 default.cool_lava = function(pos, oldnode)
220 if oldnode.name == "default:lava_source" then
221 node = "default:obsidian"
222 elseif math.random() < 0.001 then
223 node = "moreores:mineral_mithril"
224 elseif math.random() < 0.003 then
225 node = "default:stone_with_diamond"
226 elseif math.random() < 0.005 then
227 node = "default:stone_with_mese"
228 elseif math.random() < 0.01 then
229 node = "default:stone_with_gold"
230 elseif math.random() < 0.015 then
231 node = "default:stone_with_tin"
232 elseif math.random() < 0.02 then
233 node = "default:stone_with_copper"
234 elseif math.random() < 0.033 then
235 node = "default:stone_with_iron"
236 elseif math.random() < 0.04 then
237 node = "moreores:mineral_silver"
238 elseif math.random() < 0.05 then
239 node = "default:stone_with_coal"
241 node = "default:stone"
243 minetest.set_node(pos, {name = node})
244 minetest.sound_play("default_cool_lava", {pos = pos, max_hear_distance = 16, gain = 0.25}, true)
250 minetest.after(0, function()
251 minetest.register_alias("default:pine_leaves", "default:pine_needles")
252 minetest.register_alias("default:pine_bush_leaves", "default:pine_bush_needles")
253 local trees = {"default:", "default:jungle", "default:pine_", "default:acacia_", "default:aspen_", "default:bush_", "default:blueberry_bush_", "default:acacia_bush_", "default:pine_bush_",}
254 for _, tree in pairs(trees) do
256 items[#items + 1] = {
257 items = {tree .. "sapling"},
260 for _, stree in pairs(trees) do
261 if stree ~= tree then
262 items[#items + 1] = {
263 items = {stree .. "sapling"},
268 items[#items + 1] = {
269 items = {tree .. "leaves"},
271 minetest.registered_nodes[tree .. "leaves"].drop = {max_items = 1, items = items}
277 minetest.register_abm({
278 nodenames = {"default:dirt_with_grass"},
281 action = function(pos, node)
283 local light = minetest.get_node_light(pos) or 0
284 if minetest.get_node(pos).name == "air" and light > 12 and not minetest.find_node_near(pos, 2, {"group:flora"}) then
285 local flowers = {"default:junglegrass", "default:grass_1", "flowers:dandelion_white", "flowers:dandelion_yellow", "flowers:geranium", "flowers:rose", "flowers:tulip", "flowers:tulip_black", "flowers:viola", "flowers:chrysanthemum_green"}
286 minetest.set_node(pos, {name = flowers[math.random(#flowers)]})
293 minetest.register_craft({
294 output = "default:desert_sand",
301 minetest.register_craft({
302 output = "default:desert_stone",
304 {"default:desert_sand", "default:desert_sand"},
305 {"default:desert_sand", "default:desert_sand"},
309 minetest.register_craft({
310 output = "default:sand 4",
312 {"default:obsidian_shard"},
316 minetest.register_craft({
317 output = "default:gravel 2",
323 minetest.register_craft({
324 output = "default:dirt 2",
330 minetest.register_craft({
331 output = "default:clay_lump 4",
337 minetest.register_craft({
338 output = "default:ice",
340 {"bucket:bucket_water"},
344 minetest.register_craft({
345 output = "default:snowblock 4",
351 minetest.register_craft({
353 output = "default:lava_source",
354 recipe = "default:stone",
357 minetest.register_craft({
358 output = "default:silver_sand 9",
360 {"default:sand", "default:sand", "default:sand"},
361 {"default:sand", "moreores:silver_lump", "default:sand"},
362 {"default:sand", "default:sand", "default:sand"},
368 minetest.register_chatcommand("set_skyblock_spawn", {
369 param = "<player> <x> <y> <z>",
370 desc = "Change the skyblocks spawn of a player",
371 privs = {server = true},
372 func = function(admin, param)
373 local name = param:split(" ")[1]
374 local x = tonumber(param:split(" ")[2])
375 local y = tonumber(param:split(" ")[3])
376 local z = tonumber(param:split(" ")[4])
377 if name and x and y and z then
378 elidragon.skyblock.set_spawn(name, {x = x, y = y, z = z})
380 minetest.chat_send_player(admin, "Invalid usage.")
385 minetest.register_chatcommand("island", {
387 description = "Teleport to your Island",
388 func = function(name, param)
389 elidragon.skyblock.spawn_player(minetest.get_player_by_name(name))