Make PaintBrush tool work with WorldEdit region, add "//pbrush" console command.

master
whats_his_face 2022-03-19 10:42:47 -05:00
parent a31982b3d4
commit c4920d2e0b
6 changed files with 150 additions and 2 deletions

View File

@ -25,6 +25,7 @@ local function load_module(path)
end
dofile(path .. "/common.lua")
dofile(path .. "/math.lua")
load_module(path .. "/manipulations.lua")
load_module(path .. "/primitives.lua")
load_module(path .. "/visualization.lua")

View File

@ -3,7 +3,6 @@
local mh = worldedit.manip_helpers
--- Sets a region to `node_names`.
-- @param pos1
-- @param pos2
@ -62,6 +61,33 @@ function worldedit.set_param2(pos1, pos2, param2)
return worldedit.volume(pos1, pos2)
end
--- Changes param2 by a constant value for each node in a region.
-- @param pos1
-- @param pos2
-- @param delta Param2 value to add to each node
-- @return The number of nodes set.
function worldedit.add_param2(pos1, pos2, delta)
pos1, pos2 = worldedit.sort_pos(pos1, pos2)
local manip, area = mh.init(pos1, pos2)
local param2_data = manip:get_param2_data()
local new_p2 = 0
-- Add delta to every node
for i in area:iterp(pos1, pos2) do
new_p2 = math.mod(param2_data[i] + delta, 256)
if new_p2 < 0 then new_p2 = new_p2 + 256 end
param2_data[i] = new_p2
end
-- Update map
manip:set_param2_data(param2_data)
manip:write_to_map()
manip:update_map()
return worldedit.volume(pos1, pos2)
end
--- Replaces all instances of `search_node` with `replace_node` in a region.
-- When `inverse` is `true`, replaces all instances that are NOT `search_node`.
-- @return The number of nodes replaced.

View File

@ -0,0 +1,13 @@
math.mod = function(value, m)
if value < 0 then
while value < -m do
value = value + m
end
elseif value > m then
while value > m do
value = value - m
end
end
return value
end

View File

@ -589,6 +589,40 @@ worldedit.register_command("param2", {
end,
})
--[[
//pbrush: special command for the "Traitor" game.
Simulates using Traitor's "PaintBrush" tool on a WorldEdit region.
]]--
worldedit.register_command("pbrush", {
params = "+ / - / [+/-]<steps>",
description = minetest.formspec_escape(
"Increase/decrease the color tone of all suitable nodes in the current WorldEdit region.\n"
.. "Suitable nodes are those that can be colored using the PaintBrush tool "
.. "(e.g. the blocks in the 'color' namespace).\n"
.. "Using + or - changes the color once; use <steps> for multiple steps.\n"
.. "Note that <steps> should be at most 7, higher values are ignored."),
privs = {worldeditor=true, creative=true},
require_pos = 2,
parse = function(param)
local found, _, sign, steps = param:find("([+-]?)(%d?)")
local delta = 32
if found == nil then return false end
if steps ~= nil and steps ~= "" then
local count = math.mod(tonumber(steps), 8)
delta = 32 * count
end
if sign == "-" then delta = -delta end
return true, delta
end,
nodes_needed = check_region,
func = function(name, delta)
local count = worldedit.add_param2(worldedit.pos1[name], worldedit.pos2[name], delta)
worldedit.player_notify(name, count .. " nodes altered")
end,
})
worldedit.register_command("mix", {
params = "<node1> [count1] <node2> [count2] ...",
description = "Fill the current WorldEdit region with a random mix of <node1>, ...",

View File

@ -123,6 +123,48 @@ worldedit.marker_update = function(name)
worldedit.mark_region(name)
end
--[[
Determines if the thing currently being pointed at is one of the following:
- one of the Worldedit position boxes to delimit a Worldedit region
- one of the special cubes that Worldedit puts at certain nodes to
visualize the bounds of a selection region
The function uses knowledge about the internal structure of the Worldedit
regions. Also, it uses the API function "ObjectRef:get_entity_name" to
determine the registered names of the object pointed at. However, the
documentation states that this function will be removed in the future[1].
--------------------------------------------------------------------------
[1] https://minetest.gitlab.io/minetest/class-reference/#objectref
--]]
worldedit.is_marker_region = function(pointed_thing)
if pointed_thing ~= nil and pointed_thing.type ~= nil then
if pointed_thing.type == 'object' and pointed_thing.ref ~= nil then
local ref = pointed_thing.ref
if ref.get_entity_name ~= nil then
local objname = ref:get_entity_name()
if objname == 'worldedit:region_cube' or
objname == 'worldedit:pos1' or
objname == 'worldedit:pos2' then
return true
end
end
end
end
return false
end
--[[
Returns true if `user` is the owner of the Worldedit marker region
currently being pointed at.
--]]
worldedit.is_region_owner = function(pointed_thing, user)
local region_ref = pointed_thing.ref
local region_entity = region_ref:get_luaentity()
return (user == region_entity.player_name)
end
minetest.register_entity(":worldedit:pos1", {
initial_properties = {
visual = "cube",

View File

@ -9,6 +9,15 @@ local function register_color(name)
})
end
local function region_add_delta(pos1, pos2, player, delta)
if minetest.is_protected(pos1, player) or minetest.is_protected(pos2, player) then
minetest.debug('*** you are trying to paint in a protected region, '
.. player .. '!')
else
worldedit.add_param2(pos1, pos2, delta)
end
end
register_color('black')
register_color('white')
@ -27,8 +36,18 @@ minetest.register_tool('color:brush', {
end
end,
on_use = function(itemstack, user, pointed_thing)
if pointed_thing.type ~= 'node' then return end
local player = user:get_player_name()
if worldedit.is_marker_region(pointed_thing) then
if worldedit.is_region_owner(pointed_thing, player) then
if worldedit.pos1[player] ~= nil and worldedit.pos2[player] ~= nil then
local pos1 = worldedit.pos1[player]
local pos2 = worldedit.pos2[player]
region_add_delta(pos1, pos2, player, 32)
end
end
return nil
end
if pointed_thing.type ~= 'node' then return end
local pos = minetest.get_pointed_thing_position(pointed_thing)
local node = minetest.get_node(pos)
if minetest.get_item_group(node.name, 'stainable') > 0 then
@ -37,6 +56,19 @@ minetest.register_tool('color:brush', {
end
end
end,
on_secondary_use = function(itemstack, user, pointed_thing)
local player = user:get_player_name()
if worldedit.is_marker_region(pointed_thing) then
if worldedit.is_region_owner(pointed_thing, player) then
if worldedit.pos1[player] ~= nil and worldedit.pos2[player] ~= nil then
local pos1 = worldedit.pos1[player]
local pos2 = worldedit.pos2[player]
region_add_delta(pos1, pos2, player, -32)
end
end
end
return nil
end,
})
color.make_darker = function(pos, node, puncher, pointed_thing)