diff --git a/mods/ethereal/compatibility.lua b/mods/ethereal/compatibility.lua new file mode 100644 index 00000000..03bb9727 --- /dev/null +++ b/mods/ethereal/compatibility.lua @@ -0,0 +1,46 @@ + +-- add compatibility for ethereal nodes already in default game or name changed +minetest.register_alias("ethereal:acacia_trunk", "default:acacia_tree") +minetest.register_alias("ethereal:acacia_wood", "default:acacia_wood") + +minetest.register_alias("ethereal:fence_acacia", "default:fence_acacia_wood") +minetest.register_alias("ethereal:fence_junglewood", "default:fence_junglewood") +minetest.register_alias("ethereal:fence_pine", "default:fence_pine_wood") + +minetest.register_alias("ethereal:acacia_leaves", "default:acacia_leaves") +minetest.register_alias("ethereal:pineleaves", "default:pine_needles") + +minetest.register_alias("ethereal:mushroom_craftingitem", "flowers:mushroom_brown") +minetest.register_alias("ethereal:mushroom_plant", "flowers:mushroom_brown") +minetest.register_alias("ethereal:mushroom_soup_cooked", "ethereal:mushroom_soup") +minetest.register_alias("ethereal:mushroom_1", "flowers:mushroom_brown") +minetest.register_alias("ethereal:mushroom_2", "flowers:mushroom_brown") +minetest.register_alias("ethereal:mushroom_3", "flowers:mushroom_brown") +minetest.register_alias("ethereal:mushroom_4", "flowers:mushroom_brown") + +minetest.register_alias("ethereal:strawberry_bush", "ethereal:strawberry_7") +minetest.register_alias("ethereal:seed_strawberry", "ethereal:strawberry") + +for i = 1, 5 do + minetest.register_alias("ethereal:wild_onion_"..i, "ethereal:onion_"..i) +end + +minetest.register_alias("ethereal:onion_7", "ethereal:onion_4") +minetest.register_alias("ethereal:onion_8", "ethereal:onion_5") +minetest.register_alias("ethereal:wild_onion_7", "ethereal:onion_4") +minetest.register_alias("ethereal:wild_onion_8", "ethereal:onion_5") +minetest.register_alias("ethereal:wild_onion_craftingitem", "ethereal:wild_onion_plant") + +minetest.register_alias("ethereal:hearty_stew_cooked", "ethereal:hearty_stew") + +minetest.register_alias("ethereal:obsidian_brick", "default:obsidianbrick") + +minetest.register_alias("ethereal:crystal_topped_dirt", "ethereal:crystal_dirt") +minetest.register_alias("ethereal:fiery_dirt_top", "ethereal:fiery_dirt") +minetest.register_alias("ethereal:gray_dirt_top", "ethereal:gray_dirt") +minetest.register_alias("ethereal:green_dirt_top", "default;dirt_with_grass") + +minetest.register_alias("ethereal:tree_sapling", "default:sapling") +minetest.register_alias("ethereal:jungle_tree_sapling", "default:junglesapling") +minetest.register_alias("ethereal:acacia_sapling", "default:acacia_sapling") +minetest.register_alias("ethereal:pine_tree_sapling", "default:pine_sapling") diff --git a/mods/ethereal/crystal.lua b/mods/ethereal/crystal.lua new file mode 100644 index 00000000..5254416d --- /dev/null +++ b/mods/ethereal/crystal.lua @@ -0,0 +1,311 @@ + +local S = ethereal.intllib + +-- Crystal Spike (Hurts if you touch it - thanks to ZonerDarkRevention for his DokuCraft DeviantArt crystal texture) +minetest.register_node("ethereal:crystal_spike", { + description = S("Crystal Spike"), + drawtype = "plantlike", + tiles = { "crystal_spike.png" }, + inventory_image = "crystal_spike.png", + wield_image = "crystal_spike.png", + paramtype = "light", + light_source = 7, + sunlight_propagates = true, + walkable = true, + damage_per_second = 1, + groups = {cracky = 1, falling_node = 1, puts_out_fire = 1, cools_lava = 1}, + sounds = default.node_sound_glass_defaults(), + selection_box = { + type = "fixed", + fixed = {-5 / 16, -0.5, -5 / 16, 5 / 16, 0, 5 / 16}, + }, + node_box = { + type = "fixed", + fixed = {-5 / 16, -0.5, -5 / 16, 5 / 16, 0, 5 / 16}, + }, +}) + +-- Crystal Ingot +minetest.register_craftitem("ethereal:crystal_ingot", { + description = S("Crystal Ingot"), + inventory_image = "crystal_ingot.png", + wield_image = "crystal_ingot.png", +}) + +if minetest.get_modpath("builtin_item") then + + minetest.override_item("ethereal:crystal_spike", { + + dropped_step = function(self, pos, dtime) + + self.ctimer = (self.ctimer or 0) + dtime + if self.ctimer < 5.0 then return end + self.ctimer = 0 + + if self.node_inside + and self.node_inside.name ~= "default:water_source" then + return + end + + local objs = core.get_objects_inside_radius(pos, 0.8) + + if not objs or #objs ~= 2 then return end + + local crystal, mese, ent = nil, nil, nil + + for k, obj in pairs(objs) do + + ent = obj:get_luaentity() + + if ent and ent.name == "__builtin:item" then + + if ent.itemstring == "default:mese_crystal 2" + and not mese then + + mese = obj + + elseif ent.itemstring == "ethereal:crystal_spike 2" + and not crystal then + + crystal = obj + end + end + end + + if mese and crystal then + + mese:remove() + crystal:remove() + + core.add_item(pos, "ethereal:crystal_ingot") + + return false + end + end + }) +end + +minetest.register_craft({ + type = "shapeless", + output = "ethereal:crystal_ingot", + recipe = { + "default:mese_crystal", "ethereal:crystal_spike", + "ethereal:crystal_spike", "default:mese_crystal", "bucket:bucket_water" + }, + replacements = { {"bucket:bucket_water", "bucket:bucket_empty"} } +}) + +-- Crystal Block +minetest.register_node("ethereal:crystal_block", { + description = S("Crystal Block"), + tiles = {"crystal_block.png"}, + light_source = 9, + is_ground_content = false, + groups = {cracky = 1, level = 2, puts_out_fire = 1, cools_lava = 1}, + sounds = default.node_sound_glass_defaults(), +}) + +minetest.register_craft({ + output = "ethereal:crystal_block", + recipe = { + {"ethereal:crystal_ingot", "ethereal:crystal_ingot", "ethereal:crystal_ingot"}, + {"ethereal:crystal_ingot", "ethereal:crystal_ingot", "ethereal:crystal_ingot"}, + {"ethereal:crystal_ingot", "ethereal:crystal_ingot", "ethereal:crystal_ingot"}, + } +}) + +minetest.register_craft({ + output = "ethereal:crystal_ingot 9", + recipe = { + {"ethereal:crystal_block"}, + } +}) + +-- Crystal Sword (Powerful wee beastie) +minetest.register_tool("ethereal:sword_crystal", { + description = S("Crystal Sword"), + inventory_image = "crystal_sword.png", + wield_image = "crystal_sword.png", + tool_capabilities = { + full_punch_interval = 0.6, + max_drop_level = 1, + groupcaps = { + snappy = { + times = {[1] = 1.70, [2] = 0.70, [3] = 0.25}, + uses = 50, + maxlevel = 3 + }, + }, + damage_groups = {fleshy = 10}, + }, + groups = {sword = 1}, + sound = {breaks = "default_tool_breaks"}, +}) + +minetest.register_craft({ + output = "ethereal:sword_crystal", + recipe = { + {"ethereal:crystal_ingot"}, + {"ethereal:crystal_ingot"}, + {"default:steel_ingot"}, + } +}) + +-- Crystal Axe +minetest.register_tool("ethereal:axe_crystal", { + description = S("Crystal Axe"), + inventory_image = "crystal_axe.png", + wield_image = "crystal_axe.png", + tool_capabilities = { + full_punch_interval = 0.8, + max_drop_level = 1, + groupcaps = { + choppy = { + times = {[1] = 2.00, [2] = 0.80, [3] = 0.40}, + uses = 40, + maxlevel = 3 + }, + }, + damage_groups = {fleshy = 7}, + }, + groups = {axe = 1}, + sound = {breaks = "default_tool_breaks"}, +}) + +minetest.register_craft({ + output = "ethereal:axe_crystal", + recipe = { + {"ethereal:crystal_ingot", "ethereal:crystal_ingot"}, + {"ethereal:crystal_ingot", "default:steel_ingot"}, + {"", "default:steel_ingot"}, + } +}) + +minetest.register_craft({ + output = "ethereal:axe_crystal", + recipe = { + {"ethereal:crystal_ingot", "ethereal:crystal_ingot"}, + {"default:steel_ingot", "ethereal:crystal_ingot"}, + {"default:steel_ingot", ""}, + } +}) + +-- Crystal Pick (This will last a while) +minetest.register_tool("ethereal:pick_crystal", { + description = S("Crystal Pickaxe"), + inventory_image = "crystal_pick.png", + wield_image = "crystal_pick.png", + tool_capabilities = { + full_punch_interval = 0.7, + max_drop_level = 3, + groupcaps={ + cracky = { + times = {[1] = 1.8, [2] = 0.8, [3] = 0.40}, + uses = 40, + maxlevel = 3 + }, + }, + damage_groups = {fleshy = 6}, + }, + groups = {pickaxe = 1}, + sound = {breaks = "default_tool_breaks"}, +}) + +minetest.register_craft({ + output = "ethereal:pick_crystal", + recipe = { + {"ethereal:crystal_ingot", "ethereal:crystal_ingot", "ethereal:crystal_ingot"}, + {"", "default:steel_ingot", ""}, + {"", "default:steel_ingot", ""}, + } +}) + +local old_handle_node_drops = minetest.handle_node_drops + +function minetest.handle_node_drops(pos, drops, digger) + + -- are we holding Crystal Shovel? + if digger:get_wielded_item():get_name() ~= "ethereal:shovel_crystal" then + return old_handle_node_drops(pos, drops, digger) + end + + local nn = minetest.get_node(pos).name + + if minetest.get_item_group(nn, "crumbly") == 0 then + return old_handle_node_drops(pos, drops, digger) + end + + return old_handle_node_drops(pos, {ItemStack(nn)}, digger) +end + + +minetest.register_tool("ethereal:shovel_crystal", { + description = "Crystal Shovel", + inventory_image = "crystal_shovel.png", + wield_image = "crystal_shovel.png^[transformR90", + tool_capabilities = { + full_punch_interval = 1.0, + max_drop_level = 1, + groupcaps = { + crumbly = { + times = {[1] = 1.10, [2] = 0.50, [3] = 0.30}, + uses = 30, + maxlevel = 3 + }, + }, + damage_groups = {fleshy = 4}, + }, + groups = {shovel = 1}, + sound = {breaks = "default_tool_breaks"}, +}) + +minetest.register_craft({ + output = "ethereal:shovel_crystal", + recipe = { + {"ethereal:crystal_ingot"}, + {"default:steel_ingot"}, + {"default:steel_ingot"}, + } +}) + +-- Crystal Gilly Staff (replenishes air supply when used) +minetest.register_tool("ethereal:crystal_gilly_staff", { + description = S("Crystal Gilly Staff"), + inventory_image = "crystal_gilly_staff.png", + wield_image = "crystal_gilly_staff.png", + + on_use = function(itemstack, user, pointed_thing) + if user:get_breath() < 10 then + user:set_breath(10) + end + end, +}) + +minetest.register_craft({ + type = "shapeless", + output = "ethereal:crystal_gilly_staff", + recipe = { + "ethereal:green_moss", "ethereal:gray_moss", "ethereal:fiery_moss", + "ethereal:crystal_moss", "ethereal:crystal_ingot", "ethereal:mushroom_moss", + "ethereal:crystal_ingot" + }, +}) + +-- Add [toolranks] mod support if found +if minetest.get_modpath("toolranks") then + + -- Helper function + local function add_tool(name, desc, afteruse) + + minetest.override_item(name, { + original_description = desc, + description = toolranks.create_description(desc, 0, 1), + after_use = afteruse and toolranks.new_afteruse + }) + end + + add_tool("ethereal:pick_crystal", "Crystal Pickaxe", true) + add_tool("ethereal:axe_crystal", "Crystal Axe", true) + add_tool("ethereal:shovel_crystal", "Crystal Shovel", true) + add_tool("ethereal:sword_crystal", "Crystal Sword", true) +end diff --git a/mods/ethereal/depends.txt b/mods/ethereal/depends.txt new file mode 100644 index 00000000..da7e44b3 --- /dev/null +++ b/mods/ethereal/depends.txt @@ -0,0 +1,10 @@ +default +farming? +stairs +flowers +doors +bakedclay? +moreblocks? +intllib? +lucky_block? +toolranks? diff --git a/mods/ethereal/description.txt b/mods/ethereal/description.txt new file mode 100644 index 00000000..53388353 --- /dev/null +++ b/mods/ethereal/description.txt @@ -0,0 +1 @@ +Ethereal mod uses the v7 mapgen to add many new biomes to the world. \ No newline at end of file diff --git a/mods/ethereal/dirt.lua b/mods/ethereal/dirt.lua new file mode 100644 index 00000000..2ae5c47c --- /dev/null +++ b/mods/ethereal/dirt.lua @@ -0,0 +1,309 @@ + +local S = ethereal.intllib + +-- override default dirt (to stop caves cutting away dirt) +minetest.override_item("default:dirt", {is_ground_content = ethereal.cavedirt}) + +minetest.register_alias("ethereal:green_dirt", "default:dirt_with_grass") + +-- dry dirt +minetest.register_node("ethereal:dry_dirt", { + description = S("Dried Dirt"), + tiles = {"ethereal_dry_dirt.png"}, + is_ground_content = ethereal.cavedirt, + groups = {crumbly = 3}, + sounds = default.node_sound_dirt_defaults() +}) + +minetest.register_craft({ + type = "cooking", + output = "ethereal:dry_dirt", + recipe = "default:dirt", + cooktime = 3, +}) + +local dirts = { + "Bamboo", "Jungle", "Grove", "Prairie", "Cold", + "Crystal", "Mushroom", "Fiery", "Gray" +} + +for n = 1, #dirts do + + local desc = dirts[n] + local name = desc:lower() + + minetest.register_node("ethereal:"..name.."_dirt", { + description = S(desc.." Dirt"), + tiles = { + "ethereal_grass_"..name.."_top.png", + "default_dirt.png", + { + name = "default_dirt.png^ethereal_grass_" + .. name .."_side.png", + tileable_vertical = false + } + }, + is_ground_content = ethereal.cavedirt, + groups = {crumbly = 3, soil = 1, spreading_dirt_type = 1}, + soil = { + base = "ethereal:"..name.."_dirt", + dry = "farming:soil", + wet = "farming:soil_wet" + }, + drop = "default:dirt", + sounds = default.node_sound_dirt_defaults({ + footstep = {name = "default_grass_footstep", gain = 0.25}, + }), + }) + +end + + +-- flower spread, also crystal and fire flower regeneration +local flower_spread = function(pos, node) + + if (minetest.get_node_light(pos) or 0) < 13 then + return + end + + local pos0 = {x = pos.x - 4, y = pos.y - 2, z = pos.z - 4} + local pos1 = {x = pos.x + 4, y = pos.y + 2, z = pos.z + 4} + + local num = #minetest.find_nodes_in_area(pos0, pos1, "group:flora") + + -- stop flowers spreading too much just below top of map block + if minetest.find_node_near(pos, 2, "ignore") then + return + end + + if num > 3 + and node.name == "ethereal:crystalgrass" then + + local grass = minetest.find_nodes_in_area_under_air( + pos0, pos1, {"ethereal:crystalgrass"}) + + if #grass > 4 + and not minetest.find_node_near(pos, 4, {"ethereal:crystal_spike"}) then + + pos = grass[math.random(#grass)] + + pos.y = pos.y - 1 + + if minetest.get_node(pos).name == "ethereal:crystal_dirt" then + + pos.y = pos.y + 1 + + minetest.swap_node(pos, {name = "ethereal:crystal_spike"}) + end + end + + return + + elseif num > 3 + and node.name == "ethereal:dry_shrub" then + + local grass = minetest.find_nodes_in_area_under_air( + pos0, pos1, {"ethereal:dry_shrub"}) + + if #grass > 8 + and not minetest.find_node_near(pos, 4, {"ethereal:fire_flower"}) then + + pos = grass[math.random(#grass)] + + pos.y = pos.y - 1 + + if minetest.get_node(pos).name == "ethereal:fiery_dirt" then + + pos.y = pos.y + 1 + + minetest.swap_node(pos, {name = "ethereal:fire_flower"}) + end + end + + return + + elseif num > 3 then + return + end + + local seedling = minetest.find_nodes_in_area_under_air( + pos0, pos1, {"group:soil"}) + + if #seedling > 0 then + + pos = seedling[math.random(#seedling)] + + -- default farming has desert sand as soil, so dont spread on this + if minetest.get_node(pos).name == "default:desert_sand" then + return + end + + pos.y = pos.y + 1 + + if (minetest.get_node_light(pos) or 0) < 13 then + return + end + + minetest.swap_node(pos, {name = node.name}) + end +end + +-- grow papyrus up to 4 high and bamboo up to 8 high +local grow_papyrus = function(pos, node) + + local oripos = pos.y + local high = 4 + + pos.y = pos.y - 1 + + local nod = minetest.get_node_or_nil(pos) + + if not nod + or minetest.get_item_group(nod.name, "soil") < 1 + or minetest.find_node_near(pos, 3, {"group:water"}) == nil then + return + end + + if node.name == "ethereal:bamboo" then + high = 8 + end + + pos.y = pos.y + 1 + + local height = 0 + + while height < high + and minetest.get_node(pos).name == node.name do + height = height + 1 + pos.y = pos.y + 1 + end + + nod = minetest.get_node_or_nil(pos) + + if nod + and nod.name == "air" + and height < high then + + if node.name == "ethereal:bamboo" + and height == (high - 1) then + + ethereal.grow_bamboo_tree({x = pos.x, y = oripos, z = pos.z}) + else + minetest.swap_node(pos, {name = node.name}) + end + end + +end + +-- loop through active abm's +for _, ab in pairs(minetest.registered_abms) do + + local label = ab.label or "" + local node1 = ab.nodenames and ab.nodenames[1] or "" + local node2 = ab.nodenames and ab.nodenames[2] or "" + local neigh = ab.neighbors and ab.neighbors[1] or "" + + if label == "Flower spread" + or node1 == "group:flora" then + + --ab.interval = 1 + --ab.chance = 1 + ab.nodenames = {"group:flora"} + ab.neighbors = {"group:soil"} + ab.action = flower_spread + + -- find grow papyrus abm and change to grow_papyrus function + elseif label == "Grow papyrus" + or node1 == "default:papyrus" then + + --ab.interval = 2 + --ab.chance = 1 + ab.nodenames = {"default:papyrus", "ethereal:bamboo"} + ab.neighbors = {"group:soil"} + ab.action = grow_papyrus + end +end + +-- If Baked Clay mod not active, make Red, Orange and Grey nodes +if not minetest.get_modpath("bakedclay") then + + minetest.register_node(":bakedclay:red", { + description = S("Red Baked Clay"), + tiles = {"baked_clay_red.png"}, + groups = {cracky = 3}, + is_ground_content = ethereal.cavedirt, + sounds = default.node_sound_stone_defaults(), + }) + + minetest.register_node(":bakedclay:orange", { + description = S("Orange Baked Clay"), + tiles = {"baked_clay_orange.png"}, + groups = {cracky = 3}, + is_ground_content = ethereal.cavedirt, + sounds = default.node_sound_stone_defaults(), + }) + + minetest.register_node(":bakedclay:grey", { + description = S("Grey Baked Clay"), + tiles = {"baked_clay_grey.png"}, + groups = {cracky = 3}, + is_ground_content = ethereal.cavedirt, + sounds = default.node_sound_stone_defaults(), + }) + +end + +-- Quicksand (old style, sinking inside shows black instead of yellow effect, +-- works ok with noclip enabled though) +minetest.register_node("ethereal:quicksand", { + description = S("Quicksand"), + tiles = {"default_sand.png"}, + drop = "default:sand", + liquid_viscosity = 15, + liquidtype = "source", + liquid_alternative_flowing = "ethereal:quicksand", + liquid_alternative_source = "ethereal:quicksand", + liquid_renewable = false, + liquid_range = 0, + drowning = 1, + walkable = false, + climbable = false, + post_effect_color = {r = 230, g = 210, b = 160, a = 245}, + groups = {crumbly = 3, sand = 1, liquid = 3, disable_jump = 1}, + sounds = default.node_sound_sand_defaults(), +}) + +-- Quicksand (new style, sinking inside shows yellow effect with or without noclip, +-- but old quicksand is shown as black until block placed nearby to update light) +minetest.register_node("ethereal:quicksand2", { + description = S("Quicksand"), + tiles = {"default_sand.png"}, + drawtype = "glasslike", + paramtype = "light", + drop = "default:sand", + liquid_viscosity = 15, + liquidtype = "source", + liquid_alternative_flowing = "ethereal:quicksand2", + liquid_alternative_source = "ethereal:quicksand2", + liquid_renewable = false, + liquid_range = 0, + drowning = 1, + walkable = false, + climbable = false, + post_effect_color = {r = 230, g = 210, b = 160, a = 245}, + groups = {crumbly = 3, sand = 1, liquid = 3, disable_jump = 1}, + sounds = default.node_sound_sand_defaults(), +}) + +-- craft quicksand +minetest.register_craft({ + output = "ethereal:quicksand2", + recipe = { + {"group:sand", "group:sand", "group:sand"}, + {"group:sand", "bucket:bucket_water", "group:sand"}, + {"group:sand", "group:sand", "group:sand"}, + }, + replacements = { + {"bucket:bucket_water", "bucket:bucket_empty"} + } +})