Include WorldEdit GUI in the documentation, improve privilege handling, simplify main dialog.

This commit is contained in:
Uberi 2013-12-18 15:56:50 -05:00
parent 36424e3dec
commit 3767ea84d2
5 changed files with 169 additions and 55 deletions

View File

@ -8,6 +8,13 @@ For more information, see the [forum topic](https://forum.minetest.net/viewtopic
Installing
----------
In order to use the WorldEdit GUI, you must have one of the following mods installed:
* [Unified Inventory](https://forum.minetest.net/viewtopic.php?id=3933) (RECOMMENDED)
* [Inventory++](https://forum.minetest.net/viewtopic.php?id=6204)
Installation of Unified Inventory is highly recommended. If neither of these mods are installed, the WorldEdit GUI will not be available, though the rest of WorldEdit will work fine.
If you are using Windows, consider installing this mod using [MODSTER](https://forum.minetest.net/viewtopic.php?id=6497), a super simple mod installer that will take care of everything for you. If you are using MODSTER, skip directly to step 6 in the instructions below.
There is a nice installation guide over at the [Minetest Wiki](http://wiki.minetest.com/wiki/Installing_mods). Here is a short summary:
@ -26,24 +33,30 @@ If you are having trouble, try asking for help in the [IRC channel](http://webch
Usage
-----
WorldEdit works primarily through chat commands. Depending on your key bindings, you can invoke chat entry with the "t" key, and open the chat console with the "F10" key.
WorldEdit works primarily through the WorldEdit GUI and chat commands. Depending on your key bindings, you can invoke chat entry with the "t" key, and open the chat console with the "F10" key.
WorldEdit has a huge potential for abuse by untrusted players. Therefore, users will not be able to use WorldEdit unless they have the "worldedit" privelege. This is available by default in single player, but in multiplayer the permission must be explicitly given by someone with the right credentials, using the follwoing chat command: `/grant <player name> worldedit`. This privelege can later be removed using the following chat command: `/revoke <player name> worldedit`.
WorldEdit has a huge potential for abuse by untrusted players. Therefore, users will not be able to use WorldEdit unless they have the `worldedit` privelege. This is available by default in single player, but in multiplayer the permission must be explicitly given by someone with the right credentials, using the follwoing chat command: `/grant <player name> worldedit`. This privelege can later be removed using the following chat command: `/revoke <player name> worldedit`.
Certain functions/commands such as WorldEdit GUI's "Run Lua" (equivalent to the `//lua` chat command) additionally require the `server` privilege. This is because it is extremely dangerous to give access to these commands to untrusted players, since they essentially are able to control the computer the server is running on. Give this privilege only to people you trust with your computer.
For in-game information about these commands, type `/help <command name>` in the chat. For example, to learn more about the `//copy` command, simply type `/help /copy` to display information relevant to copying a region.
Chat Commands
-------------
WorldEdit is accessed in-game through an interface. By default, the mod distribution includes a chat interface for this purpose. It is documented in the [Chat Commands Reference](Chat Commands.md).
Interface
---------
WorldEdit is accessed in-game in two main ways.
If visual manipulation of nodes is desired, the [WorldEdit GUI](https://forum.minetest.net/viewtopic.php?id=3112) mod provides a simple interface with buttons and text entry fields for this purpose.
The GUI adds a screen to each player's inventory that gives access to various WorldEdit functions. The [tutorial](Tutorial.md) and the [Chat Commands Reference](Chat Commands.md) may be helpful in learning to use it.
The chat interface adds many chat commands that perform various WorldEdit powered tasks. It is documented in the [Chat Commands Reference](Chat Commands.md).
Compatibility
-------------
This mod supports Minetest versions 0.4.8 and newer. Older versions of WorldEdit may work with older versions of Minetest, but are not recommended.
This mod supports Minetest versions 0.4.8 and newer. Older versions of WorldEdit may work with older versions of Minetest, but are not recommended or supported.
WorldEdit works quite well with other mods, and does not have any known mod conflicts.
WorldEdit GUI requires either [Unified Inventory](https://forum.minetest.net/viewtopic.php?id=3933) or [Inventory++](https://forum.minetest.net/viewtopic.php?id=6204) to be installed in order to use it. This is optional but highly recommended.
WorldEdit API
-------------
WorldEdit exposes all significant functionality in a simple Lua interface. Adding WorldEdit to the file "depends.txt" in your mod gives you access to all of the `worldedit` functions. The API is useful for tasks such as high-performance node manipulation, alternative interfaces, and map creation.
@ -58,11 +71,13 @@ This API is documented in the [WorldEdit API Reference](WorldEdit API.md).
Axes
----
The coordinate system is the same as that used by MineTest; Y is upwards, X is perpendicular, and Z is parallel.
The coordinate system is the same as that used by Minetest; positive Y is upwards, positive X is rightwards, and positive Z is forwards, if a player is facing North (positive Z axis).
When an axis is specified in a WorldEdit command, it is specified as one of the following values: x, y, z, or ?.
When an axis is specified in a WorldEdit chat command, it is specified as one of the following values: `x`, `y`, `z`, or `?`.
The value ? represents the axis the player is currently facing. If the player is facing more than one axis, the axis the player face direction is closest to will be used.
In the GUI, there is a dropdown menu for this purpose. The "Look direction" option has the same effect as `?` does in chat commands.
The value `?` represents the axis the player is currently facing. If the player is facing more than one axis, the axis the player face direction is closest to will be used.
Nodes
-----
@ -111,7 +126,7 @@ The current version of the WorldEdit Schematic format, internally known as versi
<...>
}
Value ordering and minor aspects of the syntax, such as trailing commas or newlines, are not guaranteed.
The ordering of the values and minor aspects of the syntax, such as trailing commas or newlines, are not guaranteed to stay the same in future versions.
The WorldEdit Schematic format is accessed via the WorldEdit API, or WorldEdit serialization chat commands such as `//serialize` and `//deserialize`.

View File

@ -9,27 +9,51 @@ Let's start with a few assumptions:
* You have WorldEdit installed as a mod.
* If using Windows, [MODSTER](https://forum.minetest.net/viewtopic.php?pid=101463) makes installing mods totally painless.
* Simply download the file, extract the archive, and move it to the correct mod folder for Minetest.
* If you want to use the WorldEdit GUI, you have installed either [Unified Inventory](https://forum.minetest.net/viewtopic.php?id=3933) (recommended), or [Inventory++](https://forum.minetest.net/viewtopic.php?id=6204).
* See the installation instructions in [README](README.md) if you need more details.
* You are familiar with the basics of the game.
* How to walk, jump, and climb.
* How to dig, place, and punch blocks.
* How to type into the chat and read text from it.
* One of the following:
* How to type into the chat and read text from it.
* How to open the inventory screen and press buttons on it.
Overview
--------
WorldEdit has a "region", which is simply a cuboid area defined by two markers, both of which the player can move around. Every player can have their own region with their own two markers.
WorldEdit chat commands can work inside the region selected, or around the first marker.
WorldEdit GUI buttons and chat commands generally work inside the region selected, or around the first marker.
If you are using the chat commands, follow the steps under **Chat Commands**. If you are using the WorldEdit GUI, follow the steps under **WorldEdit GUI**.
Step 1: Selecting a region
--------------------------
### Chat Commands
In the chat prompt, enter `//p set`. In the chat, you are prompted to punch two nodes to set the positions of the two markers.
Punch a nearby node. Be careful of breakable ones such as torches. A black cube reading "1" will appear around the node. This is the marker for WorldEdit position 1.
Walk away from the node you just punched. Now, punch another node. A black cube reading "2" will appear around the node. This is the marker for WorldEdit position 2.
### WorldEdit GUI
Open the main WorldEdit GUI from your inventory screen.
Press the "Get/Set Positions" button. On the new screen, press the "Set Position 1" button. The inventory screen should close.
Punch a nearby node. Be careful of breakable ones such as torches. A black cube reading "1" will appear around the node. This is the marker for WorldEdit position 1.
Walk away from the node you just punched. Open your inventory again. It should be on the same page as it was before.
Press the "Set Position 2" button. The inventory screen should close.
Now, punch another node. A black cube reading "2" will appear around the node. This is the marker for WorldEdit position 2.
Step 2: Region commands
-----------------------
### Chat Commands
In the chat prompt, enter `//set mese`. In the chat, you will see a message showing the number of nodes set after a small delay.
Look at the place between the two markers: it is now filled with MESE blocks!
@ -38,18 +62,60 @@ The `//set <node>` command fills the region with whatever node you want. It is a
Now, try a few different variations, such as `//set torch`, `//set cobble`, and `//set water`.
### WorldEdit GUI
Open the main WorldEdit GUI from your inventory screen.
Press the "Set Nodes" button. You should see a new screen with various options for setting nodes.
Enter "mese" in the "Name" field. Press Search if you would like to see what the node you just entered looks like.
Press the "Set Nodes" button on this screen. In the chat, you will see a message showing the number of nodes set after a small delay.
Look at the place between the two markers: it is now filled with MESE blocks!
The "Set Nodes" function fills the region with whatever node you want. It is a region-oriented command, which means it works inside the WorldEdit region only.
Now, try a few different variations on the node name, such as "torch", "cobble", and "water".
Step 3: Position commands
-------------------------
### Chat Commands
In the chat prompt, enter `//hollowdome 30 glass`. In the chat, you will see a message showing the number of nodes set after a small delay.
Look around marker 1: it is now surrounded by a hollow glass dome!
The `//hollowdome <radius> <node>` command creates a hollow dome centered around marker 1, made of any node you want. It is a position-oriented command, which means it works around marker 1 and can go outside the WorldEdit region.
### WorldEdit GUI
Open the main WorldEdit GUI from your inventory screen.
Press the "Sphere/Dome" button. You should see a new screen with various options for making spheres or domes.
Enter "glass" in the "Name" field. Press Search if you would like to see what the node you just entered looks like.
Enter "30" in the "Radius" field.
Press the "Hollow Dome" button on this screen. In the chat, you will see a message showing the number of nodes added after a small delay.
Look around marker 1: it is now surrounded by a hollow glass dome!
The "Hollow Dome" function creates a hollow dome centered around marker 1, made of any node you want. It is a position-oriented command, which means it works around marker 1 and can go outside the WorldEdit region.
Step 4: Other commands
----------------------
### Chat Commands
There are many more commands than what is shown here. See the [Chat Commands Reference](Chat Commands.md) for a detailed list of them, along with descriptions and examples for every single one.
If you're in-game and forgot how a command works, just use the `/help <command name>` command, without the first forward slash. For example, to see some information about the `//set <node>` command mentioned earlier, simply use `/help /set`.
A very useful command to check out is the `//save <schematic>` command, which can save everything inside the WorldEdit region to a file, stored on the computer hosting the server (the player's computer, in single player mode). You can then later use `//load <schematic>` to load the data in a file into a world, even another world on another computer.
A very useful command to check out is the `//save <schematic>` command, which can save everything inside the WorldEdit region to a file, stored on the computer hosting the server (the player's computer, in single player mode). You can then later use `//load <schematic>` to load the data in a file into a world, even another world on another computer.
### WorldEdit GUI
This only scratches the surface of what WorldEdit is capable of. Most of the functions in the WorldEdit GUI correspond to chat commands, and so the [Chat Commands Reference](Chat Commands.md) may be useful if you get stuck.
It is helpful to explore the various buttons in the interface and check out what they do. Learning the chat command interface is also useful if you use WorldEdit intensively - an experienced chat command user can usually work faster than an experienced WorldEdit GUI user.

View File

@ -1,5 +1,7 @@
minetest.register_privilege("worldedit", "Can use WorldEdit commands")
--wip: fold the hollow stuff into the main functions and add a hollow flag at the end, then add the compatibility stuff
worldedit.set_pos = {}
worldedit.inspect = {}

View File

@ -1,3 +1,4 @@
worldedit
worldedit_commands
unified_inventory?
inventory_plus?

View File

@ -21,49 +21,62 @@ local axis_values = {"x", "y", "z", "?"}
setmetatable(axis_indices, {__index = function () return 4 end})
setmetatable(axis_values, {__index = function () return "?" end})
local register_gui_chatcommand = function(identifier, name, command, callback)
callback = callback or function(name, command) command(name, "") end
worldedit.register_gui_function(identifier, {
name = name,
privs = minetest.chatcommands[command].privs,
on_select = function(name)
return callback(name, minetest.chatcommands[command].func)
end,
})
--given multiple sets of privileges, produces a single set of privs that would have the same effect as requiring all of them at the same time
local combine_privs = function(...)
local result = {}
for i, privs in ipairs({...}) do
for name, value in pairs(privs) do
if result[name] ~= nil and result[name] ~= value then --the priv must be both true and false, which can never happen
return {__fake_priv_that_nobody_has__=true} --priviledge table that can never be satisfied
end
result[name] = value
end
end
return result
end
register_gui_chatcommand("worldedit_gui_about", "About", "/about")
register_gui_chatcommand("worldedit_gui_inspect", "Toggle Inspection", "/inspect", function(name, command)
command(name, worldedit.inspect[name] and "disable" or "enable")
end)
register_gui_chatcommand("worldedit_gui_reset", "Reset Region", "/reset")
register_gui_chatcommand("worldedit_gui_mark", "Mark Region", "/mark")
register_gui_chatcommand("worldedit_gui_unmark", "Unmark Region", "/unmark")
worldedit.register_gui_function("worldedit_gui_about", {
name = "About", privs = minetest.chatcommands["/about"].privs,
on_select = function(name)
minetest.chatcommands["/about"].func(name, "")
end,
})
worldedit.register_gui_function("worldedit_gui_p", {
name = "Get/Set Positions", privs = minetest.chatcommands["/p"].privs,
worldedit.register_gui_function("worldedit_gui_inspect", {
name = "Toggle Inspect", privs = minetest.chatcommands["/inspect"].privs,
on_select = function(name)
minetest.chatcommands["/inspect"].func(name, worldedit.inspect[name] and "disable" or "enable")
end,
})
worldedit.register_gui_function("worldedit_gui_region", {
name = "Get/Set Region", privs = combine_privs(minetest.chatcommands["/p"].privs, minetest.chatcommands["/pos1"].privs, minetest.chatcommands["/pos2"].privs, minetest.chatcommands["/reset"].privs, minetest.chatcommands["/mark"].privs, minetest.chatcommands["/unmark"].privs, minetest.chatcommands["/volume"].privs, minetest.chatcommands["/fixedpos"].privs),
get_formspec = function(name)
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
return "size[9,6]" .. worldedit.get_formspec_header("worldedit_gui_p") ..
return "size[9,7]" .. worldedit.get_formspec_header("worldedit_gui_region") ..
"button_exit[0,1;3,0.8;worldedit_gui_p_get;Get Positions]" ..
"button_exit[3,1;3,0.8;worldedit_gui_p_set1;Choose Position 1]" ..
"button_exit[6,1;3,0.8;worldedit_gui_p_set2;Choose Position 2]" ..
"button_exit[0,2;3,0.8;worldedit_gui_pos1;Position 1 Here]" ..
"button_exit[3,2;3,0.8;worldedit_gui_pos2;Position 2 Here]" ..
"label[0,3.7;Position 1]" ..
string.format("field[2,4;1.5,0.8;worldedit_gui_fixedpos_pos1x;X ;%s]", pos1 and pos1.x or "") ..
string.format("field[3.5,4;1.5,0.8;worldedit_gui_fixedpos_pos1y;Y ;%s]", pos1 and pos1.y or "") ..
string.format("field[5,4;1.5,0.8;worldedit_gui_fixedpos_pos1z;Z ;%s]", pos1 and pos1.z or "") ..
"button_exit[6.5,3.68;2.5,0.8;worldedit_gui_fixed_pos1_submit;Set Position 1]" ..
"label[0,5.2;Position 2]" ..
string.format("field[2,5.5;1.5,0.8;worldedit_gui_fixedpos_pos2x;X ;%s]", pos2 and pos2.x or "") ..
string.format("field[3.5,5.5;1.5,0.8;worldedit_gui_fixedpos_pos2y;Y ;%s]", pos2 and pos2.y or "") ..
string.format("field[5,5.5;1.5,0.8;worldedit_gui_fixedpos_pos2z;Z ;%s]", pos2 and pos2.z or "") ..
"button_exit[6.5,5.18;2.5,0.8;worldedit_gui_fixed_pos2_submit;Set Position 2]"
"button_exit[6,2;3,0.8;worldedit_gui_reset;Reset Region]" ..
"button_exit[0,3;3,0.8;worldedit_gui_mark;Mark Region]" ..
"button_exit[3,3;3,0.8;worldedit_gui_unmark;Unmark Region]" ..
"button_exit[6,3;3,0.8;worldedit_gui_volume;Region Volume]" ..
"label[0,4.7;Position 1]" ..
string.format("field[2,5;1.5,0.8;worldedit_gui_fixedpos_pos1x;X ;%s]", pos1 and pos1.x or "") ..
string.format("field[3.5,5;1.5,0.8;worldedit_gui_fixedpos_pos1y;Y ;%s]", pos1 and pos1.y or "") ..
string.format("field[5,5;1.5,0.8;worldedit_gui_fixedpos_pos1z;Z ;%s]", pos1 and pos1.z or "") ..
"button_exit[6.5,4.68;2.5,0.8;worldedit_gui_fixed_pos1_submit;Set Position 1]" ..
"label[0,6.2;Position 2]" ..
string.format("field[2,6.5;1.5,0.8;worldedit_gui_fixedpos_pos2x;X ;%s]", pos2 and pos2.x or "") ..
string.format("field[3.5,6.5;1.5,0.8;worldedit_gui_fixedpos_pos2y;Y ;%s]", pos2 and pos2.y or "") ..
string.format("field[5,6.5;1.5,0.8;worldedit_gui_fixedpos_pos2z;Z ;%s]", pos2 and pos2.z or "") ..
"button_exit[6.5,6.18;2.5,0.8;worldedit_gui_fixed_pos2_submit;Set Position 2]"
end,
})
worldedit.register_gui_handler("worldedit_gui_p", function(name, fields)
worldedit.register_gui_handler("worldedit_gui_region", function(name, fields)
if fields.worldedit_gui_p_get then
minetest.chatcommands["/p"].func(name, "get")
return true
@ -75,32 +88,46 @@ worldedit.register_gui_handler("worldedit_gui_p", function(name, fields)
return true
elseif fields.worldedit_gui_pos1 then
minetest.chatcommands["/pos1"].func(name, "")
worldedit.show_page(name, "worldedit_gui_p")
worldedit.show_page(name, "worldedit_gui_region")
return true
elseif fields.worldedit_gui_pos2 then
minetest.chatcommands["/pos2"].func(name, "")
worldedit.show_page(name, "worldedit_gui_p")
worldedit.show_page(name, "worldedit_gui_region")
return true
elseif fields.worldedit_gui_reset then
minetest.chatcommands["/reset"].func(name, "")
worldedit.show_page(name, "worldedit_gui_region")
return true
elseif fields.worldedit_gui_mark then
minetest.chatcommands["/mark"].func(name, "")
worldedit.show_page(name, "worldedit_gui_region")
return true
elseif fields.worldedit_gui_unmark then
minetest.chatcommands["/unmark"].func(name, "")
worldedit.show_page(name, "worldedit_gui_region")
return true
elseif fields.worldedit_gui_volume then
minetest.chatcommands["/volume"].func(name, "")
worldedit.show_page(name, "worldedit_gui_region")
return true
elseif fields.worldedit_gui_fixedpos_pos1_submit then
minetest.chatcommands["/fixedpos"].func(name, string.format("set1 %s %s %s",
tostring(fields.worldedit_gui_fixedpos_pos1x),
tostring(fields.worldedit_gui_fixedpos_pos1y),
tostring(fields.worldedit_gui_fixedpos_pos1z)))
worldedit.show_page(name, "worldedit_gui_p")
worldedit.show_page(name, "worldedit_gui_region")
return true
elseif fields.worldedit_gui_fixedpos_pos2_submit then
minetest.chatcommands["/fixedpos"].func(name, string.format("set2 %s %s %s",
tostring(fields.worldedit_gui_fixedpos_pos2x),
tostring(fields.worldedit_gui_fixedpos_pos2y),
tostring(fields.worldedit_gui_fixedpos_pos2z)))
worldedit.show_page(name, "worldedit_gui_p")
worldedit.show_page(name, "worldedit_gui_region")
return true
end
return false
end)
register_gui_chatcommand("worldedit_gui_volume", "Region Volume", "/volume")
worldedit.register_gui_function("worldedit_gui_set", {
name = "Set Nodes", privs = minetest.chatcommands["/set"].privs,
get_formspec = function(name)
@ -128,7 +155,7 @@ worldedit.register_gui_handler("worldedit_gui_set", function(name, fields)
end)
worldedit.register_gui_function("worldedit_gui_replace", {
name = "Replace Nodes", privs = minetest.chatcommands["/replace"].privs,
name = "Replace Nodes", privs = combine_privs(minetest.chatcommands["/replace"].privs, minetest.chatcommands["/replaceinverse"].privs),
get_formspec = function(name)
local search, replace = gui_nodename1[name], gui_nodename2[name]
local search_nodename, replace_nodename = worldedit.normalize_nodename(search), worldedit.normalize_nodename(replace)
@ -163,7 +190,7 @@ worldedit.register_gui_handler("worldedit_gui_replace", function(name, fields)
end)
worldedit.register_gui_function("worldedit_gui_sphere_dome", {
name = "Sphere/Dome", privs = minetest.chatcommands["/sphere"].privs,
name = "Sphere/Dome", privs = combine_privs(minetest.chatcommands["/hollowsphere"].privs, minetest.chatcommands["/sphere"].privs, minetest.chatcommands["/hollowdome"].privs, minetest.chatcommands["/dome"].privs),
get_formspec = function(name)
local node, radius = gui_nodename1[name], gui_distance2[name]
local nodename = worldedit.normalize_nodename(node)
@ -202,7 +229,7 @@ worldedit.register_gui_handler("worldedit_gui_sphere_dome", function(name, field
end)
worldedit.register_gui_function("worldedit_gui_cylinder", {
name = "Cylinder", privs = minetest.chatcommands["/cylinder"].privs,
name = "Cylinder", privs = combine_privs(minetest.chatcommands["/hollowcylinder"].privs, minetest.chatcommands["/cylinder"].privs),
get_formspec = function(name)
local node, axis, length, radius = gui_nodename1[name], gui_axis[name], gui_distance1[name], gui_distance2[name]
local nodename = worldedit.normalize_nodename(node)
@ -300,7 +327,7 @@ worldedit.register_gui_handler("worldedit_gui_spiral", function(name, fields)
end)
worldedit.register_gui_function("worldedit_gui_copy_move", {
name = "Copy/Move", privs = minetest.chatcommands["/move"].privs,
name = "Copy/Move", privs = combine_privs(minetest.chatcommands["/copy"].privs, minetest.chatcommands["/move"].privs),
get_formspec = function(name)
local axis = gui_axis[name] or 4
local amount = gui_distance1[name] or "10"
@ -345,4 +372,7 @@ worldedit.register_gui_handler("worldedit_gui_formspec_tester", function(name, f
return true
end
return false
end)
end)
--wip: those other commands
--wip: Run Lua and Lua Transform