Completion Part 5
Why is writing documentation so hard?
This commit is contained in:
parent
661889b852
commit
6ff1da5595
191
Manual.md
191
Manual.md
@ -8,28 +8,28 @@ of Minetest.
|
|||||||
|
|
||||||
MapEditr reads and edits *map databases*, usually a file named `map.sqlite`
|
MapEditr reads and edits *map databases*, usually a file named `map.sqlite`
|
||||||
within each Minetest world directory. As such, the terms "world" and "map" may
|
within each Minetest world directory. As such, the terms "world" and "map" may
|
||||||
be used interchangeably.
|
be used interchangeably. Note that only SQLite format maps are currently
|
||||||
|
supported.
|
||||||
|
|
||||||
For most commands to work, the areas of the map to be read/modified must
|
For most commands to work, the parts of the map to be read/modified must
|
||||||
already be generated. This can be done by either exploring the area in-game,
|
already be generated. This can be done by either exploring the area in-game,
|
||||||
or by using Minetest's built-in `/emergeblocks` command.
|
or by using Minetest's built-in `/emergeblocks` command.
|
||||||
|
|
||||||
MapEditr supports all maps created since Minetest version 0.4.2-rc1, released
|
MapEditr supports all maps created since Minetest version 0.4.2-rc1, released
|
||||||
July 2012. Any unsupported areas of the map will be skipped. Note that only
|
July 2012. Any unsupported parts of the map will be skipped.
|
||||||
SQLite format maps are currently supported.
|
|
||||||
|
|
||||||
## General usage
|
## General usage
|
||||||
|
|
||||||
`mapeditr [-h] [-y] <map> <subcommand>`
|
`mapeditr [-h] [-y] <map> <SUBCOMMAND>`
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
|
|
||||||
- `-h, --help`: Print help information and exit.
|
- `-h, --help`: Print help information and exit.
|
||||||
- `-y, --yes`: Skip the default confirmation prompt (for those who feel brave).
|
- `-y, --yes`: Skip the default confirmation prompt (for those who feel brave).
|
||||||
- `<map>`: Path to the Minetest world/map to edit; this can be either a world
|
- `<map>`: Path to the Minetest world/map to edit; this can be either a world
|
||||||
directory or a `map.sqlite` file within a world folder. This file will be
|
directory or a `map.sqlite` file. This world/map will be modified, so *always*
|
||||||
modified, so *always* shut down the game/server before executing any command.
|
shut down the game or server before executing any command.
|
||||||
- `<subcommand>`: Command to execute. See "Commands" section below.
|
- `<SUBCOMMAND>`: Command to execute. See the "Commands" section below.
|
||||||
|
|
||||||
### Common command arguments
|
### Common command arguments
|
||||||
|
|
||||||
@ -37,11 +37,13 @@ modified, so *always* shut down the game/server before executing any command.
|
|||||||
area with corners at `p1` and `p2`, similarly to how WorldEdit's area selection
|
area with corners at `p1` and `p2`, similarly to how WorldEdit's area selection
|
||||||
works. Any two opposite corners can be used. These coordinates can be found
|
works. Any two opposite corners can be used. These coordinates can be found
|
||||||
using Minetest's F5 debug menu.
|
using Minetest's F5 debug menu.
|
||||||
- Node/item names: includes `node`, `new_node`, etc. Must be the full name,
|
- Node/item names, including `node`, `new_node`, etc.: Must be the full name,
|
||||||
e.g. "default:stone", not just "stone".
|
e.g. "default:stone", not just "stone".
|
||||||
|
|
||||||
### Other tips
|
### Other tips
|
||||||
|
|
||||||
|
Optional arguments are indicated using [square brackets].
|
||||||
|
|
||||||
Text-like arguments can be surrounded with "quotes" if they contain spaces.
|
Text-like arguments can be surrounded with "quotes" if they contain spaces.
|
||||||
|
|
||||||
Due to technical limitations, MapEditr will often leave lighting glitches. To
|
Due to technical limitations, MapEditr will often leave lighting glitches. To
|
||||||
@ -50,7 +52,7 @@ WorldEdit `//fixlight` command.
|
|||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
TODO: Unify documentation style, provide examples.
|
TODO: Unify documentation style, argument ordering, provide examples.
|
||||||
|
|
||||||
### clone
|
### clone
|
||||||
|
|
||||||
@ -61,30 +63,41 @@ Clone (copy) the contents of an area to a new location.
|
|||||||
Arguments:
|
Arguments:
|
||||||
|
|
||||||
- `--p1, --p2`: Area to clone.
|
- `--p1, --p2`: Area to clone.
|
||||||
- `--offset x y z`: Vector to shift the area by. For example, to copy an area
|
- `--offset x y z`: Vector to shift the area's contents by. For example, to
|
||||||
50 nodes downward (negative Y direction), use `--offset 0 -50 0`. Directions
|
copy an area 50 nodes downward (negative Y direction), use `--offset 0 -50 0`.
|
||||||
may be determined using Minetest's F5 debug menu.
|
Directions may be determined using Minetest's F5 debug menu.
|
||||||
|
|
||||||
This command copies nodes, param1, param2, and metadata. Nothing will be copied
|
This command copies nodes, param1, param2, and metadata. Nothing will be copied
|
||||||
from or into mapblocks that are not yet generated.
|
from or into mapblocks that are not yet generated.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
- Clone an area surrounding spawn 500 nodes west and 360 nodes north:
|
||||||
|
`clone --p1 200 80 200 --p2 -200 -15 -200 --offset -500 0 360`
|
||||||
|
|
||||||
### deleteblocks
|
### deleteblocks
|
||||||
|
|
||||||
Usage: `deleteblocks --p1 x y z --p2 x y z [--invert]`
|
Usage: `deleteblocks --p1 x y z --p2 x y z [--invert]`
|
||||||
|
|
||||||
Delete all mapblocks inside or outside an area.
|
Delete all mapblocks inside or outside an area. This command is often much
|
||||||
|
faster than Minetest's built-in `/deleteblocks` command.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
|
|
||||||
- `--p1, --p2`: Area containing mapblocks to delete. By default, only mapblocks
|
- `--p1, --p2`: Area containing mapblocks to delete. By default, only mapblocks
|
||||||
fully within this area will be deleted.
|
fully within this area will be deleted.
|
||||||
- `--invert`: If present, delete all mapblocks fully *outside* the given area.
|
- `--invert`: Delete all mapblocks fully *outside* the given area. Use with
|
||||||
Use with caution; you could erase a large portion of your world!
|
caution; you could erase a large portion of your world!
|
||||||
|
|
||||||
**Note:** Deleting mapblocks is *not* the same as filling them with air! Mapgen
|
**Note:** Deleting mapblocks is *not* the same as filling them with air! Mapgen
|
||||||
will be invoked where the blocks were deleted, and this sometimes causes
|
will be invoked where the blocks were deleted, and this sometimes causes
|
||||||
terrain glitches.
|
terrain glitches.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
- Delete all saved mapblocks below y = -200 and above y = 200:
|
||||||
|
`deleteblocks --p1 -31000 -200 -31000 --p2 31000 200 31000 --invert`
|
||||||
|
|
||||||
### deletemeta
|
### deletemeta
|
||||||
|
|
||||||
Usage: `deletemeta [--node <node>] [--p1 x y z] [--p2 x y z] [--invert]`
|
Usage: `deletemeta [--node <node>] [--p1 x y z] [--p2 x y z] [--invert]`
|
||||||
@ -98,7 +111,7 @@ Arguments:
|
|||||||
specified, metadata will be deleted from any node.
|
specified, metadata will be deleted from any node.
|
||||||
- `--p1, --p2`: (Optional) Area in which to delete metadata. If not specified,
|
- `--p1, --p2`: (Optional) Area in which to delete metadata. If not specified,
|
||||||
metadata will be deleted everywhere.
|
metadata will be deleted everywhere.
|
||||||
- `--invert`: If present, delete metadata *outside* the given area.
|
- `--invert`: Delete metadata *outside* the given area.
|
||||||
|
|
||||||
### deleteobjects
|
### deleteobjects
|
||||||
|
|
||||||
@ -109,15 +122,22 @@ Delete certain objects (entities) and/or item entities (dropped items).
|
|||||||
Arguments:
|
Arguments:
|
||||||
|
|
||||||
- `--obj <object>`: (Optional) Name of object to delete, e.g. "boats:boat".
|
- `--obj <object>`: (Optional) Name of object to delete, e.g. "boats:boat".
|
||||||
- `--items [items]`: If present, delete only item entities (dropped items). If
|
- `--items [items]`: (Optional) Delete only item entities (dropped items). If
|
||||||
one or more item names are listed after `--items`, only those items will be
|
one or more item names are listed after `--items`, only those items will be
|
||||||
deleted.
|
deleted.
|
||||||
- `--p1, --p2`: (Optional) Area in which to delete objects. If not specified,
|
- `--p1, --p2`: (Optional) Area in which to delete objects. If not specified,
|
||||||
objects will be deleted everywhere.
|
objects will be deleted everywhere.
|
||||||
- `--invert`: If present, delete objects *outside* the given area.
|
- `--invert`: Delete objects *outside* the given area.
|
||||||
|
|
||||||
`--obj` and `--items` cannot be used simultaneously.
|
`--obj` and `--items` cannot be used simultaneously.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
- Delete all objects: `deleteobjects`
|
||||||
|
- Delete all cart entities: `deleteobjects --obj carts:cart`
|
||||||
|
- Delete dropped stone and gravel:
|
||||||
|
`deleteobjects --items default:stone default:gravel`
|
||||||
|
|
||||||
### deletetimers
|
### deletetimers
|
||||||
|
|
||||||
Usage: `deletetimers [--node <node>] [--p1 x y z] [--p2 x y z] [--invert]`
|
Usage: `deletetimers [--node <node>] [--p1 x y z] [--p2 x y z] [--invert]`
|
||||||
@ -126,17 +146,18 @@ Delete node timers of certain nodes.
|
|||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
|
|
||||||
- `--node <node>`: If specified, only delete node timers from nodes with the
|
- `--node <node>`: (Optional) Name of node to delete node timers from. If not
|
||||||
given name.
|
specified, node timers of any node will be deleted.
|
||||||
- `--p1, --p2`: (Optional) Area in which to delete node timers.
|
- `--p1, --p2`: (Optional) Area in which to delete node timers. If not
|
||||||
|
specified, node timers will be deleted everywhere.
|
||||||
- `--invert`: Delete node timers *outside* the given area.
|
- `--invert`: Delete node timers *outside* the given area.
|
||||||
|
|
||||||
### fill
|
### fill
|
||||||
|
|
||||||
Usage: `fill --p1 x y z --p2 x y z [--invert] <new_node>`
|
Usage: `fill --p1 x y z --p2 x y z [--invert] <new_node>`
|
||||||
|
|
||||||
Fills everything inside or outside an area with one node. Mapblocks that are
|
Set all nodes inside or outside an area. Mapblocks that are not yet generated
|
||||||
not yet generated will not be affected.
|
will not be affected.
|
||||||
|
|
||||||
This command does not affect param2, node metadata, etc.
|
This command does not affect param2, node metadata, etc.
|
||||||
|
|
||||||
@ -144,7 +165,14 @@ Arguments:
|
|||||||
|
|
||||||
- `--p1, --p2`: Area to fill.
|
- `--p1, --p2`: Area to fill.
|
||||||
- `--invert`: Fill all generated nodes *outside* the given area.
|
- `--invert`: Fill all generated nodes *outside* the given area.
|
||||||
- `<new_node>`: Name of node to fill the area with.
|
- `<new_node>`: Name of the node to fill with.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
- Carve out a large hole in the ground:
|
||||||
|
`fill --p1 224 50 347 --p2 817 -40 73 air`
|
||||||
|
- Build a long obsidian glass wall travelling north/south:
|
||||||
|
`fill --p1 0 -30 -10000 --p2 0 30 10000 default:obsidian_glass`
|
||||||
|
|
||||||
### overlay
|
### overlay
|
||||||
|
|
||||||
@ -154,52 +182,63 @@ Copy part or all of a source map into the main map.
|
|||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
|
|
||||||
- `<input_map>`: Path to the source map/world. This world will not be modified.
|
- `<input_map>`: Path to the source map/world. This map will not be modified.
|
||||||
- `--p1, --p2`: Area to copy from. If not specified, MapEditr will try to
|
- `--p1, --p2`: (Optional) Area to copy from. If not specified, MapEditr will
|
||||||
copy everything from the source map.
|
try to copy everything from the source map.
|
||||||
- `--invert`: If present, copy everything *outside* the given area.
|
- `--invert`: Copy everything *outside* the given area.
|
||||||
- `--offset x y z`: Vector to shift nodes by when copying; default is no
|
- `--offset x y z`: (Optional) Vector to shift nodes by when copying; default
|
||||||
offset. Currently, an offset cannot be used with an inverted selection.
|
is no offset. Currently, an offset cannot be used with an inverted selection.
|
||||||
|
|
||||||
|
**If an area and/or offset is used:** To ensure that all data is copied, make
|
||||||
|
sure at least the "edges" of the destination area are generated, or the entire
|
||||||
|
destination area if using an offset.
|
||||||
|
|
||||||
This command will always copy nodes, param1, param2, and metadata. If no
|
This command will always copy nodes, param1, param2, and metadata. If no
|
||||||
offset is used, objects/entities and node timers may also be copied.
|
offset is used, objects/entities and node timers may also be copied.
|
||||||
|
|
||||||
To ensure that all data is copied, make sure the edges of the selection are
|
**Tip:** Overlay will be significantly faster if no offset is used.
|
||||||
generated in the destination map, or the entire selection if an offset is used.
|
|
||||||
|
|
||||||
**Tip:** Overlay will be significantly faster if no offset is used, as
|
Examples (your world/map paths will vary):
|
||||||
mapblocks can be copied verbatim.
|
|
||||||
|
- Copy all of map `backup.sqlite` into the main world:
|
||||||
|
`overlay backup-maps/backup.sqlite`
|
||||||
|
- Copy world `test` into the main world, excluding the area within 120 nodes of
|
||||||
|
spawn: `overlay test --p1 -120 -120 -120 --p2 120 120 120 --invert`
|
||||||
|
- Copy an area from `map.sqlite` into the main world, moving it 32 nodes north:
|
||||||
|
`overlay map.sqlite --p1 6 36 -49 --p2 -9 74 -78 --offset 0 0 32`
|
||||||
|
|
||||||
### replaceininv
|
### replaceininv
|
||||||
|
|
||||||
Usage: `replaceininv [--delete] [--deletemeta] [--nodes <nodes>] [--p1 x y z] [--p2 x y z] [--invert] <item> [new_item]`
|
Usage: `replaceininv <item> [new_item] [--delete] [--deletemeta] [--nodes <nodes>] [--p1 x y z] [--p2 x y z] [--invert]`
|
||||||
|
|
||||||
Replace, delete, or modify items in certain node inventories.
|
Replace, delete, or modify items in certain node inventories.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
|
|
||||||
- `<item>`: Name of the item to replace/delete
|
- `<item>`: Name of the item to replace/delete.
|
||||||
- `[new_item]`: Name of the new item, if replacing items.
|
- `[new_item]`: (Optional) Name of the new item, if replacing items.
|
||||||
- `--delete`: Delete items instead of replacing them.
|
- `--delete`: Delete items instead of replacing them.
|
||||||
- `--deletemeta`: Delete metadata of affected items. May be used with or
|
- `--deletemeta`: Delete metadata of affected items. May be used with or
|
||||||
without `new_item`, depending on whether items should also be replaced.
|
without `new_item`, depending on whether items should also be replaced.
|
||||||
- `--nodes <nodes>`: Names of one or more nodes to modify inventories of. If
|
- `--nodes <nodes>`: (Optional) Names of one or more nodes to modify
|
||||||
not specified, items will be modified in any node with an inventory.
|
inventories of. If not specified, items will be modified in any node with an
|
||||||
- `--p1, --p2`: Area in which to modify node inventories. If not specified,
|
inventory.
|
||||||
items will be modified everywhere.
|
- `--p1, --p2`: (Optional) Area in which to modify node inventories. If not
|
||||||
|
specified, items will be modified everywhere.
|
||||||
- `--invert`: Modify node inventories *outside* the given area.
|
- `--invert`: Modify node inventories *outside* the given area.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
Replace all written books in chests with unwritten books, deleting metadata:
|
- Delete all lava buckets:
|
||||||
|
`replaceininv bucket:bucket_lava --delete`
|
||||||
|
- Replace all written books in chests with unwritten books, deleting metadata:
|
||||||
`replaceininv default:book_written default:book --deletemeta --nodes default:chest default:chest_locked`
|
`replaceininv default:book_written default:book --deletemeta --nodes default:chest default:chest_locked`
|
||||||
|
|
||||||
### replacenodes
|
### replacenodes
|
||||||
|
|
||||||
Usage: `replacenodes [--p1 x y z] [--p2 x y z] [--invert] <node> <new_node>`
|
Usage: `replacenodes <node> <new_node> [--p1 x y z] [--p2 x y z] [--invert]`
|
||||||
|
|
||||||
Replace all of one node with another node. Can be used to remove unknown nodes
|
Replace one node with another node. Can also be used to remove unknown nodes
|
||||||
or swap a node that changed names.
|
or swap a node that changed names.
|
||||||
|
|
||||||
This command does not affect param2, metadata, etc.
|
This command does not affect param2, metadata, etc.
|
||||||
@ -208,28 +247,43 @@ Arguments:
|
|||||||
|
|
||||||
- `<node>`: Name of node to replace.
|
- `<node>`: Name of node to replace.
|
||||||
- `<new_node>`: Name of node to replace with.
|
- `<new_node>`: Name of node to replace with.
|
||||||
- `--p1, --p2`: Area in which to replace nodes. If not specified, nodes will be
|
- `--p1, --p2`: (Optional) Area in which to replace nodes. If not specified,
|
||||||
replaced across the entire map.
|
nodes will be replaced across the entire map.
|
||||||
- `--invert`: Replace nodes *outside* the given area.
|
- `--invert`: Replace nodes *outside* the given area.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
- Replace all legacy PB&J pup nodes with mese blocks:
|
||||||
|
`replacenodes pbj_pup:pbj_pup default:mese`
|
||||||
|
- Remove fire nodes near ground level:
|
||||||
|
`replacenodes fire:basic_flame air --p1 -31000 -80 -31000 --p2 31000 200 31000`
|
||||||
|
|
||||||
### setmetavar
|
### setmetavar
|
||||||
|
|
||||||
Usage: `setmetavar [--node <node>] [--p1 x y z] [--p2 x y z] [--invert] <key> <value>`
|
Usage: `setmetavar <key> [value] [--delete] [--nodes <nodes>] [--p1 x y z] [--p2 x y z] [--invert]`
|
||||||
|
|
||||||
Set or delete a variable in node metadata of certain nodes. This only works on metadata
|
Set or delete a variable in node metadata of certain nodes. This only works on
|
||||||
where the variable is already set.
|
nodes where the variable is already set.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
|
|
||||||
- `<key>`: Name of variable to set/delete, e.g. `infotext`, `formspec`, etc.
|
- `<key>`: Name of variable to set/delete, e.g. `infotext`, `formspec`, etc.
|
||||||
- `<value>`: Value to set variable to, if setting a value. This should be a
|
- `[value]`: Value to set variable to, if setting a value. This should be a
|
||||||
string.
|
string.
|
||||||
- `--delete`: Delete the variable.
|
- `--delete`: Delete the variable.
|
||||||
- `--nodes <nodes>`: Names of one or more nodes to modify. If not specified,
|
- `--nodes <nodes>`: (Optional) Names of one or more nodes to modify. If not
|
||||||
any node with the given variable will be modified.
|
specified, any node with the given variable will be modified.
|
||||||
- `--p1, --p2`: Area in which to modify node metadata.
|
- `--p1, --p2`: (Optional) Area in which to modify node metadata. If not
|
||||||
|
specified, nodes will be modified everywhere.
|
||||||
- `--invert`: Modify node metadata *outside* the given area.
|
- `--invert`: Modify node metadata *outside* the given area.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
- Clear infotext of signs:
|
||||||
|
`setmetavar infotext --delete --nodes default:sign_wall_steel default:sign_wall_wood`
|
||||||
|
- Set "player1" as the owner of all steel trapdoors:
|
||||||
|
`setmetavar owner player1 --nodes doors:trapdoor_steel`
|
||||||
|
|
||||||
### setparam2
|
### setparam2
|
||||||
|
|
||||||
Usage: `setparam2 [--node <node>] [--p1 x y z] [--p2 x y z] [--invert] <param2>`
|
Usage: `setparam2 [--node <node>] [--p1 x y z] [--p2 x y z] [--invert] <param2>`
|
||||||
@ -238,25 +292,26 @@ Set param2 values of certain nodes.
|
|||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
|
|
||||||
- `<param2>`: New param2 value, between 0 and 255.
|
- `--node <node>`: (Optional) Name of node to modify. If not specified, the
|
||||||
- `--node <node>`: Name of node to modify. If not specified, the param2 values
|
param2 values of any node will be set.
|
||||||
of any node will be set.
|
- `--p1, --p2`: (Optional) Area in which to set param2 values. If not
|
||||||
- `--p1, --p2`: Area in which to set param2 values.
|
specified, param2 will be set everywhere.
|
||||||
- `--invert`: Set param2 values *outside* the given area.
|
- `--invert`: Set param2 values *outside* the given area.
|
||||||
|
- `<param2>`: New param2 value, between 0 and 255.
|
||||||
|
|
||||||
An area and/or node is required for setparam2.
|
An area and/or node is required for this command.
|
||||||
|
|
||||||
### vacuum
|
### vacuum
|
||||||
|
|
||||||
Usage: `vacuum`
|
Usage: `vacuum`
|
||||||
|
|
||||||
Vacuums the database. This reduces the size of the database, but may take a
|
Rebuild the map database to reduce its size. Vacuuming may take a long time for
|
||||||
long time.
|
large maps.
|
||||||
|
|
||||||
All this does is perform an SQLite `VACUUM` command. This shrinks and optimizes
|
This command simply executes the SQLite `VACUUM` command, which shrinks and
|
||||||
the database by efficiently "repacking" all mapblocks. No map data is changed
|
optimizes the map database by efficiently "repacking" all mapblocks. No map
|
||||||
or deleted.
|
data is changed or deleted.
|
||||||
|
|
||||||
**Note:** Because data is copied into another file, vacuum could require
|
**Note:** Because data is temporarily copied into another file, vacuum could
|
||||||
as much free disk space as is already occupied by the map. For example, if
|
require as much free disk space as is already occupied by the map. For example,
|
||||||
map.sqlite is 10 GB, make sure you have **at least 10 GB** of free space!
|
if map.sqlite is 10 GB, make sure you have **at least 10 GB** of free space!
|
||||||
|
@ -36,10 +36,11 @@ runs much faster than the default, unoptimized version.
|
|||||||
For an overview of how MapEditr works and a listing of commands and their
|
For an overview of how MapEditr works and a listing of commands and their
|
||||||
usages, see [Manual.md](Manual.md).
|
usages, see [Manual.md](Manual.md).
|
||||||
|
|
||||||
Some useful things you can do with MapEditr:
|
These are just a few of the useful things you can do with MapEditr:
|
||||||
|
|
||||||
- Remove unknown nodes left by old mods with `replacenodes`.
|
- Remove unknown nodes left by old mods with `replacenodes`.
|
||||||
- Build extremely long walls and roads in seconds using `fill`.
|
- Build extremely long walls and roads in seconds using `fill`.
|
||||||
|
- Selectively delete entities and/or dropped items using `deleteobjects`.
|
||||||
- Combine multiple worlds or map saves with `overlay`.
|
- Combine multiple worlds or map saves with `overlay`.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
@ -316,7 +316,7 @@ pub fn run_cmd_line() {
|
|||||||
},
|
},
|
||||||
ServerEvent::ConfirmRequest => {
|
ServerEvent::ConfirmRequest => {
|
||||||
newline_if(&mut need_newline);
|
newline_if(&mut need_newline);
|
||||||
status.confirm(get_confirmation());
|
status.send_confirmation(get_confirmation());
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
@ -128,7 +128,7 @@ pub fn get_command() -> Command {
|
|||||||
verify_args: Some(verify_args),
|
verify_args: Some(verify_args),
|
||||||
args: vec![
|
args: vec![
|
||||||
(ArgType::Area(true), "Area to clone"),
|
(ArgType::Area(true), "Area to clone"),
|
||||||
(ArgType::Offset(true), "Vector to shift the area by")
|
(ArgType::Offset(true), "Vector to shift the area's contents by")
|
||||||
],
|
],
|
||||||
help: "Clone (copy) the contents of an area to a new location."
|
help: "Clone (copy) the contents of an area to a new location."
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,7 @@ pub fn get_command() -> Command {
|
|||||||
args: vec![
|
args: vec![
|
||||||
(ArgType::Area(true), "Area containing mapblocks to delete"),
|
(ArgType::Area(true), "Area containing mapblocks to delete"),
|
||||||
(ArgType::Invert,
|
(ArgType::Invert,
|
||||||
"If present, delete all mapblocks fully *outside* the given \
|
"Delete all mapblocks fully *outside* the given area.")
|
||||||
area.")
|
|
||||||
],
|
],
|
||||||
help: "Delete all mapblocks inside or outside an area."
|
help: "Delete all mapblocks inside or outside an area."
|
||||||
}
|
}
|
||||||
|
@ -83,10 +83,9 @@ pub fn get_command() -> Command {
|
|||||||
func: delete_metadata,
|
func: delete_metadata,
|
||||||
verify_args: Some(verify_args),
|
verify_args: Some(verify_args),
|
||||||
args: vec![
|
args: vec![
|
||||||
|
(ArgType::Node(false), "Name of node to delete metadata from"),
|
||||||
(ArgType::Area(false), "Area in which to delete metadata"),
|
(ArgType::Area(false), "Area in which to delete metadata"),
|
||||||
(ArgType::Invert,
|
(ArgType::Invert, "Delete metadata *outside* the given area."),
|
||||||
"If present, delete metadata *outside* the given area."),
|
|
||||||
(ArgType::Node(false), "Name of node to delete metadata from")
|
|
||||||
],
|
],
|
||||||
help: "Delete node metadata of certain nodes."
|
help: "Delete node metadata of certain nodes."
|
||||||
}
|
}
|
||||||
|
@ -132,13 +132,12 @@ pub fn get_command() -> Command {
|
|||||||
func: delete_objects,
|
func: delete_objects,
|
||||||
verify_args: Some(verify_args),
|
verify_args: Some(verify_args),
|
||||||
args: vec![
|
args: vec![
|
||||||
(ArgType::Area(false), "Area in which to delete objects"),
|
|
||||||
(ArgType::Invert,
|
|
||||||
"If present, delete objects *outside* the given area."),
|
|
||||||
(ArgType::Object, "Name of object to delete"),
|
(ArgType::Object, "Name of object to delete"),
|
||||||
(ArgType::Items,
|
(ArgType::Items,
|
||||||
"If present, delete item entities. Optionally list one or \
|
"Delete only item entities. Optionally list one or more item \
|
||||||
more item names after `--items` to delete only those items."),
|
names after `--items` to delete only those items."),
|
||||||
|
(ArgType::Area(false), "Area in which to delete objects"),
|
||||||
|
(ArgType::Invert, "Delete objects *outside* the given area."),
|
||||||
],
|
],
|
||||||
help: "Delete certain objects and/or item entities."
|
help: "Delete certain objects and/or item entities."
|
||||||
}
|
}
|
||||||
|
@ -68,11 +68,9 @@ pub fn get_command() -> Command {
|
|||||||
func: delete_timers,
|
func: delete_timers,
|
||||||
verify_args: None,
|
verify_args: None,
|
||||||
args: vec![
|
args: vec![
|
||||||
(ArgType::Area(false), "Area in which to delete timers"),
|
(ArgType::Node(false), "Name of node to delete node timers from"),
|
||||||
|
(ArgType::Area(false), "Area in which to delete node timers"),
|
||||||
(ArgType::Invert, "Delete node timers *outside* the given area."),
|
(ArgType::Invert, "Delete node timers *outside* the given area."),
|
||||||
(ArgType::Node(false),
|
|
||||||
"Node to delete timers from. If not specified, node timers \
|
|
||||||
will be deleted from any node.")
|
|
||||||
],
|
],
|
||||||
help: "Delete node timers of certain nodes."
|
help: "Delete node timers of certain nodes."
|
||||||
}
|
}
|
||||||
|
@ -82,8 +82,8 @@ pub fn get_command() -> Command {
|
|||||||
(ArgType::Area(true), "Area to fill"),
|
(ArgType::Area(true), "Area to fill"),
|
||||||
(ArgType::Invert,
|
(ArgType::Invert,
|
||||||
"Fill all generated nodes *outside* the given area."),
|
"Fill all generated nodes *outside* the given area."),
|
||||||
(ArgType::NewNode, "Name of node to fill the area with"),
|
(ArgType::NewNode, "Name of the node to fill with"),
|
||||||
],
|
],
|
||||||
help: "Fill the entire area with one node."
|
help: "Set all nodes inside or outside an area."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -228,8 +228,7 @@ pub fn get_command() -> Command {
|
|||||||
(ArgType::InputMapPath, "Path to the source map/world"),
|
(ArgType::InputMapPath, "Path to the source map/world"),
|
||||||
(ArgType::Area(false), "Area to copy from. If not specified, \
|
(ArgType::Area(false), "Area to copy from. If not specified, \
|
||||||
everything from the source map will be copied."),
|
everything from the source map will be copied."),
|
||||||
(ArgType::Invert,
|
(ArgType::Invert, "Copy everything *outside* the given area."),
|
||||||
"If present, copy everything *outside* the given area."),
|
|
||||||
(ArgType::Offset(false), "Vector to shift nodes by when copying"),
|
(ArgType::Offset(false), "Vector to shift nodes by when copying"),
|
||||||
],
|
],
|
||||||
help: "Copy part or all of a source map into the main map."
|
help: "Copy part or all of a source map into the main map."
|
||||||
|
@ -146,6 +146,6 @@ pub fn get_command() -> Command {
|
|||||||
(ArgType::Area(false), "Area in which to replace nodes"),
|
(ArgType::Area(false), "Area in which to replace nodes"),
|
||||||
(ArgType::Invert, "Replace nodes *outside* the given area.")
|
(ArgType::Invert, "Replace nodes *outside* the given area.")
|
||||||
],
|
],
|
||||||
help: "Replace all of one node with another node."
|
help: "Replace one node with another node."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,8 +60,6 @@ fn set_param2(inst: &mut InstBundle) {
|
|||||||
inst.status.begin_editing();
|
inst.status.begin_editing();
|
||||||
|
|
||||||
let mut count: u64 = 0;
|
let mut count: u64 = 0;
|
||||||
use crate::time_keeper::TimeKeeper;
|
|
||||||
let mut tk = TimeKeeper::new();
|
|
||||||
for key in keys {
|
for key in keys {
|
||||||
inst.status.inc_done();
|
inst.status.inc_done();
|
||||||
|
|
||||||
@ -81,7 +79,6 @@ fn set_param2(inst: &mut InstBundle) {
|
|||||||
.filter(|a| a.contains_block(pos) != a.touches_block(pos))
|
.filter(|a| a.contains_block(pos) != a.touches_block(pos))
|
||||||
{ // Modify part of block
|
{ // Modify part of block
|
||||||
let block_part = area.rel_block_overlap(pos).unwrap();
|
let block_part = area.rel_block_overlap(pos).unwrap();
|
||||||
let _t = tk.get_timer("set_param2_partial");
|
|
||||||
count += set_param2_partial(&mut block,
|
count += set_param2_partial(&mut block,
|
||||||
block_part, inst.args.invert, node_id, param2_val);
|
block_part, inst.args.invert, node_id, param2_val);
|
||||||
} else { // Modify whole block
|
} else { // Modify whole block
|
||||||
@ -102,7 +99,6 @@ fn set_param2(inst: &mut InstBundle) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inst.status.end_editing();
|
inst.status.end_editing();
|
||||||
tk.print(&mut inst.status);
|
|
||||||
inst.status.log_info(format!("Set param2 of {} nodes.",
|
inst.status.log_info(format!("Set param2 of {} nodes.",
|
||||||
fmt_big_num(count)));
|
fmt_big_num(count)));
|
||||||
}
|
}
|
||||||
@ -122,10 +118,10 @@ pub fn get_command() -> Command {
|
|||||||
func: set_param2,
|
func: set_param2,
|
||||||
verify_args: Some(verify_args),
|
verify_args: Some(verify_args),
|
||||||
args: vec![
|
args: vec![
|
||||||
(ArgType::Param2, "New param2 value, between 0 and 255"),
|
(ArgType::Node(false), "Name of node to modify"),
|
||||||
(ArgType::Node(false), "Node to set param2 values of"),
|
|
||||||
(ArgType::Area(false), "Area in which to set param2 values"),
|
(ArgType::Area(false), "Area in which to set param2 values"),
|
||||||
(ArgType::Invert, "Set param2 values *outside* the given area."),
|
(ArgType::Invert, "Set param2 values *outside* the given area."),
|
||||||
|
(ArgType::Param2, "New param2 value, between 0 and 255"),
|
||||||
],
|
],
|
||||||
help: "Set param2 values of certain nodes."
|
help: "Set param2 values of certain nodes."
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ fn vacuum(inst: &mut InstBundle) {
|
|||||||
|
|
||||||
match res {
|
match res {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
inst.status.log_info(format!("Completed vacuum."));
|
inst.status.log_info("Completed vacuum.");
|
||||||
},
|
},
|
||||||
Err(e) => inst.status.log_error(format!("Vacuum failed: {}.", e))
|
Err(e) => inst.status.log_error(format!("Vacuum failed: {}.", e))
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ use crate::spatial::{Vec3, Area, MAP_LIMIT};
|
|||||||
use crate::map_database::MapDatabase;
|
use crate::map_database::MapDatabase;
|
||||||
use crate::commands;
|
use crate::commands;
|
||||||
use crate::commands::ArgResult;
|
use crate::commands::ArgResult;
|
||||||
|
use crate::utils::fmt_big_num;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -200,7 +201,7 @@ impl StatusClient {
|
|||||||
&self.event_rx
|
&self.event_rx
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn confirm(&self, choice: bool) {
|
pub fn send_confirmation(&self, choice: bool) {
|
||||||
self.event_tx.send(ClientEvent::ConfirmResponse(choice)).unwrap();
|
self.event_tx.send(ClientEvent::ConfirmResponse(choice)).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -235,8 +236,6 @@ pub struct InstBundle<'a> {
|
|||||||
|
|
||||||
|
|
||||||
fn verify_args(args: &InstArgs) -> anyhow::Result<()> {
|
fn verify_args(args: &InstArgs) -> anyhow::Result<()> {
|
||||||
// TODO: Complete verifications.
|
|
||||||
|
|
||||||
if args.area.is_none() && args.invert {
|
if args.area.is_none() && args.invert {
|
||||||
anyhow::bail!("Cannot invert without a specified area.");
|
anyhow::bail!("Cannot invert without a specified area.");
|
||||||
}
|
}
|
||||||
@ -314,7 +313,7 @@ fn open_map(path: PathBuf, flags: sqlite::OpenFlags)
|
|||||||
if with_file.is_file() {
|
if with_file.is_file() {
|
||||||
with_file
|
with_file
|
||||||
} else {
|
} else {
|
||||||
anyhow::bail!("could not find map file");
|
anyhow::bail!("Could not find the map file.");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -335,17 +334,20 @@ fn compute_thread(args: InstArgs, status: StatusServer) -> anyhow::Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let db_conn = open_map(PathBuf::from(&args.map_path),
|
let db_conn = open_map(
|
||||||
sqlite::OpenFlags::new().set_read_write())?;
|
PathBuf::from(&args.map_path),
|
||||||
|
sqlite::OpenFlags::new().set_read_write()
|
||||||
|
).context("Failed to open main world/map.")?;
|
||||||
let db = MapDatabase::new(&db_conn)
|
let db = MapDatabase::new(&db_conn)
|
||||||
.context("Failed to open main world/map.")?;
|
.context("Main world or map database is invalid.")?;
|
||||||
|
|
||||||
let idb_conn = args.input_map_path.as_deref().map(
|
let idb_conn = args.input_map_path.as_deref()
|
||||||
|imp| open_map(PathBuf::from(imp),
|
.map(|imp| open_map(PathBuf::from(imp),
|
||||||
sqlite::OpenFlags::new().set_read_only())
|
sqlite::OpenFlags::new().set_read_only()))
|
||||||
).transpose().context("Failed to open input world/map.")?;
|
.transpose().context("Failed to open input world/map.")?;
|
||||||
let idb = match &idb_conn {
|
let idb = match &idb_conn {
|
||||||
Some(conn) => Some(MapDatabase::new(conn)?),
|
Some(conn) => Some(MapDatabase::new(conn)
|
||||||
|
.context("Input world or map database is invalid.")?),
|
||||||
None => None
|
None => None
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -370,7 +372,9 @@ fn compute_thread(args: InstArgs, status: StatusServer) -> anyhow::Result<()> {
|
|||||||
let fails = inst.status.get_status().blocks_failed;
|
let fails = inst.status.get_status().blocks_failed;
|
||||||
if fails > 0 {
|
if fails > 0 {
|
||||||
inst.status.log_info(format!(
|
inst.status.log_info(format!(
|
||||||
"Skipped {} invalid/unsupported mapblocks.", fails));
|
"Skipped {} invalid/unsupported mapblocks.",
|
||||||
|
fmt_big_num(fails as u64)
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if inst.db.is_in_transaction() {
|
if inst.db.is_in_transaction() {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
mod time_keeper;
|
// Kept for testing purposes
|
||||||
|
// mod time_keeper;
|
||||||
mod spatial;
|
mod spatial;
|
||||||
mod utils;
|
mod utils;
|
||||||
mod map_database;
|
mod map_database;
|
||||||
@ -9,8 +10,7 @@ mod commands;
|
|||||||
mod cmd_line;
|
mod cmd_line;
|
||||||
|
|
||||||
|
|
||||||
// TODO: Check for unnecessary #derives!
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// TODO: Add GUI. hmm...
|
// TODO: Add a GUI. hmm...
|
||||||
cmd_line::run_cmd_line();
|
cmd_line::run_cmd_line();
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,10 @@ impl Compress for Vec<u8> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Stores some data and its zlib-compressed equivalent.
|
||||||
|
///
|
||||||
|
/// The goal of this struct is to avoid recompressing data that was not
|
||||||
|
/// modified from its original compressed form.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ZlibContainer<T: Compress> {
|
pub struct ZlibContainer<T: Compress> {
|
||||||
compressed: Option<Vec<u8>>,
|
compressed: Option<Vec<u8>>,
|
||||||
|
@ -12,7 +12,7 @@ pub fn is_valid_generated(data: &[u8]) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct MapBlock {
|
pub struct MapBlock {
|
||||||
pub version: u8,
|
pub version: u8,
|
||||||
pub flags: u8,
|
pub flags: u8,
|
||||||
|
@ -9,7 +9,7 @@ use memmem::{Searcher, TwoWaySearcher};
|
|||||||
const END_STR: &[u8; 13] = b"EndInventory\n";
|
const END_STR: &[u8; 13] = b"EndInventory\n";
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct NodeMetadata {
|
pub struct NodeMetadata {
|
||||||
pub vars: HashMap<Vec<u8>, (Vec<u8>, bool)>,
|
pub vars: HashMap<Vec<u8>, (Vec<u8>, bool)>,
|
||||||
pub inv: Vec<u8>
|
pub inv: Vec<u8>
|
||||||
@ -100,20 +100,21 @@ impl NodeMetadataListExt for NodeMetadataList {
|
|||||||
fn serialize(&self, block_version: u8) -> Vec<u8> {
|
fn serialize(&self, block_version: u8) -> Vec<u8> {
|
||||||
let buf = Vec::new();
|
let buf = Vec::new();
|
||||||
let mut data = Cursor::new(buf);
|
let mut data = Cursor::new(buf);
|
||||||
|
// Skip empty metadata when serializing.
|
||||||
|
let count = self.iter().filter(|&(_, m)| !m.is_empty()).count();
|
||||||
|
|
||||||
if self.len() == 0 {
|
if count == 0 {
|
||||||
data.write_u8(0).unwrap();
|
data.write_u8(0).unwrap();
|
||||||
} else {
|
} else {
|
||||||
let version = if block_version >= 28 { 2 } else { 1 };
|
let version = if block_version >= 28 { 2 } else { 1 };
|
||||||
data.write_u8(version).unwrap();
|
data.write_u8(version).unwrap();
|
||||||
data.write_u16::<BigEndian>(self.len() as u16).unwrap();
|
data.write_u16::<BigEndian>(count as u16).unwrap();
|
||||||
|
|
||||||
for (&pos, meta) in self {
|
for (&pos, meta) in self {
|
||||||
if meta.is_empty() {
|
if !meta.is_empty() {
|
||||||
continue; // Skip empty metadata.
|
data.write_u16::<BigEndian>(pos).unwrap();
|
||||||
|
meta.serialize(&mut data, version);
|
||||||
}
|
}
|
||||||
data.write_u16::<BigEndian>(pos).unwrap();
|
|
||||||
meta.serialize(&mut data, version);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ use std::collections::BTreeMap;
|
|||||||
/// Maps 16-bit node IDs to actual node names.
|
/// Maps 16-bit node IDs to actual node names.
|
||||||
///
|
///
|
||||||
/// Relevant Minetest source file: /src/nameidmapping.cpp
|
/// Relevant Minetest source file: /src/nameidmapping.cpp
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct NameIdMap(pub BTreeMap<u16, Vec<u8>>);
|
pub struct NameIdMap(pub BTreeMap<u16, Vec<u8>>);
|
||||||
|
|
||||||
impl NameIdMap {
|
impl NameIdMap {
|
||||||
|
@ -2,7 +2,7 @@ use super::*;
|
|||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct NodeTimer {
|
pub struct NodeTimer {
|
||||||
pub pos: u16,
|
pub pos: u16,
|
||||||
pub timeout: u32,
|
pub timeout: u32,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user