From f8d3ffd86be4ea7e8cd4da7d040cbb285aa1fccc Mon Sep 17 00:00:00 2001 From: teknomunk Date: Fri, 12 Apr 2024 19:01:15 +0000 Subject: [PATCH] Add persistent player-specific metadata into mcl_playerinfo, simple cart reattachment (only exists if the luaentity for the cart exists when the player logs in) --- mods/ENTITIES/mcl_minecarts/carts.lua | 41 ++++++++++++ .../ENTITIES/mcl_minecarts/carts/minecart.lua | 67 ++++++++++--------- mods/PLAYER/mcl_playerinfo/init.lua | 27 +++++++- 3 files changed, 103 insertions(+), 32 deletions(-) diff --git a/mods/ENTITIES/mcl_minecarts/carts.lua b/mods/ENTITIES/mcl_minecarts/carts.lua index 26a95f826..d13059b99 100644 --- a/mods/ENTITIES/mcl_minecarts/carts.lua +++ b/mods/ENTITIES/mcl_minecarts/carts.lua @@ -42,6 +42,8 @@ local function detach_driver(self) -- Update cart informatino self._driver = nil self._start_pos = nil + local meta = mcl_playerinfo.get_mod_meta(driver_name, modname) + meta.attached_to = nil -- Detatch the player object from the minecart local player = minetest.get_player_by_name(driver_name) @@ -609,3 +611,42 @@ minetest.register_globalstep(function(dtime) end end) +minetest.register_on_joinplayer(function(player) + local player_name = player:get_player_name() + local meta = mcl_playerinfo.get_mod_meta(player_name, modname) + local cart_uuid = meta.attached_to + if cart_uuid then + print("Trying to reattach "..player_name.." to cart #"..cart_uuid) + local cartdata = get_cart_data(cart_uuid) + + -- Can't get into a cart that was destroyed + if not cartdata then + print("Failed to get cartdata") + return + end + + -- Don't reattach players if someone else got in the cart + if cartdata.last_player ~= player_name then + print("Somebody else got in the cart while you were gone") + return + end + + minetest.after(0.2,function(player_name, cart_uuid) + local player = minetest.get_player_by_name(player_name) + if not player then + print("Can't get an ObjectRef for "..player_name) + return + end + + local cart = mcl_util.get_luaentity_from_uuid(cart_uuid) + if not cart then + print("Can't find the luaentity for cart #"..cart_uuid) + return + end + + mod.attach_driver(cart, player) + + end, player_name, cart_uuid) + end +end) + diff --git a/mods/ENTITIES/mcl_minecarts/carts/minecart.lua b/mods/ENTITIES/mcl_minecarts/carts/minecart.lua index bf3fce514..7f36fbb07 100644 --- a/mods/ENTITIES/mcl_minecarts/carts/minecart.lua +++ b/mods/ENTITIES/mcl_minecarts/carts/minecart.lua @@ -16,6 +16,41 @@ local function activate_normal_minecart(self) end end +function mod.attach_driver(cart, player) + local staticdata = cart._staticdata + + -- Make sure we have a player + if not player or not player:is_player() then return end + + local player_name = player:get_player_name() + if cart._driver or player:get_player_control().sneak then return end + + -- Update cart information + cart._driver = player_name + cart._start_pos = cart.object:get_pos() + + -- Keep track of player attachment + local meta = mcl_playerinfo.get_mod_meta(player_name, modname) + meta.attached_to = cart._uuid + staticdata.last_player = player_name + + -- Update player information + local uuid = staticdata.uuid + mcl_player.player_attached[player_name] = true + minetest.log("action", player_name.." entered minecart #"..tostring(uuid).." at "..tostring(cart._start_pos)) + + -- Attach the player object to the minecart + player:set_attach(cart.object, "", vector.new(1,-1.75,-2), vector.new(0,0,0)) + minetest.after(0.2, function(name) + local player = minetest.get_player_by_name(name) + if player then + mcl_player.player_set_animation(player, "sit" , 30) + player:set_eye_offset(vector.new(0,-5.5,0), vector.new(0,-4,0)) + mcl_title.set(player, "actionbar", {text=S("Sneak to dismount"), color="white", stay=60}) + end + end, player_name) +end + mod.register_minecart({ itemstring = "mcl_minecarts:minecart", craft = { @@ -39,37 +74,7 @@ mod.register_minecart({ }, icon = "mcl_minecarts_minecart_normal.png", drop = {"mcl_minecarts:minecart"}, - on_rightclick = function(self, clicker) - -- Make sure we have a player - if not clicker or not clicker:is_player() then return end - - local player_name = clicker:get_player_name() - if self._driver or clicker:get_player_control().sneak then return end - - -- Update cart information - self._driver = player_name - self._start_pos = self.object:get_pos() - - -- Update player information - local uuid = self._staticdata.uuid - local playerinfo = mcl_playerinfo[player_name] - if playerinfo and self._staticdata then - playerinfo.attached_to = uuid - end - mcl_player.player_attached[player_name] = true - minetest.log("action", player_name.." entered minecart #"..tostring(uuid).." at "..tostring(self._start_pos)) - - -- Attach the player object to the minecart - clicker:set_attach(self.object, "", vector.new(1,-1.75,-2), vector.new(0,0,0)) - minetest.after(0.2, function(name) - local player = minetest.get_player_by_name(name) - if player then - mcl_player.player_set_animation(player, "sit" , 30) - player:set_eye_offset(vector.new(0,-5.5,0), vector.new(0,-4,0)) - mcl_title.set(clicker, "actionbar", {text=S("Sneak to dismount"), color="white", stay=60}) - end - end, player_name) - end, + on_rightclick = mod.attach_driver, on_activate_by_rail = activate_normal_minecart, _mcl_minecarts_on_step = function(self, dtime) -- Grab mob diff --git a/mods/PLAYER/mcl_playerinfo/init.lua b/mods/PLAYER/mcl_playerinfo/init.lua index f15f46b36..b2ce5cf70 100644 --- a/mods/PLAYER/mcl_playerinfo/init.lua +++ b/mods/PLAYER/mcl_playerinfo/init.lua @@ -1,7 +1,10 @@ local table = table +local storage = minetest.get_mod_storage() + -- Player state for public API mcl_playerinfo = {} +local player_mod_metadata = {} -- Get node but use fallback for nil or unknown local function node_ok(pos, fallback) @@ -73,6 +76,23 @@ minetest.register_globalstep(function(dtime) end) +function mcl_playerinfo.get_mod_meta(player_name, modname) + -- Load the player's metadata + local meta = player_mod_metadata[player_name] + if not meta then + meta = minetest.deserialize(storage:get_string(player_name)) + end + if not meta then + meta = {} + end + player_mod_metadata[player_name] = meta + + -- Get the requested module's section of the metadata + local mod_meta = meta[modname] or {} + meta[modname] = mod_meta + return mod_meta +end + -- set to blank on join (for 3rd party mods) minetest.register_on_joinplayer(function(player) local name = player:get_player_name() @@ -84,7 +104,6 @@ minetest.register_on_joinplayer(function(player) node_stand_below = "", node_head_top = "", } - end) -- clear when player leaves @@ -93,3 +112,9 @@ minetest.register_on_leaveplayer(function(player) mcl_playerinfo[name] = nil end) + +minetest.register_on_shutdown(function() + for name,data in pairs(player_mod_metadata) do + storage:set_string(name, minetest.serialize(data)) + end +end)