Merge branch 'main' into selection-tools

This commit is contained in:
VorTechnix 2023-12-13 14:22:38 -08:00
commit 15c07170c1
No known key found for this signature in database
GPG key ID: 091E91A69545D5BA
21 changed files with 294 additions and 49 deletions

View file

@ -1,6 +1,6 @@
{
"name": "worldeditadditions",
"version": "1.14.1",
"version": "1.14.5",
"description": "Documentation website for WorldEditAdditions",
"main": "index.js",
"private": true,

26
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View file

@ -0,0 +1,26 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
**Describe the bug**
What's the bug? Be clear and concise in our explanation. Don't forget to include any context, error messages, logs, and screenshots required to understand the issue if applicable.
**Reproduction steps:**
Steps to reproduce the behaviour:
1. Go to '...'
2. Click on '....'
3. Enter this command to '....'
4. See error
**System information (please complete the following information):**
- **Operating system and version:** [e.g. iOS]
- **Minetest version:** [e.g. 5.8.0]
- **WorldEdit version:**
- **WorldEditAdditions version:**
Please add any other additional specific system information here too if you think it would help.

View file

@ -0,0 +1,22 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ''
---
## Problem
A clear and concise description of what the problem you want to solve is. e.g. I'm always frustrated when [...]
## Solution
Describe clearly the solution you'd like.
## Alternatives
A clear and concise description of any alternative solutions or features you've considered, and how they relate to your proposed feature.
## Additional context
Add any other context or screenshots about the feature request here.
Don't forget to remove replace descriptions, but keep the headers.

View file

@ -3,6 +3,24 @@ It's about time I started a changelog! This will serve from now on as the main c
Note to self: See the bottom of this file for the release template text.
## v1.14.5: The multipoint update, hotfix 5 (1st August 2023)
- Fix a bug where creative players in survival couldn't punch out position markers
- Added `//listentities`, which lists all currently loaded `ObjectRef`s. This is intended for debugging mods - thanks to @Zughy in #103
## v1.14.4: The multipoint update, hotfix 4 (31st July 2023)
- When any segment of the marker wall is punched, unmark the entire wall
## v1.14.3: The multipoint update, hotfix 3 (18th July 2023)
- Fix regions not remembering their state and being unresettable
## v1.14.2: The multipoint update, hotfix 2 (15th July 2023)
- Fix crash in `//subdivide`, again due to the new position system
## v1.14.1: The multipoint update, hotfix 1 (12th July 2023)
- Fix issue #100, which caused a crash as `//pos1` and `//pos2` allowed non-integer positions to be set

View file

@ -1349,6 +1349,17 @@ Here are some more examples:
```
### `//listentities`
Lists all currently loaded ObjectRefs. Displays their IDs, Names (if possible), and possitions.
This command is intended for development and modding. You will not normally need to use this command using WorldEditAdditions.
`//listentities` takes no arguments.
```
//listentities
```
## Extras
<!--

View file

@ -1,5 +1,5 @@
# ![](https://raw.githubusercontent.com/sbrl/Minetest-WorldEditAdditions/main/worldeditadditions-64.png) Minetest-WorldEditAdditions
![GitHub release (latest by date)](https://img.shields.io/github/v/release/sbrl/Minetest-WorldEditAdditions?color=green&label=latest%20release) [![View the changelog](https://img.shields.io/badge/%F0%9F%93%B0-Changelog-informational)](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/CHANGELOG.md) [![ContentDB](https://content.minetest.net/packages/Starbeamrainbowlabs/worldeditadditions/shields/downloads/)](https://content.minetest.net/packages/Starbeamrainbowlabs/worldeditadditions/)
# ![](https://raw.githubusercontent.com/sbrl/Minetest-WorldEditAdditions/main/worldeditadditions-64.png) WorldEditAdditions
![GitHub release (latest by date)](https://img.shields.io/github/v/release/sbrl/Minetest-WorldEditAdditions?color=green&label=latest%20release) [![View the changelog](https://img.shields.io/badge/%F0%9F%93%B0-Changelog-informational)](https://github.com/sbrl/Minetest-WorldEditAdditions/blob/main/CHANGELOG.md) [![ContentDB](https://content.minetest.net/packages/Starbeamrainbowlabs/worldeditadditions/shields/downloads/)](https://content.minetest.net/packages/Starbeamrainbowlabs/worldeditadditions/) [![Join the official discord server](https://worldeditadditions.mooncarrot.space/img/shield-discord.svg)](https://discord.gg/FzD73kuhsk)
> Extra tools and commands to extend WorldEdit for Minetest

View file

@ -2,10 +2,10 @@
set -e;
# current_branch="$(git rev-parse --abbrev-ref HEAD)";
is_main="$(git branch --contains HEAD | awk '/HEAD/ { next } /main/ { print $1 }')";
is_main="$(git branch --contains HEAD | awk '/HEAD/ { next } /dev/ { print $1 }')";
if [[ "${1}" == "ci" ]] && [[ ! -z "${is_main}" ]]; then
echo "Skipping build, because this commit does not appear to be on the 'main' branch, and we only deploy commits on the 'main' branch.";
echo "Skipping build, because this commit does not appear to be on the 'dev' branch, and we only deploy commits on the 'main' branch.";
fi
# ██████ ██ ██████ ██ ██ ██ ██ ██████

View file

@ -3,4 +3,4 @@ description = Extra tools and commands to extend WorldEdit. Currently has over 2
depends = worldedit
optional_depends = bonemeal,cool_trees,default,moretrees,ethereal
min_minetest_version = 5.1
min_minetest_version = 5.2

View file

@ -1,6 +1,6 @@
--- WorldEditAdditions
-- @namespace worldeditadditions
-- @release 1.14.1
-- @release 1.14.5
-- @copyright 2023 Starbeamrainbowlabs
-- @license Mozilla Public License, 2.0
-- @author Starbeamrainbowlabs

View file

@ -1,6 +1,7 @@
local wea = worldeditadditions
--- Noise generation algorithm engines.
-- @namespace worldeditadditions.noise.engines
return {
available = { "perlin", "perlinmt", "sin", "white", "red", "infrared" },
Perlin = dofile(wea.modpath.."/lib/noise/engines/perlin.lua"),

View file

@ -1,5 +1,8 @@
local wea = worldeditadditions
--- System to manipulate the world using noise generation functions.
-- @namespace worldeditadditions.noise
wea.noise = {}
-- The command itself

View file

@ -5,17 +5,18 @@
-- ███████ ██████ ██████ ██████ ██ ████ ██ ██████ ███████
local wea_c = worldeditadditions_core
local wea = worldeditadditions
local Vector3 = wea_c.Vector3
-- Counts the number of chunks in the given area.
-- Maths is now done properly. Values from this new implementation were tested
-- with 1000 random pos1, pos2, and chunk_size combinations and found to be identical.
local function count_chunks(pos1, pos2, chunk_size)
-- Assume pos1 & pos2 are sorted
local dimensions = {
x = pos2.x - pos1.x + 1,
y = pos2.y - pos1.y + 1,
z = pos2.z - pos1.z + 1,
}
local dimensions = Vector3.new(
pos2.x - pos1.x + 1,
pos2.y - pos1.y + 1,
pos2.z - pos1.z + 1
)
-- print("[new] dimensions", dimensions.x, dimensions.y, dimensions.z)
return math.ceil(dimensions.x / chunk_size.x)
* math.ceil(dimensions.y / chunk_size.y)
@ -68,12 +69,12 @@ local function subdivide_step_beforeload(state)
end
end
state.cpos2 = { x = state.cpos.x, y = state.cpos.y, z = state.cpos.z }
state.cpos1 = {
x = state.cpos.x - state.chunk_size.x,
y = state.cpos.y - state.chunk_size.y,
z = state.cpos.z - state.chunk_size.z
}
state.cpos2 = Vector3.new(state.cpos.x, state.cpos.y, state.cpos.z)
state.cpos1 = Vector3.new(
state.cpos.x - state.chunk_size.x,
state.cpos.y - state.chunk_size.y,
state.cpos.z - state.chunk_size.z
)
if state.cpos1.x < state.pos1.x then state.cpos1.x = state.pos1.x end
if state.cpos1.y < state.pos1.y then state.cpos1.y = state.pos1.y end
if state.cpos1.z < state.pos1.z then state.cpos1.z = state.pos1.z end
@ -151,7 +152,7 @@ function worldeditadditions.subdivide(pos1, pos2, chunk_size, callback_subblock,
local state = {
pos1 = pos1, pos2 = pos2,
-- Note that we start 1 over on the Z axis because we increment *before* calling the callback, so if we don't fiddle it here, we'll miss the first chunk
cpos = { x = pos2.x, y = pos2.y, z = pos2.z + chunk_size.z + 1 },
cpos = Vector3.new(pos2.x, pos2.y, pos2.z + chunk_size.z + 1),
-- The size of a single subblock
chunk_size = chunk_size,
-- The total number of nodes in the defined region

View file

@ -16,3 +16,5 @@ dofile(we_cmdpath.."many.lua")
dofile(we_cmdpath.."multi.lua")
dofile(we_cmdpath.."noiseapply2d.lua")
dofile(we_cmdpath.."subdivide.lua")
dofile(we_cmdpath.."listentities.lua")

View file

@ -0,0 +1,39 @@
-- Lists all currently loaded entities.
local weac = worldeditadditions_core
minetest.register_chatcommand("/listentities", {
params = "",
description =
"Lists all currently loaded entities. This is a command for debugging and development. You will not need this unless you are developing a mod.",
privs = { worldedit = true },
func = function(name, params_text)
local table_vals = {
{ "ID", "Name", "Position" },
{ "------", "-------", "---------" },
}
for id, obj in pairs(minetest.object_refs) do
local obj_name = "[ObjectRef]"
if obj.get_luaentity then
local luaentity = obj:get_luaentity()
if luaentity then
obj_name = "[LuaEntity:"..luaentity.name.."]"
else
obj_name = "[LuaEntity:__UNKNOWN__]"
end
end
local pos = weac.Vector3.clone(obj:get_pos())
table.insert(table_vals, {
id,
obj_name,
tostring(pos)
})
end
worldedit.player_notify(name, table.concat({
"Currently loaded entities:",
weac.format.make_ascii_table(table_vals),
"",
"Total "..tostring(#table_vals).." objects"
}, "\n"))
end
})

View file

@ -4,6 +4,13 @@ local EventEmitter = worldeditadditions_core.EventEmitter
local anchor
local function make_id()
return tostring(wea_c.get_ms_time()) .. "_" .. tostring(math.floor(math.random() * 1000000))
end
local last_reset = make_id()
local WEAPositionMarker = {
initial_properties = {
visual = "cube",
@ -11,7 +18,7 @@ local WEAPositionMarker = {
collisionbox = { -0.55, -0.55, -0.55, 0.55, 0.55, 0.55 },
physical = false,
collide_with_objects = false,
static_save = false,
hp_max = 1,
textures = {
"worldeditadditions_core_bg.png",
@ -24,25 +31,57 @@ local WEAPositionMarker = {
},
on_activate = function(self, staticdata)
-- noop
local data = minetest.parse_json(staticdata)
print("DEBUG:pos_marker ON_ACTIVATE data", data)
if type(data) ~= "table" or data.id ~= last_reset then
-- print("DEBUG:marker_wall/remove staticdata", staticdata, "last_reset", last_reset)
self.object:remove()
-- else
-- print("DEBUG:marker_wall/ok staticdata", staticdata, "type", type(staticdata), "last_reset", last_reset, "type", type(last_reset))
return
end
self.__id = data.id
self.player_name = data.player_name
self.display_number = data.display_number
anchor:emit("update_entity", {
entity = self.object,
id = self.__id,
player_name = self.player_name,
i = self.display_number
})
anchor.set_number(self.object, self.display_number)
end,
on_punch = function(self, _)
print("DEBUG:pos_marker on_punch")
anchor.delete(self)
end,
on_blast = function(self, damage)
return false, false, {} -- Do not damage or knockback the player
end,
get_staticdata = function(self)
return minetest.write_json({
id = self.__id,
display_number = self.display_number,
player_name = self.player_name
})
end
}
minetest.register_entity(":worldeditadditions:position", WEAPositionMarker)
local function create(player_name, pos, display_number)
local entity = minetest.add_entity(pos, "worldeditadditions:position")
local entity = minetest.add_entity(pos, "worldeditadditions:position", minetest.write_json({
id = last_reset,
display_number = display_number,
player_name = player_name
}))
entity:get_luaentity().player_name = player_name
entity:get_luaentity().display_number = display_number
-- entity:get_luaentity().player_name = player_name
-- entity:get_luaentity().display_number = display_number
anchor.set_number(entity, display_number)
-- anchor.set_number(entity, display_number)
anchor:emit("create", {
player_name = player_name,
@ -53,11 +92,13 @@ local function create(player_name, pos, display_number)
end
local function delete(entity)
if not entity.get_luaentity or not entity:get_luaentity() then return end -- Ensure the entity is still valid
if not entity or not entity.get_luaentity or not entity:get_luaentity() then return end -- Ensure the entity is still valid
local player_name = entity:get_luaentity().player_name
local display_number = entity:get_luaentity().display_number
last_reset = make_id()
entity:remove()
anchor:emit("delete", {
@ -117,5 +158,5 @@ anchor = EventEmitter.new({
delete = delete,
set_number = set_number
})
anchor.debug = true
return anchor

View file

@ -7,7 +7,12 @@ local anchor
local entity_wall_size = 10
local collision_thickness = 0.2
local last_reset = tostring(wea_c.get_ms_time())
local function make_id()
return tostring(wea_c.get_ms_time()) .. "_" .. tostring(math.floor(math.random() * 1000000))
end
local last_reset = make_id()
local WEAPositionMarkerWall = {
initial_properties = {
@ -17,7 +22,7 @@ local WEAPositionMarkerWall = {
-- ^^ { xmin, ymin, zmin, xmax, ymax, zmax } relative to obj pos
physical = false,
collide_with_objects = false,
static_save = false,
hp_max = 1,
textures = {
"worldeditadditions_core_marker_wall.png",
@ -30,18 +35,41 @@ local WEAPositionMarkerWall = {
},
on_activate = function(self, staticdata)
if staticdata ~= last_reset then
-- print("DEBUG:marker_wall/remove staticdata", staticdata, "last_reset", last_reset)
local data = minetest.parse_json(staticdata)
if type(data) ~= "table" or data.id ~= last_reset then
self.object:remove()
-- else
-- print("DEBUG:marker_wall/ok staticdata", staticdata, "type", type(staticdata), "last_reset", last_reset, "type", type(last_reset))
return
end
self.__id = data.id
self._size = Vector3.clone(data.size)
self._side = data.side
self.player_name = data.player_name
anchor.__single_setup(self.object, self._size, self._side)
anchor:emit("update_entity", {
entity = self.object,
player_name = self.player_name
})
end,
on_punch = function(self, _)
print("DEBUG:pos_marker_wall on_punch")
anchor.delete(self)
-- Only unmark the rest of the walls
-- Unmark for the player that created this wall.... NOT the player who punched it!
wea_c.pos.unmark(self.player_name, false, true)
end,
on_blast = function(self, damage)
return false, false, {} -- Do not damage or knockback the player
end,
get_staticdata = function(self)
return minetest.write_json({
id = self.__id,
size = self._size,
side = self._side,
player_name = self.player_name
})
end
}
@ -109,12 +137,17 @@ local function create_single(player_name, pos1, pos2, side)
local pos_centre = ((pos2 - pos1) / 2) + pos1
local entity = minetest.add_entity(pos_centre, "worldeditadditions:marker_wall", last_reset)
local entity = minetest.add_entity(pos_centre, "worldeditadditions:marker_wall", minetest.write_json({
id = last_reset,
size = pos2 - pos1,
side = side,
player_name = player_name
}))
-- print("DEBUG:marker_wall create_single --> START player_name", player_name, "pos1", pos1, "pos2", pos2, "side", side, "SPAWN", pos_centre, "last_reset", last_reset)
entity:get_luaentity().player_name = player_name
-- entity:get_luaentity().player_name = player_name
single_setup(entity, pos2 - pos1, side)
-- single_setup(entity, pos2 - pos1, side)
return entity
end
@ -438,7 +471,7 @@ local function delete(entitylist)
entity:remove()
end
last_reset = tostring(wea_c.get_ms_time())
last_reset = make_id()
-- print("DEBUG:marker_wall delete --> LAST_RESET is now", last_reset, "type", type(last_reset))
anchor:emit("delete", {
@ -450,7 +483,8 @@ end
anchor = EventEmitter.new({
create = create_wall,
delete = delete
delete = delete,
__single_setup = single_setup
})
return anchor

View file

@ -33,7 +33,7 @@ local anchor = nil
--- It is requested that all position/region marker UI elements be hidden for the given player.
-- @event unmark
-- @format { player_name: string }
-- @format { player_name: string, markers: bool, walls: bool }
--- It is requested that all position/region marker UI elements be shown once more for the given player.
-- @event mark
@ -268,15 +268,24 @@ end
--- Hides the visual markers for the given player's positions and defined region, but does not clear the points.
-- @param player_name string The name of the player to operate on.
local function unmark(player_name)
-- @param markers=true bool Whether to hide positional markers.
-- @param walls=true bool Whether to hide the marker walls.
-- @returns void
local function unmark(player_name, markers, walls)
if markers == nil then markers = true end
if walls == nil then walls = true end
anchor:emit("unmark", {
player_name = player_name
player_name = player_name,
markers = markers,
walls = walls
})
end
--- Shows the visual markers for the given player's positions and defined region once more.
-- Often used some time after calling worldeditadditions_core.pos.unmark().
-- @param player_name string The name of the player to operate on.
-- @returns void
local function mark(player_name)
anchor:emit("mark", {
player_name = player_name

View file

@ -92,8 +92,9 @@ end)
wea_c.pos:addEventListener("unmark", function(event)
ensure_player(event.player_name)
do_delete_all(event.player_name)
if event.markers then
do_delete_all(event.player_name)
end
-- Note that this function is NOT WorldEdit compatible, because it is only called through our override of WorldEdit's `//unmark`, and WorldEdit doesn't have an API function to call to unmark and everything is complicated.
end)
@ -110,3 +111,11 @@ wea_c.pos:addEventListener("mark", function(event)
})
end
end)
wea_c.entities.pos_marker:addEventListener("update_entity", function(event)
wea_c.entities.pos_marker.delete(
position_entities[event.player_name][event.i]
)
position_entities[event.player_name][event.i] = event.entity
end)

View file

@ -53,6 +53,26 @@ local function do_update(event)
end
local function garbage_collect(player_name)
if not wall_entity_lists[player_name] then return end -- Nothing to do
for i, entity in ipairs(wall_entity_lists[player_name]) do
if not entity:get_pos() then
table.remove(wall_entity_lists[player_name], i)
end
end
end
local function update_entity(event)
print("DEBUG:pos_marker_wall_manage UPDATE_ENTITY event", weac.inspect(event))
garbage_collect(event.player_name)
ensure_player(event.player_name)
table.insert(
wall_entity_lists[event.player_name],
event.entity
)
end
local function needs_update(event)
if event.i > 2 then
@ -65,11 +85,16 @@ local function handle_event(event)
if needs_update(event) then do_update(event) end
end
local function handle_unmark(event)
if event.walls then do_delete(event) end
end
weac.pos:addEventListener("set", handle_event)
weac.pos:addEventListener("pop", handle_event)
weac.pos:addEventListener("push", handle_event)
weac.pos:addEventListener("clear", do_delete)
weac.pos:addEventListener("unmark", do_delete)
weac.pos:addEventListener("unmark", handle_unmark)
weac.pos:addEventListener("mark", do_update)
weac.entities.pos_marker_wall:addEventListener("update_entity", update_entity)

View file

@ -1,6 +1,6 @@
--- WorldEditAdditions-Core
-- @namespace worldeditadditions_core
-- @release 1.14.1
-- @release 1.14.5
-- @copyright 2021 Starbeamrainbowlabs and VorTechnix
-- @license Mozilla Public License, 2.0
-- @author Starbeamrainbowlabs and VorTechnix

View file

@ -58,8 +58,12 @@ end
-- @param event_name string The name of the event to emit.
-- @param args table|any The argument(s) to pass to listener functions. It is strongly advised you pass a table here.
function EventEmitter.emit(this, event_name, args)
if this.debug then
listeners = 0
if this.events[event_name] ~= nil then listeners = #this.events[event_name] end
print("DEBUG:EventEmitter emit", event_name, "listeners", listeners, "args", wea_c.inspect(args))
end
if this.events[event_name] == nil then return end
if this.debug then print("DEBUG:EventEmitter emit", event_name, "args", wea_c.inspect(args)) end
for index,next_func in ipairs(this.events[event_name]) do
next_func(args)