From 90f312f77278c93e7c1d0e5603263b0a7830565d Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Sun, 4 Apr 2021 19:13:46 +0200 Subject: [PATCH 01/32] Add credits overlay prototype --- mods/HUD/mcl_credits/init.lua | 105 ++++++++++++++++++ mods/HUD/mcl_credits/mod.conf | 4 + .../mcl_credits/textures/mineclone2_logo.png | Bin 0 -> 77528 bytes mods/ITEMS/mcl_portals/portal_end.lua | 4 + 4 files changed, 113 insertions(+) create mode 100644 mods/HUD/mcl_credits/init.lua create mode 100644 mods/HUD/mcl_credits/mod.conf create mode 100644 mods/HUD/mcl_credits/textures/mineclone2_logo.png diff --git a/mods/HUD/mcl_credits/init.lua b/mods/HUD/mcl_credits/init.lua new file mode 100644 index 000000000..05e7aeff4 --- /dev/null +++ b/mods/HUD/mcl_credits/init.lua @@ -0,0 +1,105 @@ +mcl_credits = { + players = {}, +} + +mcl_credits.description = "A faithful Open Source imitation of Minecraft" + +-- Sub-lists are sorted by number of commits +mcl_credits.people = { + {"Creator of MineClone", { + "davedevils", + }}, + {"Creator of MineClone2", { + "Wuzzy", + }}, + {"Maintainers", { + "Fleckenstein", + "kay27", + "oilboi", + }}, + {"Developers", { + "bzoss", + "AFCMS", + "epCode", + "ryvnf", + "iliekprogrammar", + "MysticTempest", + "Rootyjr", + "Nicu", + "aligator", + }}, + {"Contributors", { + "Code-Sploit", + "Laurent Rocher", + "HimbeerserverDE", + "TechDudie", + "Alexander Minges", + "ArTee3", + "ZeDique la Ruleta", + "pitchum", + "wuniversales", + "Bu-Gee", + "David McMackins II", + "Nicholas Niro", + "Wouters Dorian", + "Blue Blancmange", + "Jared Moody", + "Li0n", + "Midgard", + "NO11", + "Saku Laesvuori", + "Yukitty", + "ZedekThePD", + "aldum", + "dBeans", + "nickolas360", + "yutyo", + }}, + {"3D Models", { + "22i", + "tobyplowy", + }}, + {"Textures", { + "XSSheep", + "kingoscargames", + "leorockway", + "xMrVizzy", + }}, +} + +function mcl_credits.show(player) + local name = player:get_player_name() + if mcl_credits.players[name] then + return + end + local hud_list = { + player:hud_add({ + hud_elem_type = "image", + text = "menu_bg.png", + position = {x = 0, y = 0}, + alignment = {x = 1, y = 1}, + scale = {x = -100, y = -100}, + z_index = 1000, + }) + } + mcl_credits.players[name] = hud_list +end + +function mcl_credits.hide(player) + local name = player:get_player_name() + local list = mcl_credits.players[name] + if list then + for _, id in pairs(list) do + player:hud_remove(id) + end + end + mcl_credits.players[name] = nil +end + +controls.register_on_press(function(player, key) + if key == "sneak" then + mcl_credits.hide(player) + elseif key == "aux1" then + mcl_credits.show(player) + end +end) diff --git a/mods/HUD/mcl_credits/mod.conf b/mods/HUD/mcl_credits/mod.conf new file mode 100644 index 000000000..b5532cd30 --- /dev/null +++ b/mods/HUD/mcl_credits/mod.conf @@ -0,0 +1,4 @@ +name = mcl_credits +author = Fleckenstein +description = Show a HUD containing the credits +depends = controls diff --git a/mods/HUD/mcl_credits/textures/mineclone2_logo.png b/mods/HUD/mcl_credits/textures/mineclone2_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..11435df51033b13cdeba49326b6eabe72ba320a8 GIT binary patch literal 77528 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 aYyTg9*d2kzhi~x!0000 Date: Tue, 6 Apr 2021 11:55:21 +0200 Subject: [PATCH 02/32] Add credits screen --- mods/HUD/mcl_credits/init.lua | 140 ++++++++++++++---- mods/HUD/mcl_credits/mod.conf | 1 - .../mcl_credits/textures/mineclone2_icon.png | Bin 0 -> 3961 bytes 3 files changed, 113 insertions(+), 28 deletions(-) create mode 100644 mods/HUD/mcl_credits/textures/mineclone2_icon.png diff --git a/mods/HUD/mcl_credits/init.lua b/mods/HUD/mcl_credits/init.lua index 05e7aeff4..a53ebbba9 100644 --- a/mods/HUD/mcl_credits/init.lua +++ b/mods/HUD/mcl_credits/init.lua @@ -2,22 +2,22 @@ mcl_credits = { players = {}, } -mcl_credits.description = "A faithful Open Source imitation of Minecraft" +mcl_credits.description = "A faithful Open Source clone of Minecraft" --- Sub-lists are sorted by number of commits +-- Sub-lists are sorted by number of commits, but the list should not be rearranged (-> new contributors are just added at the end of the list) mcl_credits.people = { - {"Creator of MineClone", { + {"Creator of MineClone", 0x0A9400, { "davedevils", }}, - {"Creator of MineClone2", { + {"Creator of MineClone2", 0xFBF837, { "Wuzzy", }}, - {"Maintainers", { + {"Maintainers", 0xFF51D5, { "Fleckenstein", "kay27", "oilboi", }}, - {"Developers", { + {"Developers", 0xF84355, { "bzoss", "AFCMS", "epCode", @@ -28,7 +28,7 @@ mcl_credits.people = { "Nicu", "aligator", }}, - {"Contributors", { + {"Contributors", 0x52FF00, { "Code-Sploit", "Laurent Rocher", "HimbeerserverDE", @@ -55,11 +55,11 @@ mcl_credits.people = { "nickolas360", "yutyo", }}, - {"3D Models", { + {"3D Models", 0x0019FF, { "22i", "tobyplowy", }}, - {"Textures", { + {"Textures", 0xFF9705, { "XSSheep", "kingoscargames", "leorockway", @@ -67,39 +67,125 @@ mcl_credits.people = { }}, } +local function add_hud_element(def, huds, y) + def.alignment = {x = 0, y = 0} + def.position = {x = 0.5, y = 0} + def.offset = {x = 0, y = y} + def.z_index = 1001 + local id = huds.player:hud_add(def) + table.insert(huds.ids, id) + huds.moving[id] = y + return id +end + function mcl_credits.show(player) local name = player:get_player_name() if mcl_credits.players[name] then return end - local hud_list = { - player:hud_add({ - hud_elem_type = "image", - text = "menu_bg.png", - position = {x = 0, y = 0}, - alignment = {x = 1, y = 1}, - scale = {x = -100, y = -100}, - z_index = 1000, - }) + local huds = { + new = true, -- workaround for MT < 5.5 (sending hud_add and hud_remove in the same tick) + player = player, + moving = {}, + ids = { + player:hud_add({ + hud_elem_type = "image", + text = "menu_bg.png", + position = {x = 0, y = 0}, + alignment = {x = 1, y = 1}, + scale = {x = -100, y = -100}, + z_index = 1000, + }), + player:hud_add({ + hud_elem_type = "text", + text = "Sneak to skip", + position = {x = 1, y = 1}, + alignment = {x = -1, y = -1}, + offset = {x = -5, y = -5}, + z_index = 1001, + number = 0xFFFFFF, + }) + }, } - mcl_credits.players[name] = hud_list + add_hud_element({ + hud_elem_type = "image", + text = "mineclone2_logo.png", + scale = {x = 1, y = 1}, + }, huds, 300, 0) + add_hud_element({ + hud_elem_type = "text", + text = mcl_credits.description, + number = 0x757575, + scale = {x = 5, y = 5}, + }, huds, 350, 0) + local y = 450 + for _, group in ipairs(mcl_credits.people) do + add_hud_element({ + hud_elem_type = "text", + text = group[1], + number = group[2], + scale = {x = 3, y = 3}, + }, huds, y, 0) + y = y + 25 + for _, name in ipairs(group[3]) do + y = y + 25 + add_hud_element({ + hud_elem_type = "text", + text = name, + number = 0xFFFFFF, + scale = {x = 1, y = 1}, + }, huds, y, 0) + end + y = y + 200 + end + huds.icon = add_hud_element({ + hud_elem_type = "image", + text = "mineclone2_icon.png", + scale = {x = 1, y = 1}, + }, huds, y) + mcl_credits.players[name] = huds end function mcl_credits.hide(player) local name = player:get_player_name() - local list = mcl_credits.players[name] - if list then - for _, id in pairs(list) do + local huds = mcl_credits.players[name] + if huds then + for _, id in pairs(huds.ids) do player:hud_remove(id) end end mcl_credits.players[name] = nil end -controls.register_on_press(function(player, key) - if key == "sneak" then - mcl_credits.hide(player) - elseif key == "aux1" then - mcl_credits.show(player) +minetest.register_on_leaveplayer(function(player) + mcl_credits.players[player:get_player_name()] = nil +end) + +minetest.register_globalstep(function(dtime) + for _, huds in pairs(mcl_credits.players) do + local player = huds.player + if not huds.new and player:get_player_control().sneak then + mcl_credits.hide(player) + else + local moving = {} + local any + for id, y in pairs(huds.moving) do + y = y - 1 + if y > -100 then + if id == huds.icon then + y = math.max(400, y) + else + any = true + end + player:hud_change(id, "offset", {x = 0, y = y}) + moving[id] = y + end + end + if not any then + mcl_credits.hide(player) + end + huds.moving = moving + end + huds.new = false end end) diff --git a/mods/HUD/mcl_credits/mod.conf b/mods/HUD/mcl_credits/mod.conf index b5532cd30..3df6370af 100644 --- a/mods/HUD/mcl_credits/mod.conf +++ b/mods/HUD/mcl_credits/mod.conf @@ -1,4 +1,3 @@ name = mcl_credits author = Fleckenstein description = Show a HUD containing the credits -depends = controls diff --git a/mods/HUD/mcl_credits/textures/mineclone2_icon.png b/mods/HUD/mcl_credits/textures/mineclone2_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..e479dfff5a55bf28d90056e968246e803aad0297 GIT binary patch literal 3961 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 Tj70 Date: Tue, 6 Apr 2021 11:59:22 +0200 Subject: [PATCH 03/32] Remove empty line from mcl_portals --- mods/ITEMS/mcl_portals/portal_end.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/mods/ITEMS/mcl_portals/portal_end.lua b/mods/ITEMS/mcl_portals/portal_end.lua index bf93b4c1f..192f5001c 100644 --- a/mods/ITEMS/mcl_portals/portal_end.lua +++ b/mods/ITEMS/mcl_portals/portal_end.lua @@ -170,7 +170,6 @@ function mcl_portals.end_teleport(obj, pos) -- Teleport back to the player's spawn or world spawn in the Overworld. if obj:is_player() then target = mcl_spawn.get_player_spawn_pos(obj) - end target = target or mcl_spawn.get_world_spawn_pos(obj) From ba15f01ca9f2b6652bac50ebb3caeeb096dbb2c1 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Tue, 6 Apr 2021 12:08:25 +0200 Subject: [PATCH 04/32] Add translations; Duplicate listing of people --- mods/HUD/mcl_credits/init.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/mods/HUD/mcl_credits/init.lua b/mods/HUD/mcl_credits/init.lua index a53ebbba9..ba30d2408 100644 --- a/mods/HUD/mcl_credits/init.lua +++ b/mods/HUD/mcl_credits/init.lua @@ -58,12 +58,22 @@ mcl_credits.people = { {"3D Models", 0x0019FF, { "22i", "tobyplowy", + "epCode", }}, {"Textures", 0xFF9705, { "XSSheep", + "Wuzzy", "kingoscargames", "leorockway", "xMrVizzy", + "yutyo" + }}, + {"Translations", 0x00FF60, { + "Wuzzy", + "Rocher Laurent", + "wuniversales", + "kay27", + "pitchum", }}, } From 5bdb3bc274be63ef0633ad1815ae2a447d15c52c Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Tue, 6 Apr 2021 12:14:43 +0200 Subject: [PATCH 05/32] Add MineClone5 section to credits --- mods/HUD/mcl_credits/init.lua | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mods/HUD/mcl_credits/init.lua b/mods/HUD/mcl_credits/init.lua index ba30d2408..40bafa19e 100644 --- a/mods/HUD/mcl_credits/init.lua +++ b/mods/HUD/mcl_credits/init.lua @@ -55,6 +55,13 @@ mcl_credits.people = { "nickolas360", "yutyo", }}, + {"MineClone5", 0xA60014, { + "kay27", + "Debiankaios", + "epCode", + "NO11", + "j45", + }}, {"3D Models", 0x0019FF, { "22i", "tobyplowy", From a348909ba3cb8d274e313e9f6fff56d933c3dda9 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Tue, 6 Apr 2021 12:50:36 +0200 Subject: [PATCH 06/32] Enderdragon: Proper Egg and XP spawning --- mods/ENTITIES/mobs_mc/ender_dragon.lua | 16 ++++++---------- mods/ITEMS/mcl_end/end_crystal.lua | 3 +-- mods/MAPGEN/mcl_structures/init.lua | 2 +- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/ender_dragon.lua b/mods/ENTITIES/mobs_mc/ender_dragon.lua index e62b0d16b..ddaea360f 100644 --- a/mods/ENTITIES/mobs_mc/ender_dragon.lua +++ b/mods/ENTITIES/mobs_mc/ender_dragon.lua @@ -50,8 +50,8 @@ mobs:register_mob("mobs_mc:enderdragon", { arrow = "mobs_mc:dragon_fireball", shoot_interval = 0.5, shoot_offset = -1.0, - xp_min = 12000, - xp_max = 12000, + xp_min = 500, + xp_max = 500, animation = { fly_speed = 8, stand_speed = 8, stand_start = 0, stand_end = 20, @@ -59,15 +59,11 @@ mobs:register_mob("mobs_mc:enderdragon", { run_start = 0, run_end = 20, }, ignores_nametag = true, - on_die = function(self, own_pos) - if self._egg_spawn_pos then - local pos = minetest.string_to_pos(self._egg_spawn_pos) - --if minetest.get_node(pos).buildable_to then - minetest.set_node(pos, {name = mobs_mc.items.dragon_egg}) - return - --end + on_die = function(self, pos) + if not self._respawned then + mcl_experience.throw_experience(pos, 11500) -- 500 + 11500 = 12000 + minetest.set_node(self._portal_pos and minetest.string_to_pos(self._portal_pos) or vector.add(mcl_vars.mg_end_platform_pos, vector.new(-27, 2, 0)), {name = mobs_mc.items.dragon_egg}) end - minetest.add_item(own_pos, mobs_mc.items.dragon_egg) end, fire_resistant = true, }) diff --git a/mods/ITEMS/mcl_end/end_crystal.lua b/mods/ITEMS/mcl_end/end_crystal.lua index d089c3cdf..8fcf67a1d 100644 --- a/mods/ITEMS/mcl_end/end_crystal.lua +++ b/mods/ITEMS/mcl_end/end_crystal.lua @@ -58,8 +58,7 @@ local function spawn_crystal(pos) for _, crystal in pairs(crystals) do crystal_explode(crystal) end - local dragon = minetest.add_entity(vector.add(portal_center, {x = 0, y = 10, z = 0}), "mobs_mc:enderdragon") - dragon:get_luaentity()._egg_spawn_pos = minetest.pos_to_string(vector.add(portal_center, {x = 0, y = 4, z = 0})) + minetest.add_entity(vector.add(portal_center, {x = 0, y = 10, z = 0}), "mobs_mc:enderdragon"):get_luaentity()._respawned = true end minetest.register_entity("mcl_end:crystal", { diff --git a/mods/MAPGEN/mcl_structures/init.lua b/mods/MAPGEN/mcl_structures/init.lua index 6a7f44dfb..4294215a9 100644 --- a/mods/MAPGEN/mcl_structures/init.lua +++ b/mods/MAPGEN/mcl_structures/init.lua @@ -313,7 +313,7 @@ mcl_structures.generate_fossil = function(pos, rotation, pr) end mcl_structures.generate_end_exit_portal = function(pos, rot) - minetest.add_entity(vector.add(pos, vector.new(3, 11, 3)), "mobs_mc:enderdragon") + minetest.add_entity(vector.add(pos, vector.new(3, 11, 3)), "mobs_mc:enderdragon"):get_luaentity()._portal_pos = minetest.pos_to_string(vector.add(pos, vector.new(3, 5, 3))) local path = minetest.get_modpath("mcl_structures").."/schematics/mcl_structures_end_exit_portal.mts" return mcl_structures.place_schematic(pos, path, rot or "0", nil, true) end From 055c406d7a02b01724eb0f952e9ab4f5d0a4c6f5 Mon Sep 17 00:00:00 2001 From: Doloment Date: Tue, 6 Apr 2021 18:57:06 +0700 Subject: [PATCH 07/32] Fix chest entity textures (trapped chests were lighter) --- .../mcl_chests/textures/mcl_chests_normal.png | Bin 689 -> 672 bytes .../textures/mcl_chests_normal_double.png | Bin 1031 -> 961 bytes .../mcl_chests/textures/mcl_chests_trapped.png | Bin 1209 -> 674 bytes .../textures/mcl_chests_trapped_double.png | Bin 2011 -> 965 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_normal.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_normal.png index 5133f53ff7ea3f44e51d8c339f7efa67f967eefe..9974f60d5733ae946cab3be3f6e805b284eaa235 100644 GIT binary patch delta 642 zcmV-|0)73l1)v3xDSt5kFc}#cI1&&eBO@#yC0WyMH2)#9bMNF?oibdv9=* z9@}+c&cdI={Wv-P=Py07AD6Jq1_M5@+!kY=%St;{Ij$?9DMUK3+Ox}bHv7H@*b135}$+l?yK>7Y;8M~ zv7W$uV0^@nnqQokgW9%38R!Y7Bg?8(-a60f^=*g0^?&;At}X-Mo(mjja7O&i_UsO` zHoeF(d1*`mDr?h;K*y6g0i0H4O@kDZCk_Kkxd~o_0D`K#5lIL(Bbz2du?EIWMFXosuH7!RALa?3?xyH+VIq+?%ppuO3Xe zLi}@lvyVWD5AB!0mzVkFF?{nC9*L&~RQW`Ls#`%4>uEaw zz6XdL5H%epEiw49TrPj@0nbWD`G!@NWlgL9Q=(=JAWmE*>wt)c1o2LZ88 zl5s~6aLaFqb$@5G;f4cNFwHtn{~#b%c+eDm_9rMw9h#v2aY=x%BTgec_h;;eG@+=| zyEzX?*F2Vo&*cU8Pr9yD5@dOe*0J`d9O%Voiztkaf4f>;Rkst`RW%11Njr|tq5SrP z{kUaqC$tuAkS<8oP{*~8&Z~NLJE7HSL)kI1ip4k1i+@UGJK=W)i?UN70hAYjk}iIj zzd4xSVb^9C88$D87=XGqYimqA9x}k`(rD%<*gSn0n3$VLDH*_Dns>Zy=ur&em;ugm z;3fwE7~l&5?MrMPyP;3Od4|nPql3Uix+W<$C;}QL2R^882>2KjK*$Gmou+dWH8xLk z8)T4o4S!JkkM;lOEe0000o88{LUBO@a$EG$GdC_Ozr zPChV6Nl95oH)2aWaaKfkTS40Uv!_>Z&VK*|Q4at7!|Wg872H%1KuyPop$J0>a2MqT;@aO~UBJ>=WQ}Ab$ff0N zEPyWN=~6_<lp&)a0&vpkdk>iv`#nQ!a0WesUkuxFVW@# z^(LQ#lPs!zV4mazW|fLa*mMCtfJ*Qo>c=bdz3VC~Xn!riv=JgH^j)(b+=8K`vhp$r zDhV`+vJl(_s6^Mq*j6_Q+P1n+WivndPShi~{u#rAV|=5&6JDBY>?C6g1v)mJUq&=t})5jCj`bYG^w`+!V_PO_dJpDcQeNxBR^vc1)Kpwzzthg1Nu1x{uZy)ioM9_7ROnSuNKx3=Tvk9GFv`4X$vEC&5oC zl?NcmAj3w=1<{B_D&b@mE3ai3Rr8YZf+=T6fk$Z6e{7^<^r)!HifLO zAmAOW-oIFfGmBs+5Kug+AaJ@Sz;(hAsssqxTz`N{op4kq+;dhil5h&@C{@BO%8;IFpRf5x-$$*w~s%6v&JJ^7OI%4_*97m@k#w0>$sDQ zEq@DDhq;NHs7wrLI8Ihr2vv8Mu}_BTj3*sF5F>%H&mUwweaNxi_&#F`1>89mF(Dm( zwjk6S!!Q}~D8~-Q_ZeF(kP;H7Q71hWZt6`RSVEP+Dm&mw#uf{3FNvq2JMS=8j(Egi z4J<5Xiv?IGfpWP5h6>6iEMzeV6tcw@^f23`ckDa9jUC@{dTn@w54J+Kw#61(Y_Y}v Z#V-QG-H{0gf6V{@002ovPDHLkV1oaNq&ENn delta 1021 zcmV^AB0gjv7r-)aG~#p08KqYDnQYBeXp%PBn)}&O`kHaeJ}xk&ypme; zp*_dnN;|ca4K~?_1-9&Ox=60eWWXy3PXFT1UH%F_5r_x?4uff=KarBaTeP_9$ z;3$E;O&1*~AZztN4f_}YT;A_;0o3pUVKXmaQ)ABeA}@7&HsO9~S7}vMjJsY?WF~ zvR`z$nB<6XCtF$TCi{dyt!xN!t&IAx3U5V)VMmPYnz0SgiZR|8fpw&57E zOj}q)jAydX2)I}rH~jJj3P_YfVkrRh8olA@h-b2=<9PA*2&Y4N r3A_aU{w7`mFM;3kDR}YX#fyIcKpwkkCH7o88{LUBO@a$EG$GdC_Ozr zPChV6Nl95oH*r=(cUwt(UrdQ=PLXg@_=nP>00001bW%=J06^y0W&i*JBS}O-R7l6| zlEI4FP!xt;^Z_a@eStnf8yVFI#{)PrGLv}ycsi_7VAAYvy~#V z?kG32D-ucEm0=i@XXv^221n_!T^Hso{5jl@ljDE>(j)6}39C|P!271xWX$(iX{V~k zjshA&qsuOF zmi{caCj<=K@P8m+_0n`Twlr`g;Yt11ylo^6^~0xBJoz7-zsLJ(RJz-zlJ-oNeMLKKc|0epTCc zC|5NF4AV&xpF`#SSL4md+;%7dnpzPPXYwSR4g($^Czt}L@!edj)NoNb4{ zj5D1D%f`gtO= zHW8RS+JC6aESpKIF?oWTz&w>TkhOoTf1bPi#4wB(WfWJ7aW6WwJXrX^n*6!@QcBS& zDMA}=enj(j^4WMTrRbCtz{O@6t=b8LZ&Hd*iB9zz0}Oy7v?TYUfgB*t7o=z)3Rm&< woD>a+_6qkQMO(<5;D6wxlpgA#{>Sr~F000DMK}|sb0I`n?{9y$E000SaNLh0L01mzY z01mzZ>O!%=00007bV*G`2iyt~2@*72tl>rg000)d0vx3}B)`}_ON z$G4Ba`117T7y5`HmYffduYV(Rdor$-J-;bJ@s8W{(6RxD{r2hIZ+!p!ehWhS24s`K z*dJe?wlL25zkk+%9JlGAWjvd##49A%ry=+d`uOU_PRu8#l|8?4>THZ>j@$Imya5jn z58DlTdOge$Lo7MGBMgCg#Yarr0OEktWrM(G-EfjO08z&@fLPXOW#=(O0jG=T`~)DI zL5%T=I;H_UTiJQc6SV=aY?$8GC8S!jo=YO%$4M1Ff6Y>W9lMO(Wr;WJ$ z5&UNxke>jec0tUad;;XOvh!H}A;bpr+9ObyBZgT28RS+R^CLKA13Xbq*Xy6y2*!B> z5QUGqUTlx~7jXl)s%*HYzX1rdNkW|Y{%#}}(SRg34t)b4jXXAEwPF)_s2 z0M|0_)Ow@5tk-0YtuLks#KOxXZ7bxZ>gYXi*f$@!jEb{=C>h)R*%iV>WuV)AqW@vP+-7<)^2 zZ+~UyF@zxMxf;;Z%Fbh_HUKdS$LH7vB-7sjHg`$`$m1P6;q-|OAg`63#}IW)1Bm5` z7*Txs(w}p!>^z1THh4?}6w_aI@x*(kZU7tH*8pNXO`a*5_aqx(%+w74HtRR*GewCx z`JEfzqj<*CHlT-%_Vh7*Q+AQ-w6f>7<$wP>%tnPmyU5riW86ggsvO9eiYf=H*d$|{ z%&~cO^U5*i`_q?K*O)%<<@NQpcs2mvzC6dr)^ofsugM%6N&eXIB#ALUPP{`EQ~A8E z!1&O-Q|ld)*JO^ZPojJNI_u9EAf_q?o)!p;+m|5Ear%(1yJxCl?kg)PpL_e;rZGRKw+Lw-jr-1~Tv zb18XE=Ga`EMR>A^@9Bf|$?SPe=6@U7X0utE(zz0)b0tdWN|er(D4i=&I#;4}u0-iv ziPE_erE?`p=Sq~$l_;GnQ94(mbSkby>0F7@xe}#wMxM>8Vl(nQc6Id=*tZtL<|9;J P00000NkvXXu0mjf?&D5S diff --git a/mods/ITEMS/mcl_chests/textures/mcl_chests_trapped_double.png b/mods/ITEMS/mcl_chests/textures/mcl_chests_trapped_double.png index 95f768f97c0e7f1243b73df472b10174c7e69246..88ff45825f872490246c2b5eb81f18bb907d887b 100644 GIT binary patch delta 955 zcmV;s14R7W55)(N7=Hu<0000W_+m@|001yhOjJdG000>o88{LUBO@a$EG$GdC_Ozr zPChV6Nl95oH)2aWaaKfkTSt3&X@Ae9?6i?oICkEmixEnW zr4V{tW{i|m3C5FhE+z4P$z_X!>p2~}}A;J_jdRRQteeWdvrWib&XW0X~3A@B!*YEAzdpGJh**EWxxPA_?>zvp2p0LrG=j z<#=35piY#9;4VNVIwr=px=GMB)qN_O`N?;}F2U8$7#7N)w2}L{e9Jav|g#MR?DytsMU&Uxt3vYAS&U&oa$_FiDPVy ze@dx506_*BHdHPMhb&YHC(BrQEyJjq7mpT9Ia>rJ1bPRnxb~!gxuc~}3CA`Uh;*_k zqQ0#xdRqdMW9vVx(6Q&2~#5^fo7 zE|AtwHOf(?jFb_WxeST`mJ+I%rHs_OJzUK&C_f~ee%ldV&Pd}M*z8=tjv>SP+SQUx zRnN+-U@gP+H3ADc>1`?u!+*WbJ1-2wc(bEB!?1Mw@bfooJg`Nfim8gv*VbDVpVZH= zj(avX%EW*Mqj-gdP<3Z1`)H`nc--cFF%%g4{9Z=W`wZ)i?ou{az@1YO z5z^+T3qrjS43i-bGi-l!m$LZ+2_aDuwv!X#Cf@X(#Z(EbvV9(>Y`y^Z;%FMU^EPwk zkcSM`z=C`>Ux2k^D3>c>sGw}Z0v3TlE;O5OLBC15$G+p+*zp~w+k{8>V9RAITWqn# d7F+yZ`~s_X-5jfjq&NTo002ovPDHLkV1jaqv%LTS literal 2011 zcmZuydpy(o8~?5y#2QJogC#|j>nhVG3^}Z54pOQacE)j=%eHW0l*2iSKcDye^?9D>^}If*Zs(k!N}5Ul z06?+Mr`=^SQD&H(@-ja#n2;a~-v!#a+5te-ZOAu2IoVk;!r7Yw0LsnV1`^v>wa7pP zD%RCeVN^*~QB6)gsNY%!!KjWGsUG10)M&pb5)k1RM5daONz?-;OwCO#NXf@YGS&~+ z({`RQKA-bn-qa`UP7!J%qmKKjC8eM5mjkP6>^r1-!rXk1Tx)-er}=KP7Atd!(uJau zqEF1~hB9IQ7)4rO8Z)yc7H&K#uj~_xq07tD-F3^~)+KdyuN9^`Ztbhvs`PpJ%SN|l z`212Qj=(z<_R3CN&iOeII(Trt)3PWni{gb&$emp)8V&6V@K-fyUPy}dtOgkl+9qsK zZ*vkhw(fE0o2x!{&q43O^wg!{U@#RS9g3gwS>DvmeMe(G0xidz-##M^L^S-A=WNc9 zH-F?#q$D7LT1y=c=O`=TEwtsCLDeaV?AA>};!q_4r{NI{USyd-e8SDH4j$l|0cfRH z8zXFuzDvc7HD0_>uc2PxY&oPo-}MCQt6R@JfuRq;qhZ3~T)oW_I;b`j$jb^eadXO< zLs2O`nPe8q_~2f-7tFos51e^3?(V_fG4|tzfl9*4PVi1-}0y zumVZ!ZF`zJEAh#0H1Nv&wj-mo=`&mdrPXp$G+`J+2N|YRA#qY+9Idy?0+UZ^Ae_`J z&XlV8R-@UFNcw9lLRanxfR(0;DxOJ1b68h#VeVe#wK1X2*je-f56Jd_5W$PFTuY+F zTKFjlyg1(^%8q1gDzZU^{+t=y$At`ml}PDNWOiH0a8r@3^0+}Jf@-79$nWxVO|eOH zy-Cb=@K0PL`^0^pL>%-r861t`q@{v+|HpJ!=>RzkF4}{1l$~@@j}^Q5KXRp3t6s3b zduFY6CowJ3#)3I-uInItU6@1BGpkmm>*pGFJnJcC2PwC4txM4>V)wpJCk=}Y{Jekv z5?z4M@Mx5v&*8aK1*a%*S@NIZO@9Tg;t}Rhq&SM>khf53)IZ{)ls}b7mg>%h68Ech z^N(F!P{|AltLJ-k)uf!@V=olfcsn-f@^*Em*1p!}Bd+n9zEsxs^46);$o4ASJ$}O1 z3G7$tbCs>mgZ4kVz=~|?;P}JzfRd5&my&LrQS$ix)vDn%im_OC#WybM1m+MDP@Eui zvlK(v_d*6Aq^tKH{97A;#eMRF4zzz~#{m?+buh8!+Yy+NrxOyh(uewzSwJL%sR=7b z@sYK@HS!0J=#?1_YP#uZ0Zn76wWw1_`pMN&YH|+i!@D-`|dt>sAbN`5q+N%s68Z}WnKHj($ z0^GDKF|JPT_Ge_$GdL@>{WQ#6#2i+nWF~vT_(83fHjIfEX>N9WSdhC+8vCDYheeCS zMK@8L@9VPX(9Xg;ti=KKK!{fuK<3?pw!EXMg$KWEeSi;c^0Y;17OQ5pL3QmyEP)WV z#=@z_34M*`=jWS5H+tJ5>ztf#w`1A$6xiGg7Vq|GvYggw>fKn zfHaq`dO3SNl$_l^Nr(?)FvLd8a3}7rP8;v-8k3+A-)M`=QM%fi)L-^ztI&Axu9mHF2S0&EGEwja6mKJGqLRid#;2GuEs!DKEWep*WQB%f0 zvH>56Yj#(e2D$uf{X)T`tg!uBgz#+)O;WynkEC$#Ay9<)L z^KOjzi6omRiln*Lw-3!G^W20T0ouqfle9n(qY zGb#sNc>ff&Ubz$=g*Q(zD43-GChJGcP6Xm`i8y9Yw&GcxC#!kduv^z%B1S6aN7rOq z7nkh1LqX7`3olc4w-o&GYy>VmPAuoYzX-lgt=T69k_~F^t7Lh9h`qOzYei3C=E6}&Z?{1MiL|Kgr4X^M@ z`Db!Qt^4)o-G@CJrsl7kM&`6V8qkkcp{6$OMcy^7A9}T|V;%9A{Whvyok8sy1OH~M ohmTro(S=}T Date: Tue, 6 Apr 2021 14:50:34 +0200 Subject: [PATCH 08/32] Add bossbars --- mods/CORE/mcl_util/init.lua | 2 +- mods/ENTITIES/mcl_mobs/api.lua | 16 +-- mods/ENTITIES/mobs_mc/ender_dragon.lua | 3 + mods/ENTITIES/mobs_mc/wither.lua | 3 +- mods/HUD/mcl_bossbars/init.lua | 124 ++++++++++++++++++ mods/HUD/mcl_bossbars/mod.conf | 4 + .../mcl_bossbars/textures/mcl_bossbars.png | Bin 0 -> 3689 bytes .../textures/mcl_bossbars_empty.png | Bin 0 -> 3369 bytes 8 files changed, 142 insertions(+), 10 deletions(-) create mode 100644 mods/HUD/mcl_bossbars/init.lua create mode 100644 mods/HUD/mcl_bossbars/mod.conf create mode 100644 mods/HUD/mcl_bossbars/textures/mcl_bossbars.png create mode 100644 mods/HUD/mcl_bossbars/textures/mcl_bossbars_empty.png diff --git a/mods/CORE/mcl_util/init.lua b/mods/CORE/mcl_util/init.lua index a43c3d5d0..ac913de39 100644 --- a/mods/CORE/mcl_util/init.lua +++ b/mods/CORE/mcl_util/init.lua @@ -410,7 +410,7 @@ function mcl_util.get_color(colorstr) local mc_color = mcl_colors[colorstr:upper()] if mc_color then colorstr = mc_color - elseif #colorstr ~= 7 or colorstr:sub(1, 1) ~= "#"then + elseif #colorstr ~= 7 or colorstr:sub(1, 1) ~= "#" then return end local hex = tonumber(colorstr:sub(2, 7), 16) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 6e932ed5e..e599f2127 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -3526,14 +3526,6 @@ local mob_step = function(self, dtime) -- end rotation - -- knockback timer - if self.pause_timer > 0 then - - self.pause_timer = self.pause_timer - dtime - - return - end - -- run custom function (defined in mob lua file) if self.do_custom then @@ -3543,6 +3535,14 @@ local mob_step = function(self, dtime) end end + -- knockback timer + if self.pause_timer > 0 then + + self.pause_timer = self.pause_timer - dtime + + return + end + -- attack timer self.timer = self.timer + dtime diff --git a/mods/ENTITIES/mobs_mc/ender_dragon.lua b/mods/ENTITIES/mobs_mc/ender_dragon.lua index ddaea360f..509409a2e 100644 --- a/mods/ENTITIES/mobs_mc/ender_dragon.lua +++ b/mods/ENTITIES/mobs_mc/ender_dragon.lua @@ -59,6 +59,9 @@ mobs:register_mob("mobs_mc:enderdragon", { run_start = 0, run_end = 20, }, ignores_nametag = true, + do_custom = function(self) + mcl_bossbars.update_boss(self, "Ender Dragon", "light_purple") + end, on_die = function(self, pos) if not self._respawned then mcl_experience.throw_experience(pos, 11500) -- 500 + 11500 = 12000 diff --git a/mods/ENTITIES/mobs_mc/wither.lua b/mods/ENTITIES/mobs_mc/wither.lua index caf5a248d..8e7f7eb95 100644 --- a/mods/ENTITIES/mobs_mc/wither.lua +++ b/mods/ENTITIES/mobs_mc/wither.lua @@ -73,6 +73,7 @@ mobs:register_mob("mobs_mc:wither", { self.object:set_properties({textures={self.base_texture}}) self.armor = {undead = 80, fleshy = 80} end + mcl_bossbars.update_boss(self, "Wither", "dark_purple") end, on_spawn = function(self) minetest.sound_play("mobs_mc_wither_spawn", {object=self.object, gain=1.0, max_hear_distance=64}) @@ -115,4 +116,4 @@ mobs:register_arrow("mobs_mc:wither_skull", { --Spawn egg mobs:register_egg("mobs_mc:wither", S("Wither"), "mobs_mc_spawn_icon_wither.png", 0, true) -mcl_wip.register_wip_item("mobs_mc:wither") \ No newline at end of file +mcl_wip.register_wip_item("mobs_mc:wither") diff --git a/mods/HUD/mcl_bossbars/init.lua b/mods/HUD/mcl_bossbars/init.lua new file mode 100644 index 000000000..38dbbe376 --- /dev/null +++ b/mods/HUD/mcl_bossbars/init.lua @@ -0,0 +1,124 @@ +mcl_bossbars = { + bars = {}, + huds = {}, + colors = {"light_purple", "blue", "red", "green", "yellow", "dark_purple", "white"}, +} + +function mcl_bossbars.recalculate_colors() + local sorted = {} + local colors = mcl_bossbars.colors + local color_count = #colors + local frame_count = color_count * 2 + for i, color in ipairs(colors) do + local idx = i * 2 - 1 + local image = "mcl_bossbars.png" + .. "^[transformR270" + .. "^[verticalframe:" .. frame_count .. ":" .. (idx - 1) + .. "^(mcl_bossbars_empty.png" + .. "^[lowpart:%d:mcl_bossbars.png" + .. "^[transformR270" + .. "^[verticalframe:" .. frame_count .. ":" .. idx .. ")" + local _, hex = mcl_util.get_color(color) + sorted[color] = { + image = image, + hex = hex, + } + end + mcl_bossbars.colors_sorted = sorted +end + +function mcl_bossbars.update_bar(player, text, color, percentage) + local cdef = mcl_bossbars.colors_sorted[color] + table.insert(mcl_bossbars.bars[player:get_player_name()], {color = cdef.hex, text = text, image = string.format(cdef.image, percentage)}) +end + +function mcl_bossbars.update_boss(luaentity, name, color) + local object = luaentity.object + local text = luaentity.nametag + if not text or text == "" then + text = name + end + local percentage = math.floor(luaentity.health / luaentity.hp_max * 100) + for _, obj in pairs(minetest.get_objects_inside_radius(object:get_pos(), 128)) do + if obj:is_player() then + mcl_bossbars.update_bar(obj, text, color, percentage) + end + end +end + +minetest.register_on_joinplayer(function(player) + local name = player:get_player_name() + mcl_bossbars.huds[name] = {} + mcl_bossbars.bars[name] = {} +end) + +minetest.register_on_leaveplayer(function(player) + local name = player:get_player_name() + mcl_bossbars.huds[name] = nil + mcl_bossbars.bars[name] = nil +end) + +minetest.register_globalstep(function() + for _, player in pairs(minetest.get_connected_players()) do + local name = player:get_player_name() + local bars = mcl_bossbars.bars[name] + local huds = mcl_bossbars.huds[name] + local huds_new = {} + local i = 0 + + while #huds > 0 or #bars > 0 do + local bar = table.remove(bars, 1) + local hud = table.remove(huds, 1) + + if bar and not hud then + hud = { + color = bar.color, + image = bar.image, + text = bar.text, + text_id = player:hud_add({ + hud_elem_type = "text", + text = bar.text, + number = bar.color, + position = {x = 0.5, y = 0}, + alignment = {x = 0, y = 1}, + offset = {x = 0, y = i * 40}, + }), + image_id = player:hud_add({ + hud_elem_type = "image", + text = bar.image, + position = {x = 0.5, y = 0}, + alignment = {x = 0, y = 1}, + offset = {x = 0, y = i * 40 + 25}, + scale = {x = 3, y = 3}, + }), + } + elseif hud and not bar then + player:hud_remove(hud.text_id) + player:hud_remove(hud.image_id) + hud = nil + else + if bar.text ~= hud.text then + player:hud_change(hud.text_id, "text", bar.text) + hud.text = bar.text + end + + if bar.color ~= hud.color then + player:hud_change(hud.text_id, "number", bar.color) + hud.color = bar.color + end + + if bar.image ~= hud.image then + player:hud_change(hud.image_id, "text", bar.image) + hud.image = bar.image + end + end + + table.insert(huds_new, hud) + i = i + 1 + end + + mcl_bossbars.huds[name] = huds_new + end +end) + +mcl_bossbars.recalculate_colors() diff --git a/mods/HUD/mcl_bossbars/mod.conf b/mods/HUD/mcl_bossbars/mod.conf new file mode 100644 index 000000000..64cbd4c9f --- /dev/null +++ b/mods/HUD/mcl_bossbars/mod.conf @@ -0,0 +1,4 @@ +name = mcl_bossbars +author = Fleckenstein +description = Show enderdragon & wither boss bars. Also allows custom bars. +depends = mcl_util, mcl_colors diff --git a/mods/HUD/mcl_bossbars/textures/mcl_bossbars.png b/mods/HUD/mcl_bossbars/textures/mcl_bossbars.png new file mode 100644 index 0000000000000000000000000000000000000000..55bf36dc288f271d12228a67a6a39c98c6ca18e9 GIT binary patch literal 3689 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 literal 0 HcmV?d00001 diff --git a/mods/HUD/mcl_bossbars/textures/mcl_bossbars_empty.png b/mods/HUD/mcl_bossbars/textures/mcl_bossbars_empty.png new file mode 100644 index 0000000000000000000000000000000000000000..1e50b6afc2a8dddc0748ae7763a5975ef6956b24 GIT binary patch literal 3369 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 SEo%JRzk$BCkyed{6ZSuzSwWZp literal 0 HcmV?d00001 From 962a13847e64613e53f1a2542860d3439a9a6d4f Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Tue, 6 Apr 2021 14:57:29 +0200 Subject: [PATCH 09/32] Fix dragons summoned using commands spawning an egg on the exit portal --- mods/ENTITIES/mobs_mc/ender_dragon.lua | 4 ++-- mods/ITEMS/mcl_end/end_crystal.lua | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/ender_dragon.lua b/mods/ENTITIES/mobs_mc/ender_dragon.lua index 509409a2e..01c346579 100644 --- a/mods/ENTITIES/mobs_mc/ender_dragon.lua +++ b/mods/ENTITIES/mobs_mc/ender_dragon.lua @@ -63,9 +63,9 @@ mobs:register_mob("mobs_mc:enderdragon", { mcl_bossbars.update_boss(self, "Ender Dragon", "light_purple") end, on_die = function(self, pos) - if not self._respawned then + if self._portal_pos then mcl_experience.throw_experience(pos, 11500) -- 500 + 11500 = 12000 - minetest.set_node(self._portal_pos and minetest.string_to_pos(self._portal_pos) or vector.add(mcl_vars.mg_end_platform_pos, vector.new(-27, 2, 0)), {name = mobs_mc.items.dragon_egg}) + minetest.set_node(minetest.string_to_pos(self._portal_pos), {name = mobs_mc.items.dragon_egg}) end end, fire_resistant = true, diff --git a/mods/ITEMS/mcl_end/end_crystal.lua b/mods/ITEMS/mcl_end/end_crystal.lua index 8fcf67a1d..9e4fa13fd 100644 --- a/mods/ITEMS/mcl_end/end_crystal.lua +++ b/mods/ITEMS/mcl_end/end_crystal.lua @@ -58,7 +58,7 @@ local function spawn_crystal(pos) for _, crystal in pairs(crystals) do crystal_explode(crystal) end - minetest.add_entity(vector.add(portal_center, {x = 0, y = 10, z = 0}), "mobs_mc:enderdragon"):get_luaentity()._respawned = true + minetest.add_entity(vector.add(portal_center, {x = 0, y = 10, z = 0}), "mobs_mc:enderdragon") end minetest.register_entity("mcl_end:crystal", { From 83b9cf3ad258620ff3b89bc9c1ce01b02220b82e Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Tue, 6 Apr 2021 15:48:17 +0200 Subject: [PATCH 10/32] End exit portal openng / closing on dragon death / spawn --- mods/ENTITIES/mobs_mc/ender_dragon.lua | 8 ++++++-- mods/ITEMS/mcl_end/end_crystal.lua | 4 +++- mods/MAPGEN/mcl_mapgen_core/init.lua | 14 ++++++++++---- mods/MAPGEN/mcl_structures/init.lua | 12 ++++++++++-- .../mcl_structures_end_exit_portal.mts | Bin 222 -> 193 bytes .../mcl_structures_end_exit_portal_open.mts | Bin 0 -> 222 bytes 6 files changed, 29 insertions(+), 9 deletions(-) create mode 100644 mods/MAPGEN/mcl_structures/schematics/mcl_structures_end_exit_portal_open.mts diff --git a/mods/ENTITIES/mobs_mc/ender_dragon.lua b/mods/ENTITIES/mobs_mc/ender_dragon.lua index 01c346579..50aaacd4b 100644 --- a/mods/ENTITIES/mobs_mc/ender_dragon.lua +++ b/mods/ENTITIES/mobs_mc/ender_dragon.lua @@ -64,8 +64,12 @@ mobs:register_mob("mobs_mc:enderdragon", { end, on_die = function(self, pos) if self._portal_pos then - mcl_experience.throw_experience(pos, 11500) -- 500 + 11500 = 12000 - minetest.set_node(minetest.string_to_pos(self._portal_pos), {name = mobs_mc.items.dragon_egg}) + local portal_pos = minetest.string_to_pos(self._portal_pos) + mcl_structures.call_struct(portal_pos, "end_exit_portal_open") + if self._initial then + mcl_experience.throw_experience(pos, 11500) -- 500 + 11500 = 12000 + minetest.set_node(vector.add(portal_pos, vector.new(3, 5, 3)), {name = mobs_mc.items.dragon_egg}) + end end end, fire_resistant = true, diff --git a/mods/ITEMS/mcl_end/end_crystal.lua b/mods/ITEMS/mcl_end/end_crystal.lua index 9e4fa13fd..63a37d3c6 100644 --- a/mods/ITEMS/mcl_end/end_crystal.lua +++ b/mods/ITEMS/mcl_end/end_crystal.lua @@ -58,7 +58,9 @@ local function spawn_crystal(pos) for _, crystal in pairs(crystals) do crystal_explode(crystal) end - minetest.add_entity(vector.add(portal_center, {x = 0, y = 10, z = 0}), "mobs_mc:enderdragon") + local portal_pos = vector.add(portal_center, vector.new(-3, -1, -3)) + mcl_structures.call_struct(portal_pos, "end_exit_portal") + minetest.add_entity(vector.add(portal_pos, vector.new(3, 11, 3)), "mobs_mc:enderdragon"):get_luaentity()._portal_pos = minetest.pos_to_string(portal_pos) end minetest.register_entity("mcl_end:crystal", { diff --git a/mods/MAPGEN/mcl_mapgen_core/init.lua b/mods/MAPGEN/mcl_mapgen_core/init.lua index e08b55ba3..237579dbe 100644 --- a/mods/MAPGEN/mcl_mapgen_core/init.lua +++ b/mods/MAPGEN/mcl_mapgen_core/init.lua @@ -54,8 +54,7 @@ local superflat = mg_name == "flat" and minetest.get_mapgen_setting("mcl_superfl local WITCH_HUT_HEIGHT = 3 -- Exact Y level to spawn witch huts at. This height refers to the height of the floor --- End exit portal position. This is temporary. --- TODO: Remove the exit portal generation when the ender dragon has been implemented. +-- End exit portal position local END_EXIT_PORTAL_POS = table.copy(mcl_vars.mg_end_platform_pos) END_EXIT_PORTAL_POS.x = END_EXIT_PORTAL_POS.x - 30 END_EXIT_PORTAL_POS.z = END_EXIT_PORTAL_POS.z - 3 @@ -1251,6 +1250,13 @@ local function generate_clay(minp, maxp, blockseed, voxelmanip_data, voxelmanip_ return lvm_used end +local function generate_end_exit_portal(pos) + local dragon_entity = minetest.add_entity(vector.add(pos, vector.new(3, 11, 3)), "mobs_mc:enderdragon"):get_luaentity() + dragon_entity._initial = true + dragon_entity._portal_pos = minetest.pos_to_string(pos) + mcl_structures.call_struct(pos, "end_exit_portal") +end + -- TODO: Try to use more efficient structure generating code local function generate_structures(minp, maxp, blockseed, biomemap) local chunk_has_desert_well = false @@ -1490,11 +1496,11 @@ local function generate_structures(minp, maxp, blockseed, biomemap) for y=maxp.y, minp.y, -1 do local p = {x=END_EXIT_PORTAL_POS.x, y=y, z=END_EXIT_PORTAL_POS.z} if minetest.get_node(p).name == "mcl_end:end_stone" then - mcl_structures.call_struct(p, "end_exit_portal") + generate_end_exit_portal(p) return end end - mcl_structures.call_struct(END_EXIT_PORTAL_POS, "end_exit_portal") + generate_end_exit_portal(END_EXIT_PORTAL_POS) end end diff --git a/mods/MAPGEN/mcl_structures/init.lua b/mods/MAPGEN/mcl_structures/init.lua index 4294215a9..d75854352 100644 --- a/mods/MAPGEN/mcl_structures/init.lua +++ b/mods/MAPGEN/mcl_structures/init.lua @@ -87,6 +87,8 @@ mcl_structures.call_struct = function(pos, struct_style, rotation, pr) return mcl_structures.generate_fossil(pos, rotation, pr) elseif struct_style == "end_exit_portal" then return mcl_structures.generate_end_exit_portal(pos, rotation) + elseif struct_style == "end_exit_portal_open" then + return mcl_structures.generate_end_exit_portal_open(pos, rotation) elseif struct_style == "end_portal_shrine" then return mcl_structures.generate_end_portal_shrine(pos, rotation, pr) end @@ -313,11 +315,15 @@ mcl_structures.generate_fossil = function(pos, rotation, pr) end mcl_structures.generate_end_exit_portal = function(pos, rot) - minetest.add_entity(vector.add(pos, vector.new(3, 11, 3)), "mobs_mc:enderdragon"):get_luaentity()._portal_pos = minetest.pos_to_string(vector.add(pos, vector.new(3, 5, 3))) local path = minetest.get_modpath("mcl_structures").."/schematics/mcl_structures_end_exit_portal.mts" return mcl_structures.place_schematic(pos, path, rot or "0", nil, true) end +mcl_structures.generate_end_exit_portal_open = function(pos, rot) + local path = minetest.get_modpath("mcl_structures").."/schematics/mcl_structures_end_exit_portal_open.mts" + return mcl_structures.place_schematic(pos, path, rot or "0", nil, true) +end + local function shrine_placement_callback(p1, p2, size, rotation, pr) -- Find and setup spawner with silverfish local spawners = minetest.find_nodes_in_area(p1, p2, "mcl_mobspawners:spawner") @@ -535,7 +541,7 @@ end -- Debug command minetest.register_chatcommand("spawnstruct", { - params = "desert_temple | desert_well | igloo | witch_hut | boulder | ice_spike_small | ice_spike_large | fossil | end_exit_portal | end_portal_shrine | nether_portal | dungeon", + params = "desert_temple | desert_well | igloo | witch_hut | boulder | ice_spike_small | ice_spike_large | fossil | end_exit_portal | end_exit_portal_opens | end_portal_shrine | nether_portal | dungeon", description = S("Generate a pre-defined structure near your position."), privs = {debug = true}, func = function(name, param) @@ -567,6 +573,8 @@ minetest.register_chatcommand("spawnstruct", { mcl_structures.generate_ice_spike_large(pos, rot, pr) elseif param == "end_exit_portal" then mcl_structures.generate_end_exit_portal(pos, rot, pr) + elseif param == "end_exit_portal_open" then + mcl_structures.generate_end_exit_portal_open(pos, rot, pr) elseif param == "end_portal_shrine" then mcl_structures.generate_end_portal_shrine(pos, rot, pr) elseif param == "dungeon" and mcl_dungeons and mcl_dungeons.spawn_dungeon then diff --git a/mods/MAPGEN/mcl_structures/schematics/mcl_structures_end_exit_portal.mts b/mods/MAPGEN/mcl_structures/schematics/mcl_structures_end_exit_portal.mts index bc24f800a6de0e4265fdbe08808c9720061b8490..30d145bd7fdc822259191c918696b74769628d72 100644 GIT binary patch delta 154 zcmcb|c#u)pHze4XfrWvcft7*19t0RzCJGzWmE;#CXQUQef$8}2#GIUpIa?=n^ED`N zxH`Vx{qw7j;reJ1ys)}uDrD>;&p_i$xl%M#|4o_Hb;dWRuj`fdDjvh*7QKNMy&unx^$sU)L+^RXm2rEqVhjdOw~yd0eDy%Dic&uPyg1I8yyH zO~3W?FE<7=#tl0-et5I*%~5yCuvOaK+coXSeq%5FGkVh6GdgztnH3o08erZh5UT|M Dl|EWe literal 0 HcmV?d00001 From 1d587b88955fc1de22e78e8dc64c9d440725ed8d Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Tue, 6 Apr 2021 15:59:59 +0200 Subject: [PATCH 11/32] Fix crash in wieldview --- mods/PLAYER/wieldview/init.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mods/PLAYER/wieldview/init.lua b/mods/PLAYER/wieldview/init.lua index 48f3f99bd..6021dd369 100644 --- a/mods/PLAYER/wieldview/init.lua +++ b/mods/PLAYER/wieldview/init.lua @@ -70,6 +70,10 @@ minetest.register_on_joinplayer(function(player) local name = player:get_player_name() wieldview.wielded_item[name] = "" minetest.after(0, function(player) + -- if the player left :is_player() will return nil + if not player:is_player() then + return + end wieldview:update_wielded_item(player) local itementity = minetest.add_entity(player:get_pos(), "wieldview:wieldnode") itementity:set_attach(player, "Hand_Right", vector.new(0, 1, 0), vector.new(90, 0, 45)) From 38a12e59daebe9efc9f797db4c12e8ab2263d5b1 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Tue, 6 Apr 2021 16:02:18 +0200 Subject: [PATCH 12/32] Fix comment indentation in wieldview --- mods/PLAYER/wieldview/init.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mods/PLAYER/wieldview/init.lua b/mods/PLAYER/wieldview/init.lua index 6021dd369..7a349f2f3 100644 --- a/mods/PLAYER/wieldview/init.lua +++ b/mods/PLAYER/wieldview/init.lua @@ -115,10 +115,11 @@ minetest.register_entity("wieldview:wieldnode", { local def = minetest.registered_items[itemstring] self.object:set_properties({glow = def and def.light_source or 0}) - -- wield item as cubic + -- wield item as cubic if armor.textures[self.wielder].wielditem == "blank.png" then self.object:set_properties({textures = {itemstring}}) - else -- wield item as flat + -- wield item as flat + else self.object:set_properties({textures = {""}}) end From 3c73ad3b9866543c7c42356a49aa15f9ce938f76 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Tue, 6 Apr 2021 16:06:44 +0200 Subject: [PATCH 13/32] Add ztianyang to credits --- mods/HUD/mcl_credits/init.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/HUD/mcl_credits/init.lua b/mods/HUD/mcl_credits/init.lua index 40bafa19e..1e8138ab4 100644 --- a/mods/HUD/mcl_credits/init.lua +++ b/mods/HUD/mcl_credits/init.lua @@ -54,6 +54,7 @@ mcl_credits.people = { "dBeans", "nickolas360", "yutyo", + "ztianyang", }}, {"MineClone5", 0xA60014, { "kay27", From ea08fee9ba572287f4aad42b0afa07a7ace7369b Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Tue, 6 Apr 2021 16:38:23 +0200 Subject: [PATCH 14/32] Make the dragon stay within a 50 blocks range of the portal --- mods/ENTITIES/mobs_mc/ender_dragon.lua | 18 +++++++++++++++--- mods/ITEMS/mcl_end/end_crystal.lua | 2 +- mods/MAPGEN/mcl_mapgen_core/init.lua | 2 +- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/ender_dragon.lua b/mods/ENTITIES/mobs_mc/ender_dragon.lua index 50aaacd4b..fbdaf2bc9 100644 --- a/mods/ENTITIES/mobs_mc/ender_dragon.lua +++ b/mods/ENTITIES/mobs_mc/ender_dragon.lua @@ -61,14 +61,26 @@ mobs:register_mob("mobs_mc:enderdragon", { ignores_nametag = true, do_custom = function(self) mcl_bossbars.update_boss(self, "Ender Dragon", "light_purple") + if self._portal_pos then + -- migrate old format + if type(self._portal_pos) == "string" then + self._portal_pos = minetest.string_to_pos(self._portal_pos) + end + local portal_center = vector.add(self._portal_pos, vector.new(3, 11, 3)) + local pos = self.object:get_pos() + if vector.distance(pos, portal_center) > 50 then + self.object:set_pos(self._last_good_pos or portal_center) + else + self._last_good_pos = pos + end + end end, on_die = function(self, pos) if self._portal_pos then - local portal_pos = minetest.string_to_pos(self._portal_pos) - mcl_structures.call_struct(portal_pos, "end_exit_portal_open") + mcl_structures.call_struct(self._portal_pos, "end_exit_portal_open") if self._initial then mcl_experience.throw_experience(pos, 11500) -- 500 + 11500 = 12000 - minetest.set_node(vector.add(portal_pos, vector.new(3, 5, 3)), {name = mobs_mc.items.dragon_egg}) + minetest.set_node(vector.add(self._portal_pos, vector.new(3, 5, 3)), {name = mobs_mc.items.dragon_egg}) end end end, diff --git a/mods/ITEMS/mcl_end/end_crystal.lua b/mods/ITEMS/mcl_end/end_crystal.lua index 63a37d3c6..772776a1c 100644 --- a/mods/ITEMS/mcl_end/end_crystal.lua +++ b/mods/ITEMS/mcl_end/end_crystal.lua @@ -60,7 +60,7 @@ local function spawn_crystal(pos) end local portal_pos = vector.add(portal_center, vector.new(-3, -1, -3)) mcl_structures.call_struct(portal_pos, "end_exit_portal") - minetest.add_entity(vector.add(portal_pos, vector.new(3, 11, 3)), "mobs_mc:enderdragon"):get_luaentity()._portal_pos = minetest.pos_to_string(portal_pos) + minetest.add_entity(vector.add(portal_pos, vector.new(3, 11, 3)), "mobs_mc:enderdragon"):get_luaentity()._portal_pos = portal_pos end minetest.register_entity("mcl_end:crystal", { diff --git a/mods/MAPGEN/mcl_mapgen_core/init.lua b/mods/MAPGEN/mcl_mapgen_core/init.lua index 237579dbe..e9d9368ad 100644 --- a/mods/MAPGEN/mcl_mapgen_core/init.lua +++ b/mods/MAPGEN/mcl_mapgen_core/init.lua @@ -1253,7 +1253,7 @@ end local function generate_end_exit_portal(pos) local dragon_entity = minetest.add_entity(vector.add(pos, vector.new(3, 11, 3)), "mobs_mc:enderdragon"):get_luaentity() dragon_entity._initial = true - dragon_entity._portal_pos = minetest.pos_to_string(pos) + dragon_entity._portal_pos = pos mcl_structures.call_struct(pos, "end_exit_portal") end From 8e2493dd9a3cb9f13ffbf1dd31356e95056d646a Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 6 Apr 2021 10:40:16 -0400 Subject: [PATCH 15/32] Remove 47 node object check from mobs --- mods/ENTITIES/mcl_mobs/api.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index e599f2127..d81d3766d 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -4632,6 +4632,7 @@ function mobs:alias_mob(old_name, new_name) end +--[[ local timer = 0 minetest.register_globalstep(function(dtime) timer = timer + dtime @@ -4648,3 +4649,4 @@ minetest.register_globalstep(function(dtime) end timer = 0 end) +]]-- \ No newline at end of file From f65c40f805a7d9311519755a22725c5f4bfb38c9 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Tue, 6 Apr 2021 17:20:11 +0200 Subject: [PATCH 16/32] Make dragon egg teleport on punching --- mods/ITEMS/mcl_end/building.lua | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_end/building.lua b/mods/ITEMS/mcl_end/building.lua index 3dcf0671e..94fd26434 100644 --- a/mods/ITEMS/mcl_end/building.lua +++ b/mods/ITEMS/mcl_end/building.lua @@ -169,7 +169,16 @@ minetest.register_node("mcl_end:dragon_egg", { sounds = mcl_sounds.node_sound_stone_defaults(), _mcl_blast_resistance = 9, _mcl_hardness = 3, - -- TODO: Make dragon egg teleport on punching + on_punch = function(pos, node) + local max_dist = vector.new(15, 7, 15) + local positions = minetest.find_nodes_in_area(vector.subtract(pos, max_dist), vector.add(pos, max_dist), "air", false) + if #positions > 0 then + local tpos = positions[math.random(#positions)] + minetest.remove_node(pos) + minetest.set_node(tpos, node) + minetest.check_for_falling(tpos) + end + end, }) From 430f958faee13f9b9750f37b9a5189fe10a4f309 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Tue, 6 Apr 2021 20:08:20 +0200 Subject: [PATCH 17/32] Move end exit portal to 0, 0; Add end gateway portals (WIP) --- mods/ENTITIES/mobs_mc/ender_dragon.lua | 1 + mods/ITEMS/mcl_portals/init.lua | 6 ++- mods/ITEMS/mcl_portals/portal_gateway.lua | 45 ++++++++++++++++++ mods/ITEMS/mcl_portals/portal_nether.lua | 4 +- mods/MAPGEN/mcl_end_island/init.lua | 8 ++-- mods/MAPGEN/mcl_mapgen_core/init.lua | 5 +- mods/MAPGEN/mcl_structures/init.lua | 9 ++++ .../mcl_structures_end_gateway_portal.mts | Bin 0 -> 109 bytes 8 files changed, 66 insertions(+), 12 deletions(-) create mode 100644 mods/ITEMS/mcl_portals/portal_gateway.lua create mode 100644 mods/MAPGEN/mcl_structures/schematics/mcl_structures_end_gateway_portal.mts diff --git a/mods/ENTITIES/mobs_mc/ender_dragon.lua b/mods/ENTITIES/mobs_mc/ender_dragon.lua index fbdaf2bc9..92806d878 100644 --- a/mods/ENTITIES/mobs_mc/ender_dragon.lua +++ b/mods/ENTITIES/mobs_mc/ender_dragon.lua @@ -77,6 +77,7 @@ mobs:register_mob("mobs_mc:enderdragon", { end, on_die = function(self, pos) if self._portal_pos then + mcl_portals.spawn_gateway_portal() mcl_structures.call_struct(self._portal_pos, "end_exit_portal_open") if self._initial then mcl_experience.throw_experience(pos, 11500) -- 500 + 11500 = 12000 diff --git a/mods/ITEMS/mcl_portals/init.lua b/mods/ITEMS/mcl_portals/init.lua index 2fd96afad..080051ffa 100644 --- a/mods/ITEMS/mcl_portals/init.lua +++ b/mods/ITEMS/mcl_portals/init.lua @@ -1,6 +1,8 @@ -- Load files -mcl_portals = {} +mcl_portals = { + storage = minetest.get_mod_storage(), +} -- Nether portal: -- Obsidian frame, activated by flint and steel @@ -10,3 +12,5 @@ dofile(minetest.get_modpath("mcl_portals").."/portal_nether.lua") -- Red nether brick block frame, activated by an eye of ender dofile(minetest.get_modpath("mcl_portals").."/portal_end.lua") +dofile(minetest.get_modpath("mcl_portals").."/portal_gateway.lua") + diff --git a/mods/ITEMS/mcl_portals/portal_gateway.lua b/mods/ITEMS/mcl_portals/portal_gateway.lua new file mode 100644 index 000000000..cae6fce43 --- /dev/null +++ b/mods/ITEMS/mcl_portals/portal_gateway.lua @@ -0,0 +1,45 @@ +local S = minetest.get_translator("mcl_portals") +local storage = mcl_portals.storage + +local gateway_positions = { + {x = 96, y = -26925, z = 0}, + {x = 91, y = -26925, z = 29}, + {x = 77, y = -26925, z = 56}, + {x = 56, y = -26925, z = 77}, + {x = 29, y = -26925, z = 91}, + {x = 0, y = -26925, z = 96}, + {x = -29, y = -26925, z = 91}, + {x = -56, y = -26925, z = 77}, + {x = -77, y = -26925, z = 56}, + {x = -91, y = -26925, z = 29}, + {x = -96, y = -26925, z = 0}, + {x = -91, y = -26925, z = -29}, + {x = -77, y = -26925, z = -56}, + {x = -56, y = -26925, z = -77}, + {x = -29, y = -26925, z = -91}, + {x = 0, y = -26925, z = -96}, + {x = 29, y = -26925, z = -91}, + {x = 56, y = -26925, z = -77}, + {x = 77, y = -26925, z = -56}, + {x = 91, y = -26925, z = -29}, +} + +function mcl_portals.spawn_gateway_portal() + local id = storage:get_int("gateway_last_id") + 1 + local pos = gateway_positions[id] + if not pos then return end + storage:set_int("gateway_last_id", id) + mcl_structures.call_struct(vector.add(pos, vector.new(-1, -2, -1)), "end_gateway_portal") +end + +local gateway_def = table.copy(minetest.registered_nodes["mcl_portals:portal_end"]) +gateway_def.description = S("End Gateway Portal") +gateway_def._tt_help = S("Used to construct end gateway portals") +gateway_def._doc_items_longdesc = S("An End gateway portal teleports creatures and objects to the outer End (and back!).") +gateway_def._doc_items_usagehelp = S("Throw an ender pearl into the portal to teleport. Entering an Gateway portal near the Overworld teleports you to the outer End. At this destination another gateway portal will be constructed, which you can use to get back.") +gateway_def.after_destruct = nil +gateway_def.drawtype = "normal" +gateway_def.node_box = nil +gateway_def.walkable = true +gateway_def.tiles[3] = nil +minetest.register_node("mcl_portals:portal_gateway", gateway_def) diff --git a/mods/ITEMS/mcl_portals/portal_nether.lua b/mods/ITEMS/mcl_portals/portal_nether.lua index 50a3bde39..9ac569dd7 100644 --- a/mods/ITEMS/mcl_portals/portal_nether.lua +++ b/mods/ITEMS/mcl_portals/portal_nether.lua @@ -47,7 +47,7 @@ local chatter = {} local queue = {} local chunks = {} -local storage = minetest.get_mod_storage() +local storage = mcl_portals.storage local exits = {} local keys = minetest.deserialize(storage:get_string("nether_exits_keys") or "return {}") or {} for _, key in pairs(keys) do @@ -193,7 +193,7 @@ end local function destroy_nether_portal(pos, node) if not node then return end local nn, orientation = node.name, node.param2 - local obsidian = nn == OBSIDIAN + local obsidian = nn == OBSIDIAN local check_remove = function(pos, orientation) local node = get_node(pos) diff --git a/mods/MAPGEN/mcl_end_island/init.lua b/mods/MAPGEN/mcl_end_island/init.lua index fb062bf77..730176257 100644 --- a/mods/MAPGEN/mcl_end_island/init.lua +++ b/mods/MAPGEN/mcl_end_island/init.lua @@ -8,12 +8,10 @@ local noisemap = PerlinNoiseMap({ }, {x = 151, y = 30, z = 151}):get_3d_map({x = 0, y = 0, z = 0}) local c_end_stone = minetest.get_content_id("mcl_end:end_stone") - -local x_offset = mcl_vars.mg_end_platform_pos.x - 27 local y_offset = -2 minetest.register_on_generated(function(minp, maxp) - if maxp.y < (-27025 + y_offset) or minp.y > (-27000 + y_offset + 4) or maxp.x < (-75 + x_offset) or minp.x > (75 + x_offset) or maxp.z < -75 or minp.z > 75 then + if maxp.y < (-27025 + y_offset) or minp.y > (-27000 + y_offset + 4) or maxp.x < -75 or minp.x > 75 or maxp.z < -75 or minp.z > 75 then return end @@ -21,10 +19,10 @@ minetest.register_on_generated(function(minp, maxp) local data = vm:get_data() local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax}) - for idx in area:iter(math.max(minp.x, -75 + x_offset), math.max(minp.y, -27025 + y_offset + 4), math.max(minp.z, -75), math.min(maxp.x, 75 + x_offset), math.min(maxp.y, -27000 + y_offset), math.min(maxp.z, 75)) do + for idx in area:iter(math.max(minp.x, -75), math.max(minp.y, -27025 + y_offset + 4), math.max(minp.z, -75), math.min(maxp.x, 75), math.min(maxp.y, -27000 + y_offset), math.min(maxp.z, 75)) do local pos = area:position(idx) local y = 27025 + pos.y - y_offset - if noisemap[pos.x + 75 - x_offset + 1][y + 1][pos.z + 75 + 1] > (math.abs(1 - y / 25) ^ 2 + math.abs((pos.x - x_offset) / 75) ^ 2 + math.abs(pos.z / 75) ^ 2) then + if noisemap[pos.x + 75 + 1][y + 1][pos.z + 75 + 1] > (math.abs(1 - y / 25) ^ 2 + math.abs(pos.x / 75) ^ 2 + math.abs(pos.z / 75) ^ 2) then data[idx] = c_end_stone end end diff --git a/mods/MAPGEN/mcl_mapgen_core/init.lua b/mods/MAPGEN/mcl_mapgen_core/init.lua index e9d9368ad..1ee861e4a 100644 --- a/mods/MAPGEN/mcl_mapgen_core/init.lua +++ b/mods/MAPGEN/mcl_mapgen_core/init.lua @@ -55,10 +55,7 @@ local superflat = mg_name == "flat" and minetest.get_mapgen_setting("mcl_superfl local WITCH_HUT_HEIGHT = 3 -- Exact Y level to spawn witch huts at. This height refers to the height of the floor -- End exit portal position -local END_EXIT_PORTAL_POS = table.copy(mcl_vars.mg_end_platform_pos) -END_EXIT_PORTAL_POS.x = END_EXIT_PORTAL_POS.x - 30 -END_EXIT_PORTAL_POS.z = END_EXIT_PORTAL_POS.z - 3 -END_EXIT_PORTAL_POS.y = END_EXIT_PORTAL_POS.y - 3 +local END_EXIT_PORTAL_POS = vector.new(-3, -27003, -3) -- Content IDs local c_bedrock = minetest.get_content_id("mcl_core:bedrock") diff --git a/mods/MAPGEN/mcl_structures/init.lua b/mods/MAPGEN/mcl_structures/init.lua index d75854352..00efeca14 100644 --- a/mods/MAPGEN/mcl_structures/init.lua +++ b/mods/MAPGEN/mcl_structures/init.lua @@ -89,6 +89,8 @@ mcl_structures.call_struct = function(pos, struct_style, rotation, pr) return mcl_structures.generate_end_exit_portal(pos, rotation) elseif struct_style == "end_exit_portal_open" then return mcl_structures.generate_end_exit_portal_open(pos, rotation) + elseif struct_style == "end_gateway_portal" then + return mcl_structures.generate_end_gateway_portal(pos, rotation) elseif struct_style == "end_portal_shrine" then return mcl_structures.generate_end_portal_shrine(pos, rotation, pr) end @@ -324,6 +326,11 @@ mcl_structures.generate_end_exit_portal_open = function(pos, rot) return mcl_structures.place_schematic(pos, path, rot or "0", nil, true) end +mcl_structures.generate_end_gateway_portal = function(pos, rot) + local path = minetest.get_modpath("mcl_structures").."/schematics/mcl_structures_end_gateway_portal.mts" + return mcl_structures.place_schematic(pos, path, rot or "0", nil, true) +end + local function shrine_placement_callback(p1, p2, size, rotation, pr) -- Find and setup spawner with silverfish local spawners = minetest.find_nodes_in_area(p1, p2, "mcl_mobspawners:spawner") @@ -575,6 +582,8 @@ minetest.register_chatcommand("spawnstruct", { mcl_structures.generate_end_exit_portal(pos, rot, pr) elseif param == "end_exit_portal_open" then mcl_structures.generate_end_exit_portal_open(pos, rot, pr) + elseif param == "end_gateway_portal" then + mcl_structures.generate_end_gateway_portal(pos, rot, pr) elseif param == "end_portal_shrine" then mcl_structures.generate_end_portal_shrine(pos, rot, pr) elseif param == "dungeon" and mcl_dungeons and mcl_dungeons.spawn_dungeon then diff --git a/mods/MAPGEN/mcl_structures/schematics/mcl_structures_end_gateway_portal.mts b/mods/MAPGEN/mcl_structures/schematics/mcl_structures_end_gateway_portal.mts new file mode 100644 index 0000000000000000000000000000000000000000..24b06a1c8feb879c7480ccaacebb07c0fa405ac6 GIT binary patch literal 109 zcmeYb3HD`RVPIxpWniuc0U(n(F|&w4AU8QDJ~_WA)ha19r6@l+n?VXBQjlL%l9*F$ z1)<~96H8Ld6Dup`Bqua5xv{Z0q#HLWGBXPcNzbpcSmCbt`t|FFD!X(v85s6$WNQKd D{xKuw literal 0 HcmV?d00001 From 069e089ae4c6446a0de3d9740664221a6a7ebb9d Mon Sep 17 00:00:00 2001 From: kay27 Date: Wed, 7 Apr 2021 03:34:15 +0400 Subject: [PATCH 18/32] [mcl_portals, mcl_structures] Add End gateways W-I-P by Elias Fleckenstein with minor portals improvements and fixes --- mods/ITEMS/mcl_portals/portal_gateway.lua | 78 ++++++++++++++++++++++- mods/ITEMS/mcl_portals/portal_nether.lua | 33 +++++++++- mods/MAPGEN/mcl_biomes/init.lua | 2 + mods/MAPGEN/mcl_structures/init.lua | 10 +-- 4 files changed, 115 insertions(+), 8 deletions(-) diff --git a/mods/ITEMS/mcl_portals/portal_gateway.lua b/mods/ITEMS/mcl_portals/portal_gateway.lua index cae6fce43..9fa35a36f 100644 --- a/mods/ITEMS/mcl_portals/portal_gateway.lua +++ b/mods/ITEMS/mcl_portals/portal_gateway.lua @@ -24,12 +24,21 @@ local gateway_positions = { {x = 91, y = -26925, z = -29}, } +local function spawn_gateway_portal(pos, dest_str) + local path = minetest.get_modpath("mcl_structures").."/schematics/mcl_structures_end_gateway_portal.mts" + return mcl_structures.place_schematic(vector.add(pos, vector.new(-1, -2, -1)), path, "0", nil, true, nil, dest_str and function(p1, p2, size, orientation, pr, param) + -- minetest.get_voxel_manip():read_from_map(pos, pos) + minetest.get_meta(vector.add(p1, {x=1,y=2,z=1})):set_string("mcl_portals:gateway_destination", param.dest_str) + print(param.dest_str) + end, nil, {dest_str=dest_str}) +end + function mcl_portals.spawn_gateway_portal() local id = storage:get_int("gateway_last_id") + 1 local pos = gateway_positions[id] if not pos then return end storage:set_int("gateway_last_id", id) - mcl_structures.call_struct(vector.add(pos, vector.new(-1, -2, -1)), "end_gateway_portal") + spawn_gateway_portal(pos) end local gateway_def = table.copy(minetest.registered_nodes["mcl_portals:portal_end"]) @@ -43,3 +52,70 @@ gateway_def.node_box = nil gateway_def.walkable = true gateway_def.tiles[3] = nil minetest.register_node("mcl_portals:portal_gateway", gateway_def) + +local function find_destination_pos(minp, maxp) + for y = maxp.y, minp.y, -1 do + for x = maxp.x, minp.x, -1 do + for z = maxp.z, minp.z, -1 do + local pos = vector.new(x, y, z) + local nn = minetest.get_node(pos).name + if nn ~= "ignore" and nn ~= "mcl_portals:portal_gateway" and nn ~= "mcl_core:bedrock" then + local def = minetest.registered_nodes[nn] + if def and def.walkable then + return vector.add(pos, vector.new(0, 1.5, 0)) + end + end + end + end + end +end + +local preparing = {} + +local function teleport(pos, obj) + local meta = minetest.get_meta(pos) + local dest_portal + local dest_str = meta:get_string("mcl_portals:gateway_destination") + local pos_str = minetest.pos_to_string(pos) + if dest_str == "" then + dest_portal = vector.multiply(vector.direction(vector.new(0, pos.y, 0), pos), math.random(768, 1024)) + dest_portal.y = -26970 + spawn_gateway_portal(dest_portal, pos_str) + meta:set_string("mcl_portals:gateway_destination", minetest.pos_to_string(dest_portal)) + else + dest_portal = minetest.string_to_pos(dest_str) + end + local minp = vector.subtract(dest_portal, vector.new(5, 40, 5)) + local maxp = vector.add(dest_portal, vector.new(5, 10, 5)) + preparing[pos_str] = true + minetest.emerge_area( + minp, + maxp, + function(blockpos, action, calls_remaining, param) + if calls_remaining < 1 then + local minp, maxp, dest_portal, obj, pos_str = param.minp, param.maxp, param.dest_portal, param.obj, param.pos_str + if obj and obj:is_player() or obj:get_luaentity() then + obj:set_pos(find_destination_pos(minp, maxp) or vector.add(dest_portal, vector.new(0, 3.5, 0))) + end + preparing[pos_str] = false + end + end, + {minp=vector.new(minp), maxp=vector.new(maxp), dest_portal=vector.new(dest_portal), obj=obj, pos_str=pos_str} + ) +end + +minetest.register_abm({ + label = "End gateway portal teleportation", + nodenames = {"mcl_portals:portal_gateway"}, + interval = 0.1, + chance = 1, + action = function(pos) + if preparing[minetest.pos_to_string(pos)] then return end + for _, obj in pairs(minetest.get_objects_inside_radius(pos, 1)) do + if obj:get_hp() > 0 then + teleport(pos, obj) + return + end + end + end, +}) diff --git a/mods/ITEMS/mcl_portals/portal_nether.lua b/mods/ITEMS/mcl_portals/portal_nether.lua index 9ac569dd7..825c95e05 100644 --- a/mods/ITEMS/mcl_portals/portal_nether.lua +++ b/mods/ITEMS/mcl_portals/portal_nether.lua @@ -1,5 +1,7 @@ local S = minetest.get_translator("mcl_portals") +local SCAN_2_MAP_CHUNKS = true -- slower but helps to find more suitable places + -- Localize functions for better performance local abs = math.abs local ceil = math.ceil @@ -26,7 +28,7 @@ local DISTANCE_MAX = 128 local PORTAL = "mcl_portals:portal" local OBSIDIAN = "mcl_core:obsidian" local O_Y_MIN, O_Y_MAX = max(mcl_vars.mg_overworld_min, -31), min(mcl_vars.mg_overworld_max_official, 2048) -local N_Y_MIN, N_Y_MAX = mcl_vars.mg_bedrock_nether_bottom_min, mcl_vars.mg_bedrock_nether_top_max +local N_Y_MIN, N_Y_MAX = mcl_vars.mg_bedrock_nether_bottom_min, mcl_vars.mg_bedrock_nether_top_max - H_MIN local O_DY, N_DY = O_Y_MAX - O_Y_MIN + 1, N_Y_MAX - N_Y_MIN + 1 -- Alpha and particles @@ -486,6 +488,14 @@ local function ecb_scan_area_2(blockpos, action, calls_remaining, param) create_portal_2(pos0, name, obj) return end + + if param.next_chunk_1 and param.next_chunk_2 and param.next_pos then + local pos1, pos2, pos = param.next_chunk_1, param.next_chunk_2, param.next_pos + log("action", "[mcl_portals] Making additional search in chunk below, because current one doesn't contain any air space for portal, target pos "..pos_to_string(pos)) + minetest.emerge_area(pos1, pos2, ecb_scan_area_2, {pos = pos, pos1 = pos1, pos2 = pos2, name=name, obj=obj}) + return + end + log("action", "[mcl_portals] found no space, reverting to target pos "..pos_to_string(pos).." - creating a portal") if pos.y < lava then pos.y = lava + 1 @@ -507,18 +517,35 @@ local function create_portal(pos, limit1, limit2, name, obj) -- we need to emerge the area here, but currently (mt5.4/mcl20.71) map generation is slow -- so we'll emerge single chunk only: 5x5x5 blocks, 80x80x80 nodes maximum + -- and maybe one more chunk from below if (SCAN_2_MAP_CHUNKS = true) local pos1 = add(mul(mcl_vars.pos_to_chunk(pos), mcl_vars.chunk_size_in_nodes), mcl_vars.central_chunk_offset_in_nodes) local pos2 = add(pos1, mcl_vars.chunk_size_in_nodes - 1) + if not SCAN_2_MAP_CHUNKS then + if limit1 and limit1.x and limit1.y and limit1.z then + pos1 = {x = max(min(limit1.x, pos.x), pos1.x), y = max(min(limit1.y, pos.y), pos1.y), z = max(min(limit1.z, pos.z), pos1.z)} + end + if limit2 and limit2.x and limit2.y and limit2.z then + pos2 = {x = min(max(limit2.x, pos.x), pos2.x), y = min(max(limit2.y, pos.y), pos2.y), z = min(max(limit2.z, pos.z), pos2.z)} + end + minetest.emerge_area(pos1, pos2, ecb_scan_area_2, {pos = vector.new(pos), pos1 = pos1, pos2 = pos2, name=name, obj=obj}) + return + end + + -- Basically the copy of code above, with minor additions to continue the search in single additional chunk below: + local next_chunk_1 = {x = pos1.x, y = pos1.y - mcl_vars.chunk_size_in_nodes, z = pos1.z} + local next_chunk_2 = add(next_chunk_1, mcl_vars.chunk_size_in_nodes - 1) + local next_pos = {x = pos.x, y=next_chunk_2.y, z = pos.z} if limit1 and limit1.x and limit1.y and limit1.z then pos1 = {x = max(min(limit1.x, pos.x), pos1.x), y = max(min(limit1.y, pos.y), pos1.y), z = max(min(limit1.z, pos.z), pos1.z)} + next_chunk_1 = {x = max(min(limit1.x, next_pos.x), next_chunk_1.x), y = max(min(limit1.y, next_pos.y), next_chunk_1.y), z = max(min(limit1.z, next_pos.z), next_chunk_1.z)} end if limit2 and limit2.x and limit2.y and limit2.z then pos2 = {x = min(max(limit2.x, pos.x), pos2.x), y = min(max(limit2.y, pos.y), pos2.y), z = min(max(limit2.z, pos.z), pos2.z)} + next_chunk_2 = {x = min(max(limit2.x, next_pos.x), next_chunk_2.x), y = min(max(limit2.y, next_pos.y), next_chunk_2.y), z = min(max(limit2.z, next_pos.z), next_chunk_2.z)} end - - minetest.emerge_area(pos1, pos2, ecb_scan_area_2, {pos = vector.new(pos), pos1 = pos1, pos2 = pos2, name=name, obj=obj}) + minetest.emerge_area(pos1, pos2, ecb_scan_area_2, {pos = vector.new(pos), pos1 = pos1, pos2 = pos2, name=name, obj=obj, next_chunk_1 = next_chunk_1, next_chunk_2 = next_chunk_2, next_pos = next_pos}) end local function available_for_nether_portal(p) diff --git a/mods/MAPGEN/mcl_biomes/init.lua b/mods/MAPGEN/mcl_biomes/init.lua index 66de6c13a..5f0510344 100644 --- a/mods/MAPGEN/mcl_biomes/init.lua +++ b/mods/MAPGEN/mcl_biomes/init.lua @@ -1484,6 +1484,7 @@ local function register_dimension_biomes() node_stone = "mcl_nether:netherrack", node_water = "air", node_river_water = "air", + node_cave_liquid = "air", y_min = mcl_vars.mg_nether_min, -- FIXME: For some reason the Nether stops generating early if this constant is not added. -- Figure out why. @@ -1501,6 +1502,7 @@ local function register_dimension_biomes() node_filler = "air", node_water = "air", node_river_water = "air", + node_cave_liquid = "air", -- FIXME: For some reason the End stops generating early if this constant is not added. -- Figure out why. y_min = mcl_vars.mg_end_min, diff --git a/mods/MAPGEN/mcl_structures/init.lua b/mods/MAPGEN/mcl_structures/init.lua index 00efeca14..2ce5d94b5 100644 --- a/mods/MAPGEN/mcl_structures/init.lua +++ b/mods/MAPGEN/mcl_structures/init.lua @@ -11,10 +11,10 @@ local function ecb_place(blockpos, action, calls_remaining, param) if calls_remaining >= 1 then return end minetest.place_schematic(param.pos, param.schematic, param.rotation, param.replacements, param.force_placement, param.flags) if param.after_placement_callback and param.p1 and param.p2 then - param.after_placement_callback(param.p1, param.p2, param.size, param.rotation, param.pr) + param.after_placement_callback(param.p1, param.p2, param.size, param.rotation, param.pr, param.callback_param) end end -mcl_structures.place_schematic = function(pos, schematic, rotation, replacements, force_placement, flags, after_placement_callback, pr) +mcl_structures.place_schematic = function(pos, schematic, rotation, replacements, force_placement, flags, after_placement_callback, pr, callback_param) local s = loadstring(minetest.serialize_schematic(schematic, "lua", {lua_use_comments = false, lua_num_indent_spaces = 0}) .. " return(schematic)")() if s and s.size then local x, z = s.size.x, s.size.z @@ -32,7 +32,7 @@ mcl_structures.place_schematic = function(pos, schematic, rotation, replacements local p1 = {x=pos.x , y=pos.y , z=pos.z } local p2 = {x=pos.x+x-1, y=pos.y+s.size.y-1, z=pos.z+z-1} minetest.log("verbose","[mcl_structures] size=" ..minetest.pos_to_string(s.size) .. ", rotation=" .. tostring(rotation) .. ", emerge from "..minetest.pos_to_string(p1) .. " to " .. minetest.pos_to_string(p2)) - local param = {pos=vector.new(pos), schematic=s, rotation=rotation, replacements=replacements, force_placement=force_placement, flags=flags, p1=p1, p2=p2, after_placement_callback = after_placement_callback, size=vector.new(s.size), pr=pr} + local param = {pos=vector.new(pos), schematic=s, rotation=rotation, replacements=replacements, force_placement=force_placement, flags=flags, p1=p1, p2=p2, after_placement_callback = after_placement_callback, size=vector.new(s.size), pr=pr, callback_param=callback_param} minetest.emerge_area(p1, p2, ecb_place, param) end end @@ -548,7 +548,7 @@ end -- Debug command minetest.register_chatcommand("spawnstruct", { - params = "desert_temple | desert_well | igloo | witch_hut | boulder | ice_spike_small | ice_spike_large | fossil | end_exit_portal | end_exit_portal_opens | end_portal_shrine | nether_portal | dungeon", + params = "desert_temple | desert_well | igloo | witch_hut | boulder | ice_spike_small | ice_spike_large | fossil | end_exit_portal | end_exit_portal_opens | end_portal_shrine | nether_portal | gateway_portal | dungeon", description = S("Generate a pre-defined structure near your position."), privs = {debug = true}, func = function(name, param) @@ -590,6 +590,8 @@ minetest.register_chatcommand("spawnstruct", { mcl_dungeons.spawn_dungeon(pos, rot, pr) elseif param == "nether_portal" and mcl_portals and mcl_portals.spawn_nether_portal then mcl_portals.spawn_nether_portal(pos, rot, pr, name) + elseif param == "gateway_portal" and mcl_portals.spawn_gateway_portal then + mcl_portals.spawn_gateway_portal(pos, rot, pr, name) elseif param == "" then message = S("Error: No structure type given. Please use “/spawnstruct ”.") errord = true From 00db03320bf6f8b59d29e3d0ce5bf5c787b319d8 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 6 Apr 2021 20:24:46 -0400 Subject: [PATCH 19/32] Fix insane enderman 64 node radius check for players --- mods/ENTITIES/mobs_mc/enderman.lua | 51 +++++++++++++----------------- 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/enderman.lua b/mods/ENTITIES/mobs_mc/enderman.lua index 22599dd9e..40d859f97 100644 --- a/mods/ENTITIES/mobs_mc/enderman.lua +++ b/mods/ENTITIES/mobs_mc/enderman.lua @@ -328,37 +328,30 @@ mobs:register_mob("mobs_mc:enderman", { --end end -- Check to see if people are near by enough to look at us. - local objs = minetest.get_objects_inside_radius(enderpos, 64) - local obj - for n = 1, #objs do - obj = objs[n] - if obj then - if minetest.is_player(obj) then - -- Check if they are looking at us. - local player_pos = obj:get_pos() - local look_dir_not_normalized = obj:get_look_dir() - local look_dir = vector.normalize(look_dir_not_normalized) - local look_pos = vector.new({x = look_dir.x+player_pos.x, y = look_dir.y+player_pos.y + 1.5, z = look_dir.z+player_pos.z}) -- Arbitrary value (1.5) is head level according to player info mod. - -- Cast up to 64 to see if player is looking at enderman. - for n = 1,64,.25 do - local node = minetest.get_node(look_pos) - if node.name ~= "air" then - break - end - if look_pos.x-1enderpos.x and look_pos.y-2.89enderpos.y and look_pos.z-1enderpos.z then - self.provoked = "staring" - self.attack = minetest.get_player_by_name(obj:get_player_name()) - break - else - if self.provoked == "staring" then - self.provoked = "broke_contact" - end - end - look_pos.x = look_pos.x + (.25 * look_dir.x) - look_pos.y = look_pos.y + (.25 * look_dir.y) - look_pos.z = look_pos.z + (.25 * look_dir.z) + for _,obj in pairs(minetest.get_connected_players()) do + -- Check if they are looking at us. + local player_pos = obj:get_pos() + local look_dir_not_normalized = obj:get_look_dir() + local look_dir = vector.normalize(look_dir_not_normalized) + local look_pos = vector.new({x = look_dir.x+player_pos.x, y = look_dir.y+player_pos.y + 1.5, z = look_dir.z+player_pos.z}) -- Arbitrary value (1.5) is head level according to player info mod. + -- Cast up to 64 to see if player is looking at enderman. + for n = 1,64,.25 do + local node = minetest.get_node(look_pos) + if node.name ~= "air" then + break + end + if look_pos.x-1enderpos.x and look_pos.y-2.89enderpos.y and look_pos.z-1enderpos.z then + self.provoked = "staring" + self.attack = minetest.get_player_by_name(obj:get_player_name()) + break + else + if self.provoked == "staring" then + self.provoked = "broke_contact" end end + look_pos.x = look_pos.x + (.25 * look_dir.x) + look_pos.y = look_pos.y + (.25 * look_dir.y) + look_pos.z = look_pos.z + (.25 * look_dir.z) end end -- TAKE AND PLACE STUFF BEHAVIOUR BELOW. From 9f7899c01ab7cb1d1b9e5b026e82c3a77a5656ab Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 6 Apr 2021 20:37:48 -0400 Subject: [PATCH 20/32] Enderman use vectors to check distance between player and self --- mods/ENTITIES/mobs_mc/enderman.lua | 41 ++++++++++++++++-------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/enderman.lua b/mods/ENTITIES/mobs_mc/enderman.lua index 40d859f97..5b228a9af 100644 --- a/mods/ENTITIES/mobs_mc/enderman.lua +++ b/mods/ENTITIES/mobs_mc/enderman.lua @@ -331,27 +331,30 @@ mobs:register_mob("mobs_mc:enderman", { for _,obj in pairs(minetest.get_connected_players()) do -- Check if they are looking at us. local player_pos = obj:get_pos() - local look_dir_not_normalized = obj:get_look_dir() - local look_dir = vector.normalize(look_dir_not_normalized) - local look_pos = vector.new({x = look_dir.x+player_pos.x, y = look_dir.y+player_pos.y + 1.5, z = look_dir.z+player_pos.z}) -- Arbitrary value (1.5) is head level according to player info mod. - -- Cast up to 64 to see if player is looking at enderman. - for n = 1,64,.25 do - local node = minetest.get_node(look_pos) - if node.name ~= "air" then - break - end - if look_pos.x-1enderpos.x and look_pos.y-2.89enderpos.y and look_pos.z-1enderpos.z then - self.provoked = "staring" - self.attack = minetest.get_player_by_name(obj:get_player_name()) - break - else - if self.provoked == "staring" then - self.provoked = "broke_contact" + if vector.distance(enderpos, player_pos) <= 64 then + + local look_dir_not_normalized = obj:get_look_dir() + local look_dir = vector.normalize(look_dir_not_normalized) + local look_pos = vector.new({x = look_dir.x+player_pos.x, y = look_dir.y+player_pos.y + 1.5, z = look_dir.z+player_pos.z}) -- Arbitrary value (1.5) is head level according to player info mod. + -- Cast up to 64 to see if player is looking at enderman. + for n = 1,64,.25 do + local node = minetest.get_node(look_pos) + if node.name ~= "air" then + break end + if look_pos.x-1enderpos.x and look_pos.y-2.89enderpos.y and look_pos.z-1enderpos.z then + self.provoked = "staring" + self.attack = minetest.get_player_by_name(obj:get_player_name()) + break + else + if self.provoked == "staring" then + self.provoked = "broke_contact" + end + end + look_pos.x = look_pos.x + (.25 * look_dir.x) + look_pos.y = look_pos.y + (.25 * look_dir.y) + look_pos.z = look_pos.z + (.25 * look_dir.z) end - look_pos.x = look_pos.x + (.25 * look_dir.x) - look_pos.y = look_pos.y + (.25 * look_dir.y) - look_pos.z = look_pos.z + (.25 * look_dir.z) end end -- TAKE AND PLACE STUFF BEHAVIOUR BELOW. From 56f94af6ce95f69ab5e96cd5a498ff7425c83f5a Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 6 Apr 2021 21:13:20 -0400 Subject: [PATCH 21/32] Massively overhaul enderman sight calculations --- mods/ENTITIES/mobs_mc/enderman.lua | 45 +++++++++++++++++++----------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/enderman.lua b/mods/ENTITIES/mobs_mc/enderman.lua index 5b228a9af..e3f2c8e48 100644 --- a/mods/ENTITIES/mobs_mc/enderman.lua +++ b/mods/ENTITIES/mobs_mc/enderman.lua @@ -329,31 +329,44 @@ mobs:register_mob("mobs_mc:enderman", { end -- Check to see if people are near by enough to look at us. for _,obj in pairs(minetest.get_connected_players()) do - -- Check if they are looking at us. + + --check if they are within radius local player_pos = obj:get_pos() - if vector.distance(enderpos, player_pos) <= 64 then + if player_pos then -- prevent crashing in 1 in a million scenario - local look_dir_not_normalized = obj:get_look_dir() - local look_dir = vector.normalize(look_dir_not_normalized) - local look_pos = vector.new({x = look_dir.x+player_pos.x, y = look_dir.y+player_pos.y + 1.5, z = look_dir.z+player_pos.z}) -- Arbitrary value (1.5) is head level according to player info mod. - -- Cast up to 64 to see if player is looking at enderman. - for n = 1,64,.25 do - local node = minetest.get_node(look_pos) - if node.name ~= "air" then - break + local ender_distance = vector.distance(enderpos, player_pos) + if ender_distance <= 64 then + + -- Check if they are looking at us. + local look_dir_not_normalized = obj:get_look_dir() + local look_dir = vector.normalize(look_dir_not_normalized) + local player_eye_height = obj:get_properties().eye_height + + --skip player if they have no data - log it + if not player_eye_height then + minetest.log("error", "Enderman at location: ".. dump(enderpos).." has indexed a null player!") + goto continue end - if look_pos.x-1enderpos.x and look_pos.y-2.89enderpos.y and look_pos.z-1enderpos.z then + + --calculate very quickly the exact location the player is looking + --within the distance between the two "heads" (player and enderman) + local look_pos = vector.new(player_pos.x, player_pos.y + player_eye_height, player_pos.z) + local ender_eye_pos = vector.new(enderpos.x, enderpos.y + 2.75, enderpos.z) + local eye_distance_from_player = vector.distance(ender_eye_pos, look_pos) + look_pos = vector.add(look_pos, vector.multiply(look_dir, eye_distance_from_player)) + + --if looking in general head position, turn hostile + if vector.distance(look_pos, ender_eye_pos) <= 0.4 then self.provoked = "staring" self.attack = minetest.get_player_by_name(obj:get_player_name()) break - else + else -- I'm not sure what this part does, but I don't want to break anything - jordan4ibanez if self.provoked == "staring" then self.provoked = "broke_contact" - end + end end - look_pos.x = look_pos.x + (.25 * look_dir.x) - look_pos.y = look_pos.y + (.25 * look_dir.y) - look_pos.z = look_pos.z + (.25 * look_dir.z) + + ::continue:: -- this is a sweep over statement, this can be used to continue even when errors occurred end end end From acd2b8e691c2fc5a19e288e4865fd8fd46487f58 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 6 Apr 2021 21:29:52 -0400 Subject: [PATCH 22/32] Add line of sight calculations to the enderman --- mods/ENTITIES/mobs_mc/enderman.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mods/ENTITIES/mobs_mc/enderman.lua b/mods/ENTITIES/mobs_mc/enderman.lua index e3f2c8e48..cd8986aad 100644 --- a/mods/ENTITIES/mobs_mc/enderman.lua +++ b/mods/ENTITIES/mobs_mc/enderman.lua @@ -351,12 +351,13 @@ mobs:register_mob("mobs_mc:enderman", { --calculate very quickly the exact location the player is looking --within the distance between the two "heads" (player and enderman) local look_pos = vector.new(player_pos.x, player_pos.y + player_eye_height, player_pos.z) + local look_pos_base = look_pos local ender_eye_pos = vector.new(enderpos.x, enderpos.y + 2.75, enderpos.z) local eye_distance_from_player = vector.distance(ender_eye_pos, look_pos) look_pos = vector.add(look_pos, vector.multiply(look_dir, eye_distance_from_player)) --if looking in general head position, turn hostile - if vector.distance(look_pos, ender_eye_pos) <= 0.4 then + if minetest.line_of_sight(ender_eye_pos, look_pos_base) and vector.distance(look_pos, ender_eye_pos) <= 0.4 then self.provoked = "staring" self.attack = minetest.get_player_by_name(obj:get_player_name()) break From 4a1faa44de4c107f9ed7e016e6d53789234249e9 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 6 Apr 2021 21:59:51 -0400 Subject: [PATCH 23/32] Make unmounting a mob less of a jolt --- mods/ENTITIES/mcl_mobs/mount.lua | 8 ++++++-- mods/ENTITIES/mobs_mc/horse.lua | 1 - 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/mount.lua b/mods/ENTITIES/mcl_mobs/mount.lua index d8ce484c3..3d093a123 100644 --- a/mods/ENTITIES/mcl_mobs/mount.lua +++ b/mods/ENTITIES/mcl_mobs/mount.lua @@ -168,16 +168,20 @@ function mobs.detach(player, offset) mcl_player.player_set_animation(player, "stand" , 30) - local pos = player:get_pos() + --local pos = player:get_pos() - pos = {x = pos.x + offset.x, y = pos.y + 0.2 + offset.y, z = pos.z + offset.z} + --pos = {x = pos.x + offset.x, y = pos.y + 0.2 + offset.y, z = pos.z + offset.z} + player:add_velocity(vector.new(math.random(-5,5),math.random(3,6),math.random(-5,5))) --throw the rider off + + --[[ minetest.after(0.1, function(name, pos) local player = minetest.get_player_by_name(name) if player then player:set_pos(pos) end end, player:get_player_name(), pos) + ]]-- end diff --git a/mods/ENTITIES/mobs_mc/horse.lua b/mods/ENTITIES/mobs_mc/horse.lua index 1c2df41f3..3da63831e 100644 --- a/mods/ENTITIES/mobs_mc/horse.lua +++ b/mods/ENTITIES/mobs_mc/horse.lua @@ -231,7 +231,6 @@ local horse = { temper_increase = 5 elseif (iname == mobs_mc.items.golden_apple) then temper_increase = 10 - -- Trying to ride elseif not self.driver then self.object:set_properties({stepheight = 1.1}) From 6aaf25bbc949c2aa5aefbfc70a6593073d0e48c4 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 6 Apr 2021 22:02:52 -0400 Subject: [PATCH 24/32] Increase unmounting force --- mods/ENTITIES/mcl_mobs/mount.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ENTITIES/mcl_mobs/mount.lua b/mods/ENTITIES/mcl_mobs/mount.lua index 3d093a123..9383ee067 100644 --- a/mods/ENTITIES/mcl_mobs/mount.lua +++ b/mods/ENTITIES/mcl_mobs/mount.lua @@ -172,7 +172,7 @@ function mobs.detach(player, offset) --pos = {x = pos.x + offset.x, y = pos.y + 0.2 + offset.y, z = pos.z + offset.z} - player:add_velocity(vector.new(math.random(-5,5),math.random(3,6),math.random(-5,5))) --throw the rider off + player:add_velocity(vector.new(math.random(-6,6),math.random(5,8),math.random(-6,6))) --throw the rider off --[[ minetest.after(0.1, function(name, pos) From 7cecc71b91db42fbe11506c1a2720237a191816e Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 6 Apr 2021 22:08:10 -0400 Subject: [PATCH 25/32] Make mobs not collide with objects to stop weird glitches --- mods/ENTITIES/mcl_mobs/api.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index d81d3766d..94d6340ea 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -3418,6 +3418,7 @@ local mob_activate = function(self, staticdata, def, dtime) self.timer = 0 self.blinktimer = 0 self.blinkstatus = false + self.collide_with_objects = false -- check existing nametag if not self.nametag then From 6c4c22e3b9bd75c864a676adb8892b2af38b0478 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 6 Apr 2021 22:22:05 -0400 Subject: [PATCH 26/32] Adjust enderman projectile behavior, add snowballs to avoidance --- mods/ENTITIES/mobs_mc/enderman.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/enderman.lua b/mods/ENTITIES/mobs_mc/enderman.lua index cd8986aad..f93f131cb 100644 --- a/mods/ENTITIES/mobs_mc/enderman.lua +++ b/mods/ENTITIES/mobs_mc/enderman.lua @@ -295,7 +295,8 @@ mobs:register_mob("mobs_mc:enderman", { -- ARROW / DAYTIME PEOPLE AVOIDANCE BEHAVIOUR HERE. -- Check for arrows and people nearby. local enderpos = self.object:get_pos() - local objs = minetest.get_objects_inside_radius(enderpos, 4) + enderpos.y = enderpos.y + 1.5 + local objs = minetest.get_objects_inside_radius(enderpos, 2) for n = 1, #objs do local obj = objs[n] if obj then @@ -307,7 +308,7 @@ mobs:register_mob("mobs_mc:enderman", { else local lua = obj:get_luaentity() if lua then - if lua.name == "mcl_bows:arrow_entity" then + if lua.name == "mcl_bows:arrow_entity" or lua.name == "mcl_throwing:snowball_entity" then self:teleport(nil) end end From 6cdf7c98c2cc53e3a530fe99fbc8451742a54a3c Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Wed, 7 Apr 2021 00:55:57 -0400 Subject: [PATCH 27/32] Rework all mobs spawning - preprototype stage --- mods/ENTITIES/mcl_mobs/api.lua | 109 ++++++++++++++++++++- mods/ENTITIES/mobs_mc/agent.lua | 2 +- mods/ENTITIES/mobs_mc/bat.lua | 2 +- mods/ENTITIES/mobs_mc/blaze.lua | 4 +- mods/ENTITIES/mobs_mc/chicken.lua | 2 +- mods/ENTITIES/mobs_mc/cow+mooshroom.lua | 5 +- mods/ENTITIES/mobs_mc/creeper.lua | 7 +- mods/ENTITIES/mobs_mc/enderman.lua | 6 +- mods/ENTITIES/mobs_mc/ghast.lua | 2 +- mods/ENTITIES/mobs_mc/guardian_elder.lua | 2 +- mods/ENTITIES/mobs_mc/horse.lua | 4 +- mods/ENTITIES/mobs_mc/llama.lua | 2 +- mods/ENTITIES/mobs_mc/ocelot.lua | 8 +- mods/ENTITIES/mobs_mc/parrot.lua | 4 +- mods/ENTITIES/mobs_mc/pig.lua | 2 +- mods/ENTITIES/mobs_mc/polar_bear.lua | 2 +- mods/ENTITIES/mobs_mc/rabbit.lua | 6 +- mods/ENTITIES/mobs_mc/sheep.lua | 2 +- mods/ENTITIES/mobs_mc/shulker.lua | 2 +- mods/ENTITIES/mobs_mc/skeleton+stray.lua | 6 +- mods/ENTITIES/mobs_mc/skeleton_wither.lua | 2 +- mods/ENTITIES/mobs_mc/slime+magma_cube.lua | 18 ++-- mods/ENTITIES/mobs_mc/spider.lua | 2 +- mods/ENTITIES/mobs_mc/squid.lua | 2 +- mods/ENTITIES/mobs_mc/villager.lua | 2 +- mods/ENTITIES/mobs_mc/villager_zombie.lua | 4 +- mods/ENTITIES/mobs_mc/witch.lua | 2 +- mods/ENTITIES/mobs_mc/wolf.lua | 2 +- mods/ENTITIES/mobs_mc/zombie.lua | 8 +- mods/ENTITIES/mobs_mc/zombiepig.lua | 6 +- 30 files changed, 171 insertions(+), 56 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 94d6340ea..49c8edeaf 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -3562,7 +3562,7 @@ local mob_step = function(self, dtime) end -- mob plays random sound at times - if random(1, 100) == 1 then + if random(1, 70) == 1 then mob_sound(self, "random", true) end @@ -3925,7 +3925,35 @@ end end -- END mobs:register_mob function + + + + + + + + + + + +--BEGIN SPAWNING ALGORITHM + + + + + + + + + + + + + + + -- count how many mobs of one type are inside an area +--[[ local count_mobs = function(pos, mobtype) local num = 0 @@ -3969,7 +3997,7 @@ local count_mobs = function(pos, mobtype) return num end - +]]-- -- global functions @@ -3979,8 +4007,45 @@ function mobs:spawn_abm_check(pos, node, name) end -function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, - interval, chance, aoc, min_height, max_height, day_toggle, on_spawn) +--[[ + Custom elements changed: +name: +the mobs name + +dimension: +"overworld" +"nether" +"end" + +types of spawning: +"air" +"water" +"ground" +"lava" + +what is aoc??? + +WARNING: BIOME INTEGRATION NEEDED -> How to get biome through lua?? + ]]-- + +function mobs:spawn_specific( + name, + dimension, + type_of_spawning, + min_light, + max_light, + interval, + chance, + aoc, + min_height, + max_height, + day_toggle, + on_spawn) + + + + + print(name, dump(nodes)) -- Do mobs spawn at all? if not mobs_spawn then @@ -4207,6 +4272,42 @@ function mobs:spawn(def) chance, active_object_count, min_height, max_height, day_toggle, on_spawn) end + + + + + + + + + + + + + + + +--END SPAWNING ALGORITHM + + + + + + + + + + + + + + + + + + + + -- register arrow for shoot attack function mobs:register_arrow(name, def) diff --git a/mods/ENTITIES/mobs_mc/agent.lua b/mods/ENTITIES/mobs_mc/agent.lua index 8fa7314cf..cc9910ee6 100644 --- a/mods/ENTITIES/mobs_mc/agent.lua +++ b/mods/ENTITIES/mobs_mc/agent.lua @@ -1,5 +1,5 @@ --################### ---################### AGENT +--################### AGENT - seemingly unused --################### local S = minetest.get_translator("mobs_mc") diff --git a/mods/ENTITIES/mobs_mc/bat.lua b/mods/ENTITIES/mobs_mc/bat.lua index 103579b67..b6825bbbf 100644 --- a/mods/ENTITIES/mobs_mc/bat.lua +++ b/mods/ENTITIES/mobs_mc/bat.lua @@ -64,7 +64,7 @@ else end -- Spawn on solid blocks at or below Sea level and the selected light level -mobs:spawn_specific("mobs_mc:bat", mobs_mc.spawn.solid, {"air"}, 0, maxlight, 20, 5000, 2, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.water-1) +mobs:spawn_specific("mobs_mc:bat", "overworld", "air", 0, maxlight, 20, 5000, 2, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.water-1) -- spawn eggs diff --git a/mods/ENTITIES/mobs_mc/blaze.lua b/mods/ENTITIES/mobs_mc/blaze.lua index fbffa7920..d56acdf38 100644 --- a/mods/ENTITIES/mobs_mc/blaze.lua +++ b/mods/ENTITIES/mobs_mc/blaze.lua @@ -1,6 +1,6 @@ -- daufinsyd -- My work is under the LGPL terms --- Model and mobs_blaze.png see https://github.com/22i/minecraft-voxel-blender-models +-- Model and mobs_blaze.png see https://github.com/22i/minecraft-voxel-blender-models -hi 22i ~jordan4ibanez -- blaze.lua partial copy of mobs_mc/ghast.lua local S = minetest.get_translator("mobs_mc") @@ -128,7 +128,7 @@ mobs:register_mob("mobs_mc:blaze", { end, }) -mobs:spawn_specific("mobs_mc:blaze", mobs_mc.spawn.nether_fortress, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 5000, 3, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max) +mobs:spawn_specific("mobs_mc:blaze", "nether", "ground", 0, minetest.LIGHT_MAX+1, 30, 5000, 3, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max) -- Blaze fireball mobs:register_arrow("mobs_mc:blaze_fireball", { diff --git a/mods/ENTITIES/mobs_mc/chicken.lua b/mods/ENTITIES/mobs_mc/chicken.lua index 325371e2b..397b6b8da 100644 --- a/mods/ENTITIES/mobs_mc/chicken.lua +++ b/mods/ENTITIES/mobs_mc/chicken.lua @@ -100,7 +100,7 @@ mobs:register_mob("mobs_mc:chicken", { }) --spawn -mobs:spawn_specific("mobs_mc:chicken", mobs_mc.spawn.grassland, {"air"}, 9, minetest.LIGHT_MAX+1, 30, 17000, 3, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) +mobs:spawn_specific("mobs_mc:chicken", "overworld", "ground", 9, minetest.LIGHT_MAX+1, 30, 17000, 3, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) -- spawn eggs mobs:register_egg("mobs_mc:chicken", S("Chicken"), "mobs_mc_spawn_icon_chicken.png", 0) diff --git a/mods/ENTITIES/mobs_mc/cow+mooshroom.lua b/mods/ENTITIES/mobs_mc/cow+mooshroom.lua index 005af2980..a094d6d35 100644 --- a/mods/ENTITIES/mobs_mc/cow+mooshroom.lua +++ b/mods/ENTITIES/mobs_mc/cow+mooshroom.lua @@ -145,8 +145,9 @@ mobs:register_mob("mobs_mc:mooshroom", mooshroom_def) -- Spawning -mobs:spawn_specific("mobs_mc:cow", mobs_mc.spawn.grassland, {"air"}, 9, minetest.LIGHT_MAX+1, 30, 17000, 10, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) -mobs:spawn_specific("mobs_mc:mooshroom", mobs_mc.spawn.mushroom_island, {"air"}, 9, minetest.LIGHT_MAX+1, 30, 17000, 5, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) +mobs:spawn_specific("mobs_mc:cow", "overworld", "ground", 9, minetest.LIGHT_MAX+1, 30, 17000, 10, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) +--WARNING: THIS NEEDS A BIOME INTEGRATION +mobs:spawn_specific("mobs_mc:mooshroom", "overworld", "ground", 9, minetest.LIGHT_MAX+1, 30, 17000, 5, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) -- spawn egg mobs:register_egg("mobs_mc:cow", S("Cow"), "mobs_mc_spawn_icon_cow.png", 0) diff --git a/mods/ENTITIES/mobs_mc/creeper.lua b/mods/ENTITIES/mobs_mc/creeper.lua index 9ee9e9d24..f283fac18 100644 --- a/mods/ENTITIES/mobs_mc/creeper.lua +++ b/mods/ENTITIES/mobs_mc/creeper.lua @@ -39,6 +39,8 @@ mobs:register_mob("mobs_mc:creeper", { runaway_from = { "mobs_mc:ocelot", "mobs_mc:cat" }, attack_type = "explode", + --hssssssssssss + explosion_strength = 3, explosion_radius = 3.5, explosion_damage_radius = 3.5, @@ -139,6 +141,9 @@ mobs:register_mob("mobs_mc:creeper_charged", { pathfinding = 1, visual = "mesh", mesh = "mobs_mc_creeper.b3d", + + --BOOM + textures = { {"mobs_mc_creeper.png", "mobs_mc_creeper_charge.png"}, @@ -250,7 +255,7 @@ mobs:register_mob("mobs_mc:creeper_charged", { glow = 3, }) -mobs:spawn_specific("mobs_mc:creeper", mobs_mc.spawn.solid, {"air"}, 0, 7, 20, 16500, 2, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) +mobs:spawn_specific("mobs_mc:creeper", "overworld", "ground", 0, 7, 20, 16500, 2, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) -- spawn eggs mobs:register_egg("mobs_mc:creeper", S("Creeper"), "mobs_mc_spawn_icon_creeper.png", 0) diff --git a/mods/ENTITIES/mobs_mc/enderman.lua b/mods/ENTITIES/mobs_mc/enderman.lua index f93f131cb..ca3bc84ce 100644 --- a/mods/ENTITIES/mobs_mc/enderman.lua +++ b/mods/ENTITIES/mobs_mc/enderman.lua @@ -562,11 +562,11 @@ mobs:register_mob("mobs_mc:enderman", { -- End spawn -mobs:spawn_specific("mobs_mc:enderman", mobs_mc.spawn.solid, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 3000, 12, mobs_mc.spawn_height.end_min, mobs_mc.spawn_height.end_max) +mobs:spawn_specific("mobs_mc:enderman", "end", "ground", 0, minetest.LIGHT_MAX+1, 30, 3000, 12, mobs_mc.spawn_height.end_min, mobs_mc.spawn_height.end_max) -- Overworld spawn -mobs:spawn_specific("mobs_mc:enderman", mobs_mc.spawn.solid, {"air"}, 0, 7, 30, 19000, 2, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) +mobs:spawn_specific("mobs_mc:enderman", "overworld", "ground", 0, 7, 30, 19000, 2, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) -- Nether spawn (rare) -mobs:spawn_specific("mobs_mc:enderman", mobs_mc.spawn.solid, {"air"}, 0, 7, 30, 27500, 4, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max) +mobs:spawn_specific("mobs_mc:enderman", "nether", "ground", 0, 7, 30, 27500, 4, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max) -- spawn eggs mobs:register_egg("mobs_mc:enderman", S("Enderman"), "mobs_mc_spawn_icon_enderman.png", 0) diff --git a/mods/ENTITIES/mobs_mc/ghast.lua b/mods/ENTITIES/mobs_mc/ghast.lua index 7aed9395e..e2f6b1369 100644 --- a/mods/ENTITIES/mobs_mc/ghast.lua +++ b/mods/ENTITIES/mobs_mc/ghast.lua @@ -75,7 +75,7 @@ mobs:register_mob("mobs_mc:ghast", { }) -mobs:spawn_specific("mobs_mc:ghast", mobs_mc.spawn.nether, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 18000, 2, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max) +mobs:spawn_specific("mobs_mc:ghast", "nether", "air", 0, minetest.LIGHT_MAX+1, 30, 18000, 2, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max) -- fireball (projectile) mobs:register_arrow("mobs_mc:fireball", { diff --git a/mods/ENTITIES/mobs_mc/guardian_elder.lua b/mods/ENTITIES/mobs_mc/guardian_elder.lua index a58a4a5b7..089f6e38f 100644 --- a/mods/ENTITIES/mobs_mc/guardian_elder.lua +++ b/mods/ENTITIES/mobs_mc/guardian_elder.lua @@ -106,7 +106,7 @@ mobs:register_mob("mobs_mc:guardian_elder", { view_range = 16, }) --- Spawning disabled due to size issues +-- Spawning disabled due to size issues <- what do you mean? -j4i -- TODO: Re-enable spawning -- mobs:spawn_specific("mobs_mc:guardian_elder", mobs_mc.spawn.water, mobs_mc.spawn_water, 0, minetest.LIGHT_MAX+1, 30, 40000, 2, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.water-18) diff --git a/mods/ENTITIES/mobs_mc/horse.lua b/mods/ENTITIES/mobs_mc/horse.lua index 3da63831e..00c292c1d 100644 --- a/mods/ENTITIES/mobs_mc/horse.lua +++ b/mods/ENTITIES/mobs_mc/horse.lua @@ -510,8 +510,8 @@ mobs:register_mob("mobs_mc:mule", mule) --=========================== --Spawn Function -mobs:spawn_specific("mobs_mc:horse", mobs_mc.spawn.grassland_savanna, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 15000, 4, mobs_mc.spawn_height.water+3, mobs_mc.spawn_height.overworld_max) -mobs:spawn_specific("mobs_mc:donkey", mobs_mc.spawn.grassland_savanna, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 15000, 4, mobs_mc.spawn_height.water+3, mobs_mc.spawn_height.overworld_max) +mobs:spawn_specific("mobs_mc:horse", "overworld", "ground", 0, minetest.LIGHT_MAX+1, 30, 15000, 4, mobs_mc.spawn_height.water+3, mobs_mc.spawn_height.overworld_max) +mobs:spawn_specific("mobs_mc:donkey", "overworld", "ground", 0, minetest.LIGHT_MAX+1, 30, 15000, 4, mobs_mc.spawn_height.water+3, mobs_mc.spawn_height.overworld_max) -- spawn eggs mobs:register_egg("mobs_mc:horse", S("Horse"), "mobs_mc_spawn_icon_horse.png", 0) diff --git a/mods/ENTITIES/mobs_mc/llama.lua b/mods/ENTITIES/mobs_mc/llama.lua index 36d020a65..0efb8e0ab 100644 --- a/mods/ENTITIES/mobs_mc/llama.lua +++ b/mods/ENTITIES/mobs_mc/llama.lua @@ -217,7 +217,7 @@ mobs:register_mob("mobs_mc:llama", { }) --spawn -mobs:spawn_specific("mobs_mc:llama", mobs_mc.spawn.savanna, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 15000, 5, mobs_mc.spawn_height.water+15, mobs_mc.spawn_height.overworld_max) +mobs:spawn_specific("mobs_mc:llama", "overworld", "ground", 0, minetest.LIGHT_MAX+1, 30, 15000, 5, mobs_mc.spawn_height.water+15, mobs_mc.spawn_height.overworld_max) -- spawn eggs mobs:register_egg("mobs_mc:llama", S("Llama"), "mobs_mc_spawn_icon_llama.png", 0) diff --git a/mods/ENTITIES/mobs_mc/ocelot.lua b/mods/ENTITIES/mobs_mc/ocelot.lua index eca74d3ba..3b5273185 100644 --- a/mods/ENTITIES/mobs_mc/ocelot.lua +++ b/mods/ENTITIES/mobs_mc/ocelot.lua @@ -152,6 +152,9 @@ mobs:register_mob("mobs_mc:cat", cat) local base_spawn_chance = 5000 -- Spawn ocelot +--they get the same as the llama because I'm trying to rework so much of this code right now -j4i +mobs:spawn_specific("mobs_mc:ocelot", "overworld", "ground", 0, minetest.LIGHT_MAX+1, 30, 15000, 5, mobs_mc.spawn_height.water+15, mobs_mc.spawn_height.overworld_max) +--[[ mobs:spawn({ name = "mobs_mc:ocelot", nodes = mobs_mc.spawn.jungle, @@ -163,8 +166,8 @@ mobs:spawn({ min_height = mobs_mc.spawn_height.water+1, -- Right above ocean level max_height = mobs_mc.spawn_height.overworld_max, on_spawn = function(self, pos) - --[[ Note: Minecraft has a 1/3 spawn failure rate. - In this mod it is emulated by reducing the spawn rate accordingly (see above). ]] + Note: Minecraft has a 1/3 spawn failure rate. + In this mod it is emulated by reducing the spawn rate accordingly (see above). -- 1/7 chance to spawn 2 ocelot kittens if pr:next(1,7) == 1 then @@ -207,6 +210,7 @@ mobs:spawn({ end end, }) +]]-- -- spawn eggs -- FIXME: The spawn icon shows a cat texture, not an ocelot texture diff --git a/mods/ENTITIES/mobs_mc/parrot.lua b/mods/ENTITIES/mobs_mc/parrot.lua index 407cb4466..c67263fb9 100644 --- a/mods/ENTITIES/mobs_mc/parrot.lua +++ b/mods/ENTITIES/mobs_mc/parrot.lua @@ -90,8 +90,8 @@ mobs:register_mob("mobs_mc:parrot", { }) --- Parrots spawn rarely in jungles. TODO: Also check for jungle *biome* -mobs:spawn_specific("mobs_mc:parrot", {"mcl_core:jungletree", "mcl_core:jungleleaves"}, {"air"}, 0, minetest.LIGHT_MAX+1, 7, 30000, 1, mobs_mc.spawn_height.water+7, mobs_mc.spawn_height.overworld_max) +-- Parrots spawn rarely in jungles. TODO: Also check for jungle *biome* <- I'll get to this eventually -j4i +mobs:spawn_specific("mobs_mc:parrot","overworld", "air", 0, minetest.LIGHT_MAX+1, 7, 30000, 1, mobs_mc.spawn_height.water+7, mobs_mc.spawn_height.overworld_max) -- spawn eggs mobs:register_egg("mobs_mc:parrot", S("Parrot"), "mobs_mc_spawn_icon_parrot.png", 0) diff --git a/mods/ENTITIES/mobs_mc/pig.lua b/mods/ENTITIES/mobs_mc/pig.lua index 38700b6ca..143fcb495 100644 --- a/mods/ENTITIES/mobs_mc/pig.lua +++ b/mods/ENTITIES/mobs_mc/pig.lua @@ -182,7 +182,7 @@ mobs:register_mob("mobs_mc:pig", { end, }) -mobs:spawn_specific("mobs_mc:pig", mobs_mc.spawn.grassland, {"air"}, 9, minetest.LIGHT_MAX+1, 30, 15000, 8, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) +mobs:spawn_specific("mobs_mc:pig", "overworld", "ground", 9, minetest.LIGHT_MAX+1, 30, 15000, 8, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) -- spawn eggs mobs:register_egg("mobs_mc:pig", S("Pig"), "mobs_mc_spawn_icon_pig.png", 0) diff --git a/mods/ENTITIES/mobs_mc/polar_bear.lua b/mods/ENTITIES/mobs_mc/polar_bear.lua index 459ca29b4..745c13a26 100644 --- a/mods/ENTITIES/mobs_mc/polar_bear.lua +++ b/mods/ENTITIES/mobs_mc/polar_bear.lua @@ -67,7 +67,7 @@ mobs:register_mob("mobs_mc:polar_bear", { }) -mobs:spawn_specific("mobs_mc:polar_bear", mobs_mc.spawn.snow, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 7000, 3, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) +mobs:spawn_specific("mobs_mc:polar_bear", "overworld", "ground", 0, minetest.LIGHT_MAX+1, 30, 7000, 3, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) -- spawn egg mobs:register_egg("mobs_mc:polar_bear", S("Polar Bear"), "mobs_mc_spawn_icon_polarbear.png", 0) diff --git a/mods/ENTITIES/mobs_mc/rabbit.lua b/mods/ENTITIES/mobs_mc/rabbit.lua index e167649f6..f09a70584 100644 --- a/mods/ENTITIES/mobs_mc/rabbit.lua +++ b/mods/ENTITIES/mobs_mc/rabbit.lua @@ -107,8 +107,11 @@ end mobs:register_mob("mobs_mc:killer_bunny", killer_bunny) -- Mob spawning rules. --- Different skins depending on spawn location +-- Different skins depending on spawn location <- we'll get to this when the spawning algorithm is fleshed out +mobs:spawn_specific("mobs_mc:rabbit", "overworld", "ground", 9, minetest.LIGHT_MAX+1, 30, 15000, 8, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) + +--[[ local spawn = { name = "mobs_mc:rabbit", neighbors = {"air"}, @@ -165,6 +168,7 @@ spawn_grass.on_spawn = function(self, pos) self.object:set_properties({textures = self.base_texture}) end mobs:spawn(spawn_grass) +]]-- -- Spawn egg mobs:register_egg("mobs_mc:rabbit", S("Rabbit"), "mobs_mc_spawn_icon_rabbit.png", 0) diff --git a/mods/ENTITIES/mobs_mc/sheep.lua b/mods/ENTITIES/mobs_mc/sheep.lua index 84650b4dd..b3400ab5f 100644 --- a/mods/ENTITIES/mobs_mc/sheep.lua +++ b/mods/ENTITIES/mobs_mc/sheep.lua @@ -303,7 +303,7 @@ mobs:register_mob("mobs_mc:sheep", { end end, }) -mobs:spawn_specific("mobs_mc:sheep", mobs_mc.spawn.grassland, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 15000, 3, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) +mobs:spawn_specific("mobs_mc:sheep", "overworld", "ground", 0, minetest.LIGHT_MAX+1, 30, 15000, 3, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) -- spawn eggs mobs:register_egg("mobs_mc:sheep", S("Sheep"), "mobs_mc_spawn_icon_sheep.png", 0) diff --git a/mods/ENTITIES/mobs_mc/shulker.lua b/mods/ENTITIES/mobs_mc/shulker.lua index faaf2ac40..583c5eed1 100644 --- a/mods/ENTITIES/mobs_mc/shulker.lua +++ b/mods/ENTITIES/mobs_mc/shulker.lua @@ -81,4 +81,4 @@ mobs:register_arrow("mobs_mc:shulkerbullet", { mobs:register_egg("mobs_mc:shulker", S("Shulker"), "mobs_mc_spawn_icon_shulker.png", 0) -mobs:spawn_specific("mobs_mc:shulker", mobs_mc.spawn.end_city, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 5000, 2, mobs_mc.spawn_height.end_min, mobs_mc.spawn_height.end_max) +mobs:spawn_specific("mobs_mc:shulker", "end", "ground", 0, minetest.LIGHT_MAX+1, 30, 5000, 2, mobs_mc.spawn_height.end_min, mobs_mc.spawn_height.end_max) diff --git a/mods/ENTITIES/mobs_mc/skeleton+stray.lua b/mods/ENTITIES/mobs_mc/skeleton+stray.lua index cb12e905d..84e51c517 100644 --- a/mods/ENTITIES/mobs_mc/skeleton+stray.lua +++ b/mods/ENTITIES/mobs_mc/skeleton+stray.lua @@ -139,13 +139,13 @@ table.insert(stray.drops, { mobs:register_mob("mobs_mc:stray", stray) -- Overworld spawn -mobs:spawn_specific("mobs_mc:skeleton", mobs_mc.spawn.solid, {"air"}, 0, 7, 20, 17000, 2, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) +mobs:spawn_specific("mobs_mc:skeleton", "overworld", "ground", 0, 7, 20, 17000, 2, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) -- Nether spawn -mobs:spawn_specific("mobs_mc:skeleton", mobs_mc.spawn.nether_fortress, {"air"}, 0, 7, 30, 10000, 3, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max) +mobs:spawn_specific("mobs_mc:skeleton", "nether", "ground", 0, 7, 30, 10000, 3, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max) -- Stray spawn -- TODO: Spawn directly under the sky -mobs:spawn_specific("mobs_mc:stray", mobs_mc.spawn.snow, {"air"}, 0, 7, 20, 19000, 2, mobs_mc.spawn_height.water, mobs_mc.spawn_height.overworld_max) +mobs:spawn_specific("mobs_mc:stray", "overworld", "ground", 0, 7, 20, 19000, 2, mobs_mc.spawn_height.water, mobs_mc.spawn_height.overworld_max) -- spawn eggs diff --git a/mods/ENTITIES/mobs_mc/skeleton_wither.lua b/mods/ENTITIES/mobs_mc/skeleton_wither.lua index e4a1f86fc..d9de90d84 100644 --- a/mods/ENTITIES/mobs_mc/skeleton_wither.lua +++ b/mods/ENTITIES/mobs_mc/skeleton_wither.lua @@ -94,7 +94,7 @@ mobs:register_mob("mobs_mc:witherskeleton", { }) --spawn -mobs:spawn_specific("mobs_mc:witherskeleton", mobs_mc.spawn.nether_fortress, {"air"}, 0, 7, 30, 5000, 5, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max) +mobs:spawn_specific("mobs_mc:witherskeleton", "nether", "ground", 0, 7, 30, 5000, 5, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max) -- spawn eggs mobs:register_egg("mobs_mc:witherskeleton", S("Wither Skeleton"), "mobs_mc_spawn_icon_witherskeleton.png", 0) diff --git a/mods/ENTITIES/mobs_mc/slime+magma_cube.lua b/mods/ENTITIES/mobs_mc/slime+magma_cube.lua index fd1f92bb4..2f9e8c8a9 100644 --- a/mods/ENTITIES/mobs_mc/slime+magma_cube.lua +++ b/mods/ENTITIES/mobs_mc/slime+magma_cube.lua @@ -157,9 +157,9 @@ mobs:register_mob("mobs_mc:slime_tiny", slime_tiny) local smin = mobs_mc.spawn_height.overworld_min local smax = mobs_mc.spawn_height.water - 23 -mobs:spawn_specific("mobs_mc:slime_tiny", mobs_mc.spawn.solid, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 12000, 4, smin, smax) -mobs:spawn_specific("mobs_mc:slime_small", mobs_mc.spawn.solid, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 8500, 4, smin, smax) -mobs:spawn_specific("mobs_mc:slime_big", mobs_mc.spawn.solid, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 10000, 4, smin, smax) +mobs:spawn_specific("mobs_mc:slime_tiny", "overworld", "ground", 0, minetest.LIGHT_MAX+1, 30, 12000, 4, smin, smax) +mobs:spawn_specific("mobs_mc:slime_small", "overworld", "ground", 0, minetest.LIGHT_MAX+1, 30, 8500, 4, smin, smax) +mobs:spawn_specific("mobs_mc:slime_big", "overworld", "ground", 0, minetest.LIGHT_MAX+1, 30, 10000, 4, smin, smax) -- Magma cube local magma_cube_big = { @@ -272,13 +272,13 @@ mobs:register_mob("mobs_mc:magma_cube_tiny", magma_cube_tiny) local mmin = mobs_mc.spawn_height.nether_min local mmax = mobs_mc.spawn_height.nether_max -mobs:spawn_specific("mobs_mc:magma_cube_tiny", mobs_mc.spawn.nether, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 15000, 4, mmin, mmax) -mobs:spawn_specific("mobs_mc:magma_cube_small", mobs_mc.spawn.nether, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 15500, 4, mmin, mmax) -mobs:spawn_specific("mobs_mc:magma_cube_big", mobs_mc.spawn.nether, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 16000, 4, mmin, mmax) +mobs:spawn_specific("mobs_mc:magma_cube_tiny", "nether", "ground", 0, minetest.LIGHT_MAX+1, 30, 15000, 4, mmin, mmax) +mobs:spawn_specific("mobs_mc:magma_cube_small", "nether", "ground", 0, minetest.LIGHT_MAX+1, 30, 15500, 4, mmin, mmax) +mobs:spawn_specific("mobs_mc:magma_cube_big", "nether", "ground", 0, minetest.LIGHT_MAX+1, 30, 16000, 4, mmin, mmax) -mobs:spawn_specific("mobs_mc:magma_cube_tiny", mobs_mc.spawn.nether_fortress, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 11000, 4, mmin, mmax) -mobs:spawn_specific("mobs_mc:magma_cube_small", mobs_mc.spawn.nether_fortress, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 11100, 4, mmin, mmax) -mobs:spawn_specific("mobs_mc:magma_cube_big", mobs_mc.spawn.nether_fortress, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 11200, 4, mmin, mmax) +--mobs:spawn_specific("mobs_mc:magma_cube_tiny", mobs_mc.spawn.nether_fortress, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 11000, 4, mmin, mmax) +--mobs:spawn_specific("mobs_mc:magma_cube_small", mobs_mc.spawn.nether_fortress, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 11100, 4, mmin, mmax) +--mobs:spawn_specific("mobs_mc:magma_cube_big", mobs_mc.spawn.nether_fortress, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 11200, 4, mmin, mmax) -- spawn eggs diff --git a/mods/ENTITIES/mobs_mc/spider.lua b/mods/ENTITIES/mobs_mc/spider.lua index 0bb03a9c7..1361e6a3a 100644 --- a/mods/ENTITIES/mobs_mc/spider.lua +++ b/mods/ENTITIES/mobs_mc/spider.lua @@ -87,7 +87,7 @@ cave_spider.sounds.base_pitch = 1.25 mobs:register_mob("mobs_mc:cave_spider", cave_spider) -mobs:spawn_specific("mobs_mc:spider", mobs_mc.spawn.solid, {"air"}, 0, 7, 30, 17000, 2, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) +mobs:spawn_specific("mobs_mc:spider", "overworld", "ground", 0, 7, 30, 17000, 2, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) -- spawn eggs mobs:register_egg("mobs_mc:spider", S("Spider"), "mobs_mc_spawn_icon_spider.png", 0) diff --git a/mods/ENTITIES/mobs_mc/squid.lua b/mods/ENTITIES/mobs_mc/squid.lua index 1877a2104..2dbb7c557 100644 --- a/mods/ENTITIES/mobs_mc/squid.lua +++ b/mods/ENTITIES/mobs_mc/squid.lua @@ -62,7 +62,7 @@ mobs:register_mob("mobs_mc:squid", { local water = mobs_mc.spawn_height.water --name, nodes, neighbours, minlight, maxlight, interval, chance, active_object_count, min_height, max_height -mobs:spawn_specific("mobs_mc:squid", mobs_mc.spawn.water, {mobs_mc.items.water_source}, 0, minetest.LIGHT_MAX+1, 30, 5500, 3, water-16, water) +mobs:spawn_specific("mobs_mc:squid", "overworld", "water", 0, minetest.LIGHT_MAX+1, 30, 5500, 3, water-16, water) -- spawn eggs mobs:register_egg("mobs_mc:squid", S("Squid"), "mobs_mc_spawn_icon_squid.png", 0) diff --git a/mods/ENTITIES/mobs_mc/villager.lua b/mods/ENTITIES/mobs_mc/villager.lua index 68644266f..0b53d8015 100644 --- a/mods/ENTITIES/mobs_mc/villager.lua +++ b/mods/ENTITIES/mobs_mc/villager.lua @@ -1074,7 +1074,7 @@ mobs:register_mob("mobs_mc:villager", { -mobs:spawn_specific("mobs_mc:villager", mobs_mc.spawn.village, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 20, 4, mobs_mc.spawn_height.water+1, mobs_mc.spawn_height.overworld_max) +mobs:spawn_specific("mobs_mc:villager", "overworld", "ground", 0, minetest.LIGHT_MAX+1, 30, 20, 4, mobs_mc.spawn_height.water+1, mobs_mc.spawn_height.overworld_max) -- spawn eggs mobs:register_egg("mobs_mc:villager", S("Villager"), "mobs_mc_spawn_icon_villager.png", 0) diff --git a/mods/ENTITIES/mobs_mc/villager_zombie.lua b/mods/ENTITIES/mobs_mc/villager_zombie.lua index 09539fa76..bcede2183 100644 --- a/mods/ENTITIES/mobs_mc/villager_zombie.lua +++ b/mods/ENTITIES/mobs_mc/villager_zombie.lua @@ -146,8 +146,8 @@ mobs:register_mob("mobs_mc:villager_zombie", { harmed_by_heal = true, }) -mobs:spawn_specific("mobs_mc:villager_zombie", mobs_mc.spawn.village, {"air"}, 0, 7, 30, 4090, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) -mobs:spawn_specific("mobs_mc:villager_zombie", mobs_mc.spawn.solid, {"air"}, 0, 7, 30, 60000, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) +mobs:spawn_specific("mobs_mc:villager_zombie", "overworld", "ground", 0, 7, 30, 4090, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) +mobs:spawn_specific("mobs_mc:villager_zombie", "overworld", "ground", 0, 7, 30, 60000, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) -- spawn eggs mobs:register_egg("mobs_mc:villager_zombie", S("Zombie Villager"), "mobs_mc_spawn_icon_zombie_villager.png", 0) diff --git a/mods/ENTITIES/mobs_mc/witch.lua b/mods/ENTITIES/mobs_mc/witch.lua index 383cbd36f..f9f9b8d1f 100644 --- a/mods/ENTITIES/mobs_mc/witch.lua +++ b/mods/ENTITIES/mobs_mc/witch.lua @@ -99,7 +99,7 @@ mobs:register_arrow("mobs_mc:potion_arrow", { end }) --- TODO: Spawn when witch works properly +-- TODO: Spawn when witch works properly <- eventually -j4i --mobs:spawn_specific("mobs_mc:witch", mobs_mc.spawn.jungle, {"air"}, 0, minetest.LIGHT_MAX-6, 12, 20000, 2, mobs_mc.spawn_height.water-6, mobs_mc.spawn_height.overworld_max) -- spawn eggs diff --git a/mods/ENTITIES/mobs_mc/wolf.lua b/mods/ENTITIES/mobs_mc/wolf.lua index fe3031895..953c2df72 100644 --- a/mods/ENTITIES/mobs_mc/wolf.lua +++ b/mods/ENTITIES/mobs_mc/wolf.lua @@ -232,6 +232,6 @@ end mobs:register_mob("mobs_mc:dog", dog) -- Spawn -mobs:spawn_specific("mobs_mc:wolf", mobs_mc.spawn.wolf, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 9000, 7, mobs_mc.spawn_height.water+3, mobs_mc.spawn_height.overworld_max) +mobs:spawn_specific("mobs_mc:wolf", "overworld", "ground", 0, minetest.LIGHT_MAX+1, 30, 9000, 7, mobs_mc.spawn_height.water+3, mobs_mc.spawn_height.overworld_max) mobs:register_egg("mobs_mc:wolf", S("Wolf"), "mobs_mc_spawn_icon_wolf.png", 0) diff --git a/mods/ENTITIES/mobs_mc/zombie.lua b/mods/ENTITIES/mobs_mc/zombie.lua index df9727d34..64f99d34d 100644 --- a/mods/ENTITIES/mobs_mc/zombie.lua +++ b/mods/ENTITIES/mobs_mc/zombie.lua @@ -135,11 +135,11 @@ mobs:register_mob("mobs_mc:baby_husk", baby_husk) -- Spawning -mobs:spawn_specific("mobs_mc:zombie", mobs_mc.spawn.solid, {"air"}, 0, 7, 30, 6000, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) +mobs:spawn_specific("mobs_mc:zombie", "overworld", "ground", 0, 7, 30, 6000, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) -- Baby zombie is 20 times less likely than regular zombies -mobs:spawn_specific("mobs_mc:baby_zombie", mobs_mc.spawn.solid, {"air"}, 0, 7, 30, 60000, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) -mobs:spawn_specific("mobs_mc:husk", mobs_mc.spawn.desert, {"air"}, 0, 7, 30, 6500, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) -mobs:spawn_specific("mobs_mc:baby_husk", mobs_mc.spawn.desert, {"air"}, 0, 7, 30, 65000, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) +mobs:spawn_specific("mobs_mc:baby_zombie", "overworld", "ground", 0, 7, 30, 60000, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) +mobs:spawn_specific("mobs_mc:husk", "overworld", "ground", 0, 7, 30, 6500, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) +mobs:spawn_specific("mobs_mc:baby_husk", "overworld", "ground", 0, 7, 30, 65000, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) -- Spawn eggs mobs:register_egg("mobs_mc:husk", S("Husk"), "mobs_mc_spawn_icon_husk.png", 0) diff --git a/mods/ENTITIES/mobs_mc/zombiepig.lua b/mods/ENTITIES/mobs_mc/zombiepig.lua index 8c29a4bff..e996425c8 100644 --- a/mods/ENTITIES/mobs_mc/zombiepig.lua +++ b/mods/ENTITIES/mobs_mc/zombiepig.lua @@ -111,12 +111,12 @@ baby_pigman.child = 1 mobs:register_mob("mobs_mc:baby_pigman", baby_pigman) -- Regular spawning in the Nether -mobs:spawn_specific("mobs_mc:pigman", mobs_mc.spawn.solid, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 6000, 3, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max) +mobs:spawn_specific("mobs_mc:pigman", "nether", "ground", 0, minetest.LIGHT_MAX+1, 30, 6000, 3, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max) -- Baby zombie is 20 times less likely than regular zombies -mobs:spawn_specific("mobs_mc:baby_pigman", mobs_mc.spawn.solid, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 100000, 4, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max) +mobs:spawn_specific("mobs_mc:baby_pigman", "nether", "ground", 0, minetest.LIGHT_MAX+1, 30, 100000, 4, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max) -- Spawning in Nether portals in the Overworld -mobs:spawn_specific("mobs_mc:pigman", mobs_mc.spawn.nether_portal, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 500, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) +--mobs:spawn_specific("mobs_mc:pigman", mobs_mc.spawn.nether_portal, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 500, 4, mobs_mc.spawn_height.overworld_min, mobs_mc.spawn_height.overworld_max) -- spawn eggs mobs:register_egg("mobs_mc:pigman", S("Zombie Pigman"), "mobs_mc_spawn_icon_zombie_pigman.png", 0) From ec6eb517262793c7f0d589be5406b9a7071e5bc1 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Wed, 7 Apr 2021 02:39:15 -0400 Subject: [PATCH 28/32] Massively overhaul spawning algorithm for mobs --- mods/ENTITIES/mcl_mobs/api.lua | 156 +++++++++++++++++++++++++++++++-- 1 file changed, 150 insertions(+), 6 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 49c8edeaf..d85633421 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -4026,7 +4026,14 @@ types of spawning: what is aoc??? WARNING: BIOME INTEGRATION NEEDED -> How to get biome through lua?? - ]]-- +]]-- + +--this is where all of the spawning information is kept +local spawn_dictionary = { + ["overworld"] = {}, + ["nether"] = {}, + ["end"] = {} +} function mobs:spawn_specific( name, @@ -4043,10 +4050,6 @@ function mobs:spawn_specific( on_spawn) - - - print(name, dump(nodes)) - -- Do mobs spawn at all? if not mobs_spawn then return @@ -4067,7 +4070,6 @@ function mobs:spawn_specific( minetest.log("action", string.format("[mobs] Chance setting for %s changed to %s (total: %s)", name, chance, aoc)) - end local spawn_action @@ -4232,6 +4234,24 @@ function mobs:spawn_specific( spawn_action(pos, node, active_object_count, active_object_count_wider, name) end + + --load information into the spawn dictionary + local key = #spawn_dictionary[dimension] + 1 + + spawn_dictionary[dimension][key] = {} + spawn_dictionary[dimension][key]["name"] = name + spawn_dictionary[dimension][key]["type"] = type_of_spawning + spawn_dictionary[dimension][key]["min_light"] = min_light + spawn_dictionary[dimension][key]["max_light"] = max_light + spawn_dictionary[dimension][key]["interval"] = interval + spawn_dictionary[dimension][key]["chance"] = chance + spawn_dictionary[dimension][key]["aoc"] = aoc + spawn_dictionary[dimension][key]["min_height"] = min_height + spawn_dictionary[dimension][key]["max_height"] = max_height + spawn_dictionary[dimension][key]["day_toggle"] = day_toggle + spawn_dictionary[dimension][key]["on_spawn"] = spawn_abm_action + + --[[ minetest.register_abm({ label = name .. " spawning", nodenames = nodes, @@ -4241,18 +4261,24 @@ function mobs:spawn_specific( catch_up = false, action = spawn_abm_action, }) + ]]-- end -- compatibility with older mob registration +-- we're going to forget about this for now -j4i +--[[ function mobs:register_spawn(name, nodes, max_light, min_light, chance, active_object_count, max_height, day_toggle) mobs:spawn_specific(name, nodes, {"air"}, min_light, max_light, 30, chance, active_object_count, -31000, max_height, day_toggle) end +]]-- +--I'm not sure what this does but disabling it doesn't cause a crash -j4i -- MarkBu's spawn function +--[[ function mobs:spawn(def) local name = def.name @@ -4271,9 +4297,127 @@ function mobs:spawn(def) mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, interval, chance, active_object_count, min_height, max_height, day_toggle, on_spawn) end +]]-- +local axis +--inner and outer part of square donut radius +local inner = 1 +local outer = 70 +local int = {-1,1} +local position_calculation = function(pos) + pos = vector.floor(pos) + + --this is used to determine the axis buffer from the player + axis = math.random(0,1) + + --cast towards the direction + if axis == 0 then --x + pos.x = pos.x + math.random(inner,outer)*int[math.random(1,2)] + pos.z = pos.z + math.random(-outer,outer) + else --z + pos.z = pos.z + math.random(inner,outer)*int[math.random(1,2)] + pos.x = pos.x + math.random(-outer,outer) + end + return(pos) +end + +--[[ +local decypher_limits_dictionary = { + ["overworld"] = {mcl_vars.mg_overworld_min,mcl_vars.mg_overworld_max}, + ["nether"] = {mcl_vars.mg_nether_min, mcl_vars.mg_nether_max}, + ["end"] = {mcl_vars.mg_end_min, mcl_vars.mg_end_max} +} +]]-- + +local function decypher_limits(posy) + --local min_max_table = decypher_limits_dictionary[dimension] + --return min_max_table[1],min_max_table[2] + posy = math.floor(posy) + return posy - 32, posy + 32 +end + + +--todo mob limiting +--MAIN LOOP +local timer = 0 +minetest.register_globalstep(function(dtime) + timer = timer + dtime + if timer >= 15 then + timer = 0 + for _,player in ipairs(minetest.get_connected_players()) do + for i = 1,math.random(5) do + local player_pos = player:get_pos() + local _,dimension = mcl_worlds.y_to_layer(player_pos.y) + local min,max = decypher_limits(player_pos.y) + + local goal_pos = position_calculation(player_pos) + + + local mob_def = spawn_dictionary[dimension][math.random(1,#spawn_dictionary[dimension])] + + if not mob_def then --to catch a crazy error if it ever happens + minetest.log("error", "WARNING!! mob spawning attempted to index a NIL mob!") + goto continue + end + + if mob_def.type == "ground" then + + local spawning_position_list = minetest.find_nodes_in_area_under_air(vector.new(goal_pos.x,min,goal_pos.z), vector.new(goal_pos.x,max,goal_pos.z), {"group:solid"}) + + if #spawning_position_list <= 0 then + goto continue + end + + local spawning_position = spawning_position_list[math.random(1,#spawning_position_list)] + + spawning_position.y = spawning_position.y + 1 + + local gotten_light = minetest.get_node_light(spawning_position) + + if gotten_light and gotten_light >= mob_def.min_light and gotten_light <= mob_def.max_light then + minetest.add_entity(spawning_position, mob_def.name) + end + elseif mob_def.type == "air" then + local spawning_position_list = minetest.find_nodes_in_area(vector.new(goal_pos.x,min,goal_pos.z), vector.new(goal_pos.x,max,goal_pos.z), {"air"}) + + if #spawning_position_list <= 0 then + goto continue + end + + local spawning_position = spawning_position_list[math.random(1,#spawning_position_list)] + + local gotten_light = minetest.get_node_light(spawning_position) + + if gotten_light and gotten_light >= mob_def.min_light and gotten_light <= mob_def.max_light then + minetest.add_entity(spawning_position, mob_def.name) + end + elseif mob_def.type == "water" then + local spawning_position_list = minetest.find_nodes_in_area(vector.new(goal_pos.x,min,goal_pos.z), vector.new(goal_pos.x,max,goal_pos.z), {"group:water"}) + + if #spawning_position_list <= 0 then + goto continue + end + + local spawning_position = spawning_position_list[math.random(1,#spawning_position_list)] + + local gotten_light = minetest.get_node_light(spawning_position) + + if gotten_light and gotten_light >= mob_def.min_light and gotten_light <= mob_def.max_light then + minetest.add_entity(spawning_position, mob_def.name) + end + --elseif mob_def.type == "lava" then + --implement later + end + --local spawn minetest.find_nodes_in_area_under_air(vector.new(pos.x,pos.y-find_node_height,pos.z), vector.new(pos.x,pos.y+find_node_height,pos.z), {"group:solid"}) + + + ::continue:: --this is a safety catch + end + end + end +end) From b2c09c8ba058aaa7b9f4a2295925f1cc11b62fb6 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Wed, 7 Apr 2021 09:17:13 +0200 Subject: [PATCH 29/32] Add gateway portals --- mods/ITEMS/mcl_portals/portal_gateway.lua | 70 +++++++++++++++++- mods/MAPGEN/mcl_structures/init.lua | 4 +- .../mcl_structures_end_exit_portal.mts | Bin 193 -> 222 bytes .../mcl_structures_end_exit_portal_open.mts | Bin 222 -> 0 bytes 4 files changed, 71 insertions(+), 3 deletions(-) delete mode 100644 mods/MAPGEN/mcl_structures/schematics/mcl_structures_end_exit_portal_open.mts diff --git a/mods/ITEMS/mcl_portals/portal_gateway.lua b/mods/ITEMS/mcl_portals/portal_gateway.lua index cae6fce43..6d491433c 100644 --- a/mods/ITEMS/mcl_portals/portal_gateway.lua +++ b/mods/ITEMS/mcl_portals/portal_gateway.lua @@ -24,12 +24,21 @@ local gateway_positions = { {x = 91, y = -26925, z = -29}, } +local function spawn_gateway_portal(pos, dest_str) + local path = minetest.get_modpath("mcl_structures").."/schematics/mcl_structures_end_gateway_portal.mts" + return mcl_structures.place_schematic(vector.add(pos, vector.new(-1, -2, -1)), path, "0", nil, true, dest_str and function() + minetest.get_voxel_manip():read_from_map(pos, pos) + minetest.get_meta(pos):set_string("mcl_portals:gateway_destination", dest_str) + print(dest_str) + end) +end + function mcl_portals.spawn_gateway_portal() local id = storage:get_int("gateway_last_id") + 1 local pos = gateway_positions[id] if not pos then return end storage:set_int("gateway_last_id", id) - mcl_structures.call_struct(vector.add(pos, vector.new(-1, -2, -1)), "end_gateway_portal") + spawn_gateway_portal(pos) end local gateway_def = table.copy(minetest.registered_nodes["mcl_portals:portal_end"]) @@ -43,3 +52,62 @@ gateway_def.node_box = nil gateway_def.walkable = true gateway_def.tiles[3] = nil minetest.register_node("mcl_portals:portal_gateway", gateway_def) + +local function find_destination_pos(minp, maxp) + for y = maxp.y, minp.y, -1 do + for x = maxp.x, minp.x, -1 do + for z = maxp.z, minp.z, -1 do + local pos = vector.new(x, y, z) + local nn = minetest.get_node(pos).name + if nn ~= "ignore" and nn ~= "mcl_portals:portal_gateway" and nn ~= "mcl_core:bedrock" then + local def = minetest.registered_nodes[nn] + if def and def.walkable then + return vector.add(pos, vector.new(0, 1.5, 0)) + end + end + end + end + end +end + +local preparing = {} + +local function teleport(pos, obj) + local meta = minetest.get_meta(pos) + local dest_portal + local dest_str = meta:get_string("mcl_portals:gateway_destination") + local pos_str = minetest.pos_to_string(pos) + if dest_str == "" then + dest_portal = vector.multiply(vector.direction(vector.new(0, pos.y, 0), pos), math.random(768, 1024)) + dest_portal.y = -26970 + spawn_gateway_portal(dest_portal, pos_str) + meta:set_string("mcl_portals:gateway_destination", minetest.pos_to_string(dest_portal)) + else + dest_portal = minetest.string_to_pos(dest_str) + end + local minp = vector.subtract(dest_portal, vector.new(5, 40, 5)) + local maxp = vector.add(dest_portal, vector.new(5, 10, 5)) + preparing[pos_str] = true + minetest.emerge_area(minp, maxp, function() + if obj:is_player() or obj:get_luaentity() then + obj:set_pos(find_destination_pos(minp, maxp) or vector.add(dest_portal, vector.new(0, 3.5, 0))) + end + preparing[pos_str] = false + end) +end + +minetest.register_abm({ + label = "End gateway portal teleportation", + nodenames = {"mcl_portals:portal_gateway"}, + interval = 0.1, + chance = 1, + action = function(pos) + if preparing[minetest.pos_to_string(pos)] then return end + for _, obj in pairs(minetest.get_objects_inside_radius(pos, 1)) do + if obj:get_hp() > 0 then + teleport(pos, obj) + return + end + end + end, +}) diff --git a/mods/MAPGEN/mcl_structures/init.lua b/mods/MAPGEN/mcl_structures/init.lua index 00efeca14..4ba369e01 100644 --- a/mods/MAPGEN/mcl_structures/init.lua +++ b/mods/MAPGEN/mcl_structures/init.lua @@ -318,11 +318,11 @@ end mcl_structures.generate_end_exit_portal = function(pos, rot) local path = minetest.get_modpath("mcl_structures").."/schematics/mcl_structures_end_exit_portal.mts" - return mcl_structures.place_schematic(pos, path, rot or "0", nil, true) + return mcl_structures.place_schematic(pos, path, rot or "0", {["mcl_portals:portal_end"] = "air"}, true) end mcl_structures.generate_end_exit_portal_open = function(pos, rot) - local path = minetest.get_modpath("mcl_structures").."/schematics/mcl_structures_end_exit_portal_open.mts" + local path = minetest.get_modpath("mcl_structures").."/schematics/mcl_structures_end_exit_portal.mts" return mcl_structures.place_schematic(pos, path, rot or "0", nil, true) end diff --git a/mods/MAPGEN/mcl_structures/schematics/mcl_structures_end_exit_portal.mts b/mods/MAPGEN/mcl_structures/schematics/mcl_structures_end_exit_portal.mts index 30d145bd7fdc822259191c918696b74769628d72..bc24f800a6de0e4265fdbe08808c9720061b8490 100644 GIT binary patch delta 161 zcmX@ec#l!oHze4XfrWvcft7*19t0RzCkh(~733F{B<2)bLFo9@yp)NyQu%u)-Q_x< zz|k6fyLf*1{0PUO)hWr(V>%M#|4o_Hb;dWRuj`fdDjvh*7QKNMy&uns)}uDrD>;&p_i$xlx^$sU)L+^RXm2rEqVhjdOw~yd0eDy%Dic&uPyg1I8yyH zO~3W?FE<7=#tl0-et5I*%~5yCuvOaK+coXSeq%5FGkVh6GdgztnH3o08erZh5UT|M Dl|EWe From c451866a36a4cb6c58928dbcd1379a62500484df Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Wed, 7 Apr 2021 09:56:00 +0200 Subject: [PATCH 30/32] Fix #1426 --- mods/ITEMS/mcl_sponges/init.lua | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/mods/ITEMS/mcl_sponges/init.lua b/mods/ITEMS/mcl_sponges/init.lua index b832c01c6..75a99b0f1 100644 --- a/mods/ITEMS/mcl_sponges/init.lua +++ b/mods/ITEMS/mcl_sponges/init.lua @@ -94,6 +94,35 @@ minetest.register_node("mcl_sponges:sponge", { _mcl_hardness = 0.6, }) +function place_wet_sponge(itemstack, placer, pointed_thing) + if pointed_thing.type ~= "node" then + return itemstack + end + -- Use pointed node's on_rightclick function first, if present + local node = minetest.get_node(pointed_thing.under) + if placer and not placer:get_player_control().sneak then + if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then + return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, placer, itemstack) or itemstack + end + end + + local name = placer:get_player_name() + + if minetest.is_protected(pointed_thing.above, name) then + return itemstack + end + + if mcl_worlds.pos_to_dimension(pointed_thing.above) == "nether" then + minetest.item_place_node(ItemStack("mcl_sponges:sponge"), placer, pointed_thing) + if not minetest.is_creative_enabled(name) then + itemstack:take_item() + end + return itemstack + end + + return minetest.item_place_node(itemstack, placer, pointed_thing) +end + minetest.register_node("mcl_sponges:sponge_wet", { description = S("Waterlogged Sponge"), _tt_help = S("Can be dried in furnace"), @@ -108,6 +137,7 @@ minetest.register_node("mcl_sponges:sponge_wet", { stack_max = 64, sounds = mcl_sounds.node_sound_dirt_defaults(), groups = {handy=1, hoey=1, building_block=1}, + on_place = place_wet_sponge, _mcl_blast_resistance = 0.6, _mcl_hardness = 0.6, }) @@ -127,6 +157,7 @@ if minetest.get_modpath("mclx_core") then stack_max = 64, sounds = mcl_sounds.node_sound_dirt_defaults(), groups = {handy=1, building_block=1}, + on_place = place_wet_sponge, _mcl_blast_resistance = 0.6, _mcl_hardness = 0.6, }) From f664a87dac0f64f8fed1847fbbf1c39da5873efb Mon Sep 17 00:00:00 2001 From: TechDudie Date: Mon, 5 Apr 2021 18:45:02 +0000 Subject: [PATCH 31/32] Update 'mods/ENTITIES/mobs_mc/creeper.lua' --- mods/ENTITIES/mobs_mc/creeper.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/mods/ENTITIES/mobs_mc/creeper.lua b/mods/ENTITIES/mobs_mc/creeper.lua index f283fac18..ce07e4146 100644 --- a/mods/ENTITIES/mobs_mc/creeper.lua +++ b/mods/ENTITIES/mobs_mc/creeper.lua @@ -200,7 +200,6 @@ mobs:register_mob("mobs_mc:creeper_charged", { self._forced_explosion_countdown_timer = self._forced_explosion_countdown_timer - dtime if self._forced_explosion_countdown_timer <= 0 then mobs:boom(self, mcl_util.get_object_center(self.object), self.explosion_strength) - self.object:remove() end end end, From db9e8d23d96bcef23b94b84c4193bc0b523d9d7d Mon Sep 17 00:00:00 2001 From: TechDudie Date: Mon, 5 Apr 2021 18:51:35 +0000 Subject: [PATCH 32/32] Update 'mods/ENTITIES/mobs_mc/creeper.lua' --- mods/ENTITIES/mobs_mc/creeper.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/mods/ENTITIES/mobs_mc/creeper.lua b/mods/ENTITIES/mobs_mc/creeper.lua index ce07e4146..f1f0a3ef6 100644 --- a/mods/ENTITIES/mobs_mc/creeper.lua +++ b/mods/ENTITIES/mobs_mc/creeper.lua @@ -78,7 +78,6 @@ mobs:register_mob("mobs_mc:creeper", { self._forced_explosion_countdown_timer = self._forced_explosion_countdown_timer - dtime if self._forced_explosion_countdown_timer <= 0 then mobs:boom(self, mcl_util.get_object_center(self.object), self.explosion_strength) - self.object:remove() end end end,