From 664c24ce7dbb6d4348cfa043392d1017fb47c533 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Sun, 10 Dec 2017 22:20:48 +0100 Subject: [PATCH] Eyes of ender now fly to End portal shrines! --- mods/ITEMS/mcl_end/depends.txt | 1 + mods/ITEMS/mcl_end/init.lua | 156 ++++++++++++++++++++++++-- mods/ITEMS/mcl_portals/portal_end.lua | 2 - mods/MAPGEN/mcl_strongholds/API.md | 17 --- mods/MAPGEN/mcl_strongholds/init.lua | 10 +- mods/MAPGEN/mcl_structures/init.lua | 22 ++++ 6 files changed, 173 insertions(+), 35 deletions(-) delete mode 100644 mods/MAPGEN/mcl_strongholds/API.md diff --git a/mods/ITEMS/mcl_end/depends.txt b/mods/ITEMS/mcl_end/depends.txt index a1ffcc825..de1fd3834 100644 --- a/mods/ITEMS/mcl_end/depends.txt +++ b/mods/ITEMS/mcl_end/depends.txt @@ -2,3 +2,4 @@ mcl_sounds mcl_throwing mcl_util doc_items +mcl_worlds diff --git a/mods/ITEMS/mcl_end/init.lua b/mods/ITEMS/mcl_end/init.lua index 9bd21c78d..6f834f2c9 100644 --- a/mods/ITEMS/mcl_end/init.lua +++ b/mods/ITEMS/mcl_end/init.lua @@ -162,6 +162,153 @@ minetest.register_node("mcl_end:dragon_egg", { -- TODO: Make dragon egg teleport on punching }) +-- Eye of ender +minetest.register_entity("mcl_end:ender_eye", { + physical = false, + textures = {"mcl_end_ender_eye.png"}, + visual_size = {x=1.5, y=1.5}, + collisionbox = {0,0,0,0,0,0}, + + -- Save and restore age + get_staticdata = function(self) + return tostring(self._age) + end, + on_activate = function(self, staticdata, dtime_s) + local age = tonumber(staticdata) + if type(age) == "number" then + self._age = age + if self._age >= 2 then + self._phase = 1 + else + self._phase = 0 + end + end + end, + + on_step = function(self, dtime) + self._age = self._age + dtime + if self._age >= 3 then + -- End of life + local r = math.random(1,5) + if r == 1 or minetest.settings:get_bool("creative_mode") then + -- 20% chance to get destroyed completely. + -- 100% if in Creative Mode + self.object:remove() + return + else + -- 80% to drop as an item + local pos = self.object:get_pos() + local v = self.object:getvelocity() + self.object:remove() + local item = minetest.add_item(pos, "mcl_end:ender_eye") + item:setvelocity(v) + return + end + elseif self._age >= 2 then + if self._phase == 0 then + self._phase = 1 + -- Stop the eye and wait for another second. + -- The vertical speed changes are just eye candy. + self.object:setacceleration({x=0, y=-3, z=0}) + self.object:setvelocity({x=0, y=self.object:getvelocity().y*0.2, z=0}) + end + else + -- Fly normally and generate particles + local pos = self.object:get_pos() + pos.x = pos.x + math.random(-1, 1)*0.5 + pos.y = pos.y + math.random(-1, 0)*0.5 + pos.z = pos.z + math.random(-1, 1)*0.5 + minetest.add_particle({ + pos = pos, + texture = "mcl_particles_teleport.png", + expirationtime = 1, + velocity = {x=math.random(-1, 1)*0.1, y=math.random(-30, 0)*0.1, z=math.random(-1, 1)*0.1}, + acceleration = {x=0, y=0, z=0}, + size = 2.5, + }) + end + end, + + _age = 0, -- age in seconds + _phase = 0, -- phase 0: flying. phase 1: idling in mid air, about to drop or shatter +}) + +minetest.register_craftitem("mcl_end:ender_eye", { + description = "Eye of Ender", + _doc_items_longdesc = "This item is used to locate End portal shrines and to activate End portals.", + _doc_items_usagehelp = "Use the attack key to release the eye of ender. It will rise and fly in the horizontal direction of the closest end portal shrine. If you're very close, the eye of ender will take the direct path to the End portal shrine instead. After a few seconds, it stops. It may drop as an item, but there's a 20% chance it shatters." .. "\n" .. "To activate an End portal, eyes of ender need to be placed into each block of an intact End portal frame.", + wield_image = "mcl_end_ender_eye.png", + inventory_image = "mcl_end_ender_eye.png", + stack_max = 64, + -- Throw eye of ender to make it fly to the closest stronghold + on_use = function(itemstack, user, pointed_thing) + if user == nil then + return + end + local origin = user:get_pos() + origin.y = origin.y + 1.5 + local strongholds = mcl_structures.get_registered_structures("stronghold") + local dim = mcl_worlds.pos_to_dimension(origin) + local is_creative = minetest.settings:get_bool("creative_mode") + + -- Just drop the eye of ender if there are no strongholds + if #strongholds <= 0 or dim ~= "overworld" then + if not is_creative then + minetest.add_item(origin, "mcl_end:ender_eye") + itemstack:take_item() + end + return itemstack + end + + -- Find closest stronghold. + -- Note: Only the horizontal axes are taken into account. + local closest_stronghold + local lowest_dist + for s=1, #strongholds do + local h_pos = table.copy(strongholds[s].pos) + local h_origin = table.copy(origin) + h_pos.y = 0 + h_origin.y = 0 + local dist = vector.distance(h_origin, h_pos) + if not closest_stronghold then + closest_stronghold = strongholds[s] + lowest_dist = dist + else + if dist < lowest_dist then + closest_stronghold = strongholds[s] + lowest_dist = dist + end + end + end + + -- Throw it! + local obj = minetest.add_entity(origin, "mcl_end:ender_eye") + local dir + + if lowest_dist <= 25 then + local velocity = 4 + -- Stronghold is close: Fly directly to stronghold and take Y into account. + dir = vector.normalize(vector.direction(origin, closest_stronghold.pos)) + obj:setvelocity({x=dir.x*velocity, y=dir.y*velocity, z=dir.z*velocity}) + else + local velocity = 12 + -- Don't care about Y if stronghold is still far away. + -- Fly to direction of X/Z, and always upwards so it can be seen easily. + local o = {x=origin.x, y=0, z=origin.z} + local s = {x=closest_stronghold.pos.x, y=0, z=closest_stronghold.pos.z} + dir = vector.normalize(vector.direction(o, s)) + obj:setacceleration({x=dir.x*-3, y=4, z=dir.z*-3}) + obj:setvelocity({x=dir.x*velocity, y=3, z=dir.z*velocity}) + end + + + if not is_creative then + itemstack:take_item() + end + return itemstack + end, +}) + local chorus_flower_box = { type = "fixed", fixed = { @@ -273,15 +420,6 @@ minetest.register_craftitem("mcl_end:chorus_fruit_popped", { stack_max = 64, }) -minetest.register_craftitem("mcl_end:ender_eye", { - description = "Eye of Ender", - _doc_items_longdesc = doc.sub.items.temp.craftitem, - wield_image = "mcl_end_ender_eye.png", - inventory_image = "mcl_end_ender_eye.png", - stack_max = 64, -}) - - -- Crafting recipes minetest.register_craft({ output = "mcl_end:end_bricks 4", diff --git a/mods/ITEMS/mcl_portals/portal_end.lua b/mods/ITEMS/mcl_portals/portal_end.lua index a12920ee7..4437bf7ad 100644 --- a/mods/ITEMS/mcl_portals/portal_end.lua +++ b/mods/ITEMS/mcl_portals/portal_end.lua @@ -345,8 +345,6 @@ end -- Portal opener minetest.override_item("mcl_end:ender_eye", { - _doc_items_longdesc = "Eye of ender can be used in the construction of End portal frames.", - _doc_items_usagehelp = "Find a structure with 12 end portal frames surrounding a horizontal aread of 3×3 blocks, with each block facing inward. Place an eye of ender into each end portal frame to create the portal.", on_place = function(itemstack, user, pointed_thing) -- Use pointed node's on_rightclick function first, if present local node = minetest.get_node(pointed_thing.under) diff --git a/mods/MAPGEN/mcl_strongholds/API.md b/mods/MAPGEN/mcl_strongholds/API.md deleted file mode 100644 index f5d2edd01..000000000 --- a/mods/MAPGEN/mcl_strongholds/API.md +++ /dev/null @@ -1,17 +0,0 @@ -# Strongholds API -The API provides one function: - -## `mcl_strongholds.get_stronghold_positions()` -Returns a table of the positions of all strongholds, centered at the end portal room. -This includes strongholds which have not been generated yet. -This table is a copy, changes to the table will have no effect on the stronghold generation. - -Format of the returned table: -{ - { pos = , generated = }, -- first stronghold - { pos = , generated = }, -- second stronghold - -- and so on … -} - -* pos: Position of stronghold, centered at the end portal room -* generated: `true` if this stronghold has already been generated diff --git a/mods/MAPGEN/mcl_strongholds/init.lua b/mods/MAPGEN/mcl_strongholds/init.lua index a721dd5da..d4c8681ad 100644 --- a/mods/MAPGEN/mcl_strongholds/init.lua +++ b/mods/MAPGEN/mcl_strongholds/init.lua @@ -59,6 +59,9 @@ local init_strongholds = function() angle = math.fmod(angle + ((math.pi*2) / ring.amount), math.pi*2) end end + + mcl_structures.register_structures("stronghold", table.copy(strongholds)) + strongholds_inited = true end @@ -90,13 +93,6 @@ local generate_strongholds = function(minp, maxp) end end --- Minimal API -mcl_strongholds = {} -mcl_strongholds.get_stronghold_positions = function() - return table.copy(strongholds) -end - - init_strongholds() --[[ Note this mod depends on mcl_mapgen_core to make sure the core mapgen runs FIRST. diff --git a/mods/MAPGEN/mcl_structures/init.lua b/mods/MAPGEN/mcl_structures/init.lua index 1fb949867..c3b644aad 100644 --- a/mods/MAPGEN/mcl_structures/init.lua +++ b/mods/MAPGEN/mcl_structures/init.lua @@ -292,6 +292,28 @@ mcl_structures.generate_desert_temple = function(pos) return ret end +local registered_structures = {} + +--[[ Returns a table of structure of the specified type. +Currently the only valid parameter is "stronghold". +Format of return value: +{ + { pos = , generated= }, -- first structure + { pos = , generated= }, -- second structure + -- and so on +} + +TODO: Implement this function for all other structure types as well. +]] +mcl_structures.get_registered_structures = function(structure_type) + return table.copy(registered_structures[structure_type]) +end + +-- Register a structures table for the given type. The table format is the same as for +-- mcl_structures.get_registered_structures. +mcl_structures.register_structures = function(structure_type, structures) + registered_structures[structure_type] = structures +end -- Debug command minetest.register_chatcommand("spawnstruct", {