From 47b1c44b383bccfeb9a1a44d0f9049b0ebbff6d3 Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Mon, 19 Sep 2022 23:18:49 +0100 Subject: [PATCH] Upgrade position system, add initial position markers --- .../core/entities/init.lua | 14 ++++ .../core/entities/pos_marker.lua | 81 +++++++++++++++++++ worldeditadditions_core/core/pos.lua | 64 ++++++++++++--- .../core/pos_marker_manage.lua | 36 +++++++++ worldeditadditions_core/init.lua | 5 +- .../utils/EventEmitter.lua | 4 +- 6 files changed, 190 insertions(+), 14 deletions(-) create mode 100644 worldeditadditions_core/core/entities/init.lua create mode 100644 worldeditadditions_core/core/entities/pos_marker.lua create mode 100644 worldeditadditions_core/core/pos_marker_manage.lua diff --git a/worldeditadditions_core/core/entities/init.lua b/worldeditadditions_core/core/entities/init.lua new file mode 100644 index 0000000..f673be1 --- /dev/null +++ b/worldeditadditions_core/core/entities/init.lua @@ -0,0 +1,14 @@ +-- ███████ ███ ██ ████████ ██ ████████ ██ ███████ ███████ +-- ██ ████ ██ ██ ██ ██ ██ ██ ██ +-- █████ ██ ██ ██ ██ ██ ██ ██ █████ ███████ +-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +-- ███████ ██ ████ ██ ██ ██ ██ ███████ ███████ + +--- Entities and functions to manage them. +-- @namespace worldeditadditions_core.entities + +local wea_c = worldeditadditions_core + +return { + pos_marker = dofile(wea_c.modpath.."/core/entities/pos_marker.lua"), +} \ No newline at end of file diff --git a/worldeditadditions_core/core/entities/pos_marker.lua b/worldeditadditions_core/core/entities/pos_marker.lua new file mode 100644 index 0000000..079cc49 --- /dev/null +++ b/worldeditadditions_core/core/entities/pos_marker.lua @@ -0,0 +1,81 @@ +local wea_c = worldeditadditions_core +local EventEmitter = worldeditadditions_core.EventEmitter + + +local anchor + +local WEAPositionMarker = { + initial_properties = { + visual = "cube", + visual_size = { x = 1.15, y = 1.1 }, + collisionbox = { -0.55, -0.55, -0.55, 0.55, 0.55, 0.55 }, + physical = false, + collide_with_objects = false, + static_save = false, + + textures = { + "worldeditadditions_bg.png", + "worldeditadditions_bg.png", + "worldeditadditions_bg.png", + "worldeditadditions_bg.png", + "worldeditadditions_bg.png", + "worldeditadditions_bg.png", + } + }, + + on_activate = function(self, staticdata) + -- noop + end, + on_punch = function(self, _) + anchor.delete(self) + end, + on_blast = function(self, damage) + return false, false, {} -- Do not damage or knockback the player + end +} + +minetest.register_entity(":worldeditadditions:position", WEAPositionMarker) + +local function create(player_name, pos, display_number) + local entity = minetest.add_entity(pos, "worldeditadditions:position") + + entity:get_luaentity().player_name = player_name + entity:get_luaentity().display_number = display_number + + anchor.set_number(entity, display_number) + + anchor:emit("create", { + player_name = player_name, + pos = pos, + display_number = display_number, + }) + return entity +end + +local function delete(entity) + local player_name = entity:get_luaentity().player_name + local display_number = entity:get_luaentity().display_number + + entity:remove() + + anchor:emit("delete", { + player_name = player_name, + display_number = display_number + }) +end + +local function set_number(entity, display_number) + if type(display_number) ~= "number" then return false, "Error: The 'display_number' property must be of type number, but received value of unexpected type '"..type(display_number).."'." end + + -- marker:set_properties({ }) is our friend + print("DEBUG:pos_marker_set_number display_number", display_number) + print("DEBUG:pos_marker_set_number TODO_IMPLEMENT THIS. entity", wea_c.inspect(entity)) +end + +anchor = EventEmitter.new({ + create = create, + delete = delete, + set_number = set_number +}) + +return anchor \ No newline at end of file diff --git a/worldeditadditions_core/core/pos.lua b/worldeditadditions_core/core/pos.lua index f50e08b..b8ced59 100644 --- a/worldeditadditions_core/core/pos.lua +++ b/worldeditadditions_core/core/pos.lua @@ -2,8 +2,16 @@ local wea_c = worldeditadditions_core local positions_count_limit = 999 local positions = {} + +--- Position manager. +-- @event set { player_name: string, i: number, pos: Vector3 } A new position has been set in a player's list at a specific position. +-- @event push { player_name: string, i: number, pos: Vector3 } A new position has been pushed onto a player's stack. +-- @event pop { player_name: string, i: number, pos: Vector3 } A new position has been pushed onto a player's stack. +-- @event clear { player_name: string } The positions for a player have been cleared. local anchor = nil +--- Ensures that a table exists for the given player. +-- @param player_name string The name of the player to check. local function ensure_player(player_name) if player_name == nil then minetest.log("error", "[wea core:pos:ensure_player] player_name is nil") @@ -15,55 +23,91 @@ end --- Gets the position with the given index for the given player. -- @param player_name string The name of the player to fetch the position for. --- @param +-- @param i number The index of the position to fetch. +-- @returns Vector3? The position requested, or nil if it doesn't exist. local function get_pos(player_name, i) ensure_player(player_name) return positions[player_name][i] end +--- Convenience function that returns position 1 for the given player. +-- @param player_name string The name of the player to fetch the position for. +-- @returns Vector3? The position requested, or nil if it doesn't exist. local function get_pos1(player_name) return get_pos(player_name, 1) end +--- Convenience function that returns position 1 for the given player. +-- @param player_name string The name of the player to fetch the position for. +-- @returns Vector3? The position requested, or nil if it doesn't exist. local function get_pos2(player_name) return get_pos(player_name, 2) end +--- Gets a list of all the positions for the given player. +-- @param player_name string The name of the player to fetch the position for. +-- @returns Vector3[] A list of positions for the given player. local function get_pos_all(player_name) ensure_player(player_name) - return positions[player_name] + return wea_c.table.deepcopy(positions[player_name]) end +--- Counts the number of positioons registered to a given player. +-- @param player_name string The name of the player to fetch the position for. +-- @returns number The number of positions registered for the given player. local function pos_count(player_name) ensure_player(player_name) return #positions[player_name] end - +--- Sets the position at the given index for the given player. +-- You probably want push_pos, not this function. +-- @param player_name string The name of the player to set the position for. +-- @param i number The index to set the position at. +-- @param pos Vector3 The position to set. +-- @returns bool Whether the operation was successful or not (players aren't allowed more than positions_count_limit number of positions at a time). local function set_pos(player_name, i, pos) if i > positions_count_limit then return false end ensure_player(player_name) positions[player_name][i] = pos - anchor:emit("set", { i = i, pos = pos }) + anchor:emit("set", { player_name = player_name, i = i, pos = pos }) return true end -local function set_pos_all(player_name, i, pos_list) +--- Sets the all the positions for the given player. +-- You probably want push_pos, not this function. +-- @param player_name string The name of the player to set the positions for. +-- @param pos_list Vector3 The table of positions to set. +-- @returns bool Whether the operation was successful or not (players aren't allowed more than positions_count_limit number of positions at a time). +local function set_pos_all(player_name, pos_list) if #pos_list > positions_count_limit then return false end positions[player_name] = pos_list - for _i,pos_new in ipairs(positions[player_name]) do - anchor:emit("push", { pos = pos_new }) + for i,pos_new in ipairs(positions[player_name]) do + anchor:emit("push", { player_name = player_name, pos = pos_new, i = i }) end + return true end +--- Clears all the positions for the given player. +-- @param player_name string The name of the player to clear the positions for. +-- @returns void local function clear(player_name) if positions[player_name] then positions[player_name] = nil end - anchor:emit("clear") + anchor:emit("clear", { player_name = player_name }) end +--- Removes the last position from the for a given player and returns it. +-- @param player_name string The name of the player to pop the position for. +-- @returns Vector3? The position removed, or nil if it doesn't exist. local function pop_pos(player_name) ensure_player(player_name) if #positions[player_name] <= 0 then return nil end + local count = #positions[player_name] local last_pos = table.remove(positions[player_name]) - anchor:emit("pop", { pos = last_pos }) + anchor:emit("pop", { player_name = player_name, pos = last_pos, i = count }) return last_pos end +--- Adds a position to the list for a given player. +-- @param player_name string The name of the player to add the position for. +-- @param pos Vector3 The position to add. +-- @returns number The new number of positions for that player. local function push_pos(player_name, pos) ensure_player(player_name) table.insert(positions[player_name], pos) - anchor:emit("push", { pos = pos }) + anchor:emit("push", { player_name = player_name, pos = pos, i = #positions[player_name] }) + return #positions[player_name] end diff --git a/worldeditadditions_core/core/pos_marker_manage.lua b/worldeditadditions_core/core/pos_marker_manage.lua new file mode 100644 index 0000000..c868611 --- /dev/null +++ b/worldeditadditions_core/core/pos_marker_manage.lua @@ -0,0 +1,36 @@ +local wea_c = worldeditadditions_core + +local position_entities = {} + + +--- Ensures that a table exists for the given player. +-- @param player_name string The name of the player to check. +local function ensure_player(player_name) + if player_name == nil then + minetest.log("error", "[wea core:pos_manage:ensure_player] player_name is nil") + end + if not position_entities[player_name] then + position_entities[player_name] = {} + end +end + +wea_c.pos:addEventListener("push", function(event) + ensure_player(event.player_name) + + local new_entity = wea_c.entities.pos_marker.create( + event.player_name, + event.pos, + event.i + ) + position_entities[event.player_name][event.i] = new_entity +end) + +wea_c.pos:addEventListener("pop", function(event) + ensure_player(event.player_name) + print("pos manage: pop", wea_c.inspect(event)) + if not position_entities[event.player_name][event.i] then return end + wea_c.entities.pos_marker.delete( + position_entities[event.player_name][event.i] + ) + position_entities[event.player_name][event.i] = nil +end) \ No newline at end of file diff --git a/worldeditadditions_core/init.lua b/worldeditadditions_core/init.lua index 81738b6..3d9e5dd 100644 --- a/worldeditadditions_core/init.lua +++ b/worldeditadditions_core/init.lua @@ -58,11 +58,12 @@ dofile(wea_c.modpath.."/utils/player.lua") -- Player info functions -wea_c.pos = dofile(modpath.."/core/pos.lua") +wea_c.pos = dofile(modpath.."/core/pos.lua") -- AFTER EventEmitter wea_c.register_command = dofile(modpath.."/core/register_command.lua") wea_c.fetch_command_def = dofile(modpath.."/core/fetch_command_def.lua") wea_c.register_alias = dofile(modpath.."/core/register_alias.lua") -print("WEA_C pos", wea_c.pos.push) +wea_c.entities = dofile(modpath.."/core/entities/init.lua") -- AFTER pos +dofile(modpath.."/core/pos_marker_manage.lua") -- AFTER pos, entities -- Initialise WorldEdit stuff if the WorldEdit mod is not present if minetest.global_exists("worldedit") then diff --git a/worldeditadditions_core/utils/EventEmitter.lua b/worldeditadditions_core/utils/EventEmitter.lua index b26778b..72e3c65 100644 --- a/worldeditadditions_core/utils/EventEmitter.lua +++ b/worldeditadditions_core/utils/EventEmitter.lua @@ -1,6 +1,6 @@ --- Event manager object. --- @class +-- @class worldeditadditions_core.EventEmitter local EventEmitter = {} EventEmitter.__index = EventEmitter EventEmitter.__name = "EventEmitter" -- A hack to allow identification in wea.inspect @@ -18,7 +18,7 @@ end --- Add a new listener to the given named event. -- @param this EventEmitter The EventEmitter instance to add the listener to. -- @param event_name string The name of the event to listen on. --- @param func function The callback function to call when the event is emitted. +-- @param func function The callback function to call when the event is emitted. Will be passed a single argument - the object passed as the second argument to .emit(). -- @returns number The number of listeners attached to that event. function EventEmitter.addEventListener(this, event_name, func) if this.events[event_name] == nil then this.events[event_name] = {} end