add documentation

This commit is contained in:
FaceDeer 2017-03-01 23:33:12 -07:00
parent 9758da21b3
commit 9cce7a62cf
7 changed files with 156 additions and 2 deletions

76
api.txt Normal file
View File

@ -0,0 +1,76 @@
This document is intended primarily for modders interested in adding their own gate nodes and gate types.
This mod allows for additional gate nodes to be defined in other dependent mods that will work seamlessly with existing gate nodes. The following is a minimalist example that shows a node using all of the features offered by this mod's gate API:
minetest.register_node("castle_gates:example_gate_piece", {
description = "Example gate",
groups = {castle_gate = 1},
tiles = {"default_wood.png"},
paramtype2 = "facedir",
on_rightclick = castle_gates.trigger_gate,
_gate_edges = {"right"=true},
_gate_hinge = {axis="top", offset={"front","left"}},
})
The key features are:
* paramtype2 = "facedir" (mandatory)
* "castle_gate" group membership (mandatory)
* on_rightclick = castle_gates.trigger_gate (optional, but recommended)
* _gate_edges = <edge definition> (optional)
* _gate_hinge = <hinge defintion> (optional)
Paramtype2
==========
All gate pieces must be orientable via facedir.
Castle_gate group
=================
When a gate is triggered by right-clicking on a gate node, the gate code does a "flood fill" operation to find all connected gate nodes. This flood fill operation looks for adjacent nodes that belong to the same castle_gate group, so all gate nodes need to belong to this group.
Gates defined in this mod all belong to castle_gate=1.
on_rightclick
=============
The castle_gates.trigger_gate method is a right-click handler that will trigger the movement of the gate. If you want your gate pieces to respond to a player's right click by opening, use this call to make the gate magic happen.
Note that if you wish you can embed the call to The castle_gates.trigger_gate inside your own on_rightclick function, so that for example you could make a "locked" gate that will only respond to specific players (you may wish to use a different castle_gate group ID for such a gate). Or you can omit this function, in which case the gate piece will still move with the rest of the gate but right-clicking on it will not trigger the gate's movement.
_gate_edges
===========
This is an optional property you can put on a gate node's definition to prevent flood-fill from extending beyond this node in a particular direction. This is useful if, for example, you want players to be able to build double doors that would otherwise connect together when both doors are closed.
It consists of a table with directions defined as edges set to true. You can use this template:
_gate_edges = {right=false, left=false, top=false, bottom=false}
("front" and "back" are also possible but are unlikely to be of any real use)
Note that the flood-fill search for gate nodes will flow *around* an edge piece if a path exists, the mere fact that there's an edge piece does not guarantee that the door node beyond the edge will not be considered part of the same door as it.
_gate_hinge
===========
The hinge definition for a node def is of the following form:
_gate_hinge = {axis=<axis>, offset=<offset>}
<axis> is one of "top", "bottom", "left", "right", "front" or "back".
Top/bottom, left/right and front/back are interchangeable pairings as far as this code is concerned.
These directions are relative to the orientation of the block. Existing gates use "top", so for
maximum compatibility it's advised that new gate hinges are defined with the same axis.
<offset> is optional. If it is not defined, the gate hinge will try to rotate around the center of the node.
<offset> can be a single direction ("top", "bottom", "left", "right", "front", "back"). If a single direction is
given the hinge will try to rotate around the center of the node that lies in that direction relative to the hinge node.
<offset> can also be a pair of directions given in a table. This is how the *edge* of a node can be made into the
center of rotation. For example, existing gate hinges in this mod have the offset {"front","left"}. This means that the
gate will try to rotate around the center of the edge of the node where the front and left faces intersect.
You should only use direction pairs that form a 90 degree angle.

View File

@ -2,4 +2,5 @@ default
castle_masonry?
doors?
xpanes?
intllib?
intllib?
doc?

52
doc.lua Normal file
View File

@ -0,0 +1,52 @@
castle_gates.doc = {}
if not minetest.get_modpath("doc") then
return
end
-- internationalization boilerplate
local MP = minetest.get_modpath(minetest.get_current_modname())
local S, NS = dofile(MP.."/intllib.lua")
castle_gates.doc.portcullis_bars_longdesc = S("Heavy wooden bars designed to prevent entry even to siege equipment.")
castle_gates.doc.portcullis_bars_usagehelp = S("Place these bars in a structure together and they will slide as a unified gate when clicked on.")
castle_gates.doc.portcullis_bars_bottom_longdesc = S("The bottom edge of a portcullis gate, with knobs to lock securely into the floor.")
castle_gates.doc.portcullis_bars_bottom_usagehelp = S("This block can be used to define the edge of a portcullius that meets up with another gate, should you have an arrangement like that. Otherwise it's just decorative.")
castle_gates.doc.gate_panel_longdesc = S("A basic gate panel.")
castle_gates.doc.gate_panel_usagehelp = S("This gate segment will move in unison with adjoining gate segments when right-clicked.")
castle_gates.doc.gate_edge_longdesc = S("A gate panel with a defined edge.")
castle_gates.doc.gate_edge_usagehelp = S("The darkened edge of this panel marks the edge of the gate it's a part of. You can use these when building double doors to ensure the two parts swing separately, for example. Note that edges aren't strictly necessary for gates that stand alone.")
castle_gates.doc.gate_edge_handle_longdesc = S("A gate edge with a handle.")
castle_gates.doc.gate_edge_handle_usagehelp = S("The handle is basically decorative, a door this size can be swung by clicking anywhere on it. But the darkened edge of this panel is useful for defining the edge of a gate when it abuts a partner to the side.")
castle_gates.doc.gate_hinge_longdesc = S("A hinged gate segment that allows a gate to swing.")
castle_gates.doc.gate_hinge_usagehelp = S("If you have more than one hinge in your gate, make sure the hinges line up correctly otherwise the gate will not be able to swing. The hinge is the protruding block along the edge of the gate panel.")
castle_gates.doc.gate_slot_longdesc = S("A block with a slot to allow an adjacent sliding gate through.")
castle_gates.doc.gate_slot_usagehelp = S("This block is designed to extend into a neighboring node that a sliding gate passes through, to provide a tight seal for the gate to move through without allowing anything else to squeeze in.")
castle_gates.doc.gate_slot_reverse_longdesc = S("A block that extends into an adjacent node to provide a tight seal for a large gate.")
castle_gates.doc.gate_slot_reverse_usagehelp = S("Two nodes cannot occupy the same space, but this block extends into a neighboring node's space to allow for gates to form a tight seal. It can be used with sliding gates or swinging gates.")
doc.add_category("castle_gates",
{
name = S("Gates"),
description = S("Gates are large multi-node constructions that swing on hinges or slide out of the way when triggered."),
build_formspec = doc.entry_builders.text_and_gallery,
})
doc.add_entry("castle_gates", "construction", {
name = S("Gate construction"),
data = { text =
S("Gates are multi-node constructions, usually (though not always) consisting of multiple node types that fit together into a unified whole. The orientation of gate nodes is significant, so a screwdriver will be a helpful tool when constructing gates."
.."\n\n"..
"A gate's extent is determined by a \"flood fill\" operation. When you trigger a gate block, all compatible neighboring blocks will be considered part of the same structure and will move in unison. Only gate blocks that are aligned with each other will be considered part of the same gate. If you wish to build adjoining gates (for example, a large pair of double doors that meet in the center) you'll need to make use of gate edge blocks to prevent it all from being considered one big door. Note that if your gate does not abut any other gates you don't actually need to define its edges this way - you don't have to use edge blocks in this case."
.."\n\n"..
"If a gate has no hinge nodes it will be considered a sliding gate. When triggered, the gate code will search for a direction that the gate can slide in and will move it in that direction at a rate of one block-length per second. Once it reaches an obstruction it will stop, and when triggered again it will try sliding in the opposite direction."
.."\n\n"..
"If a gate has hinge nodes then triggering it will cause the gate to try swinging around the hinge. If the gate has multiple hinges and they don't line up properly the gate will be unable to move. Note that the gate can only exist in 90-degree increments of orientation, but the gate still looks for obstructions in the region it is swinging through and will not swing if there's something in the way.")
}})

View File

@ -23,6 +23,7 @@ local get_dirs = function(facedir)
return dirs
end
-- Returns the axis that dir points along
local dir_to_axis = function(dir)
if dir.x ~= 0 then
return "x"
@ -33,6 +34,7 @@ local dir_to_axis = function(dir)
end
end
-- Given a hinge definition, turns it into an axis and placement that can be used by the door rotation.
local interpret_hinge = function(hinge_def, pos, node_dirs)
local axis = dir_to_axis(node_dirs[hinge_def.axis])
@ -130,6 +132,8 @@ local get_door_layout = function(pos, facedir, player)
local tested = Pointset.create()
local can_slide_to = Pointset.create()
local castle_gate_group_value -- this will be populated from the first gate node we encounter, which will be the one that was clicked on
to_test:set_pos(pos, true)
local test_pos, _ = to_test:pop()
@ -152,8 +156,12 @@ local get_door_layout = function(pos, facedir, player)
if test_node_def.paramtype2 == "facedir" then
local test_node_dirs = get_dirs(test_node.param2)
local coplanar = vector.equals(test_node_dirs.back, door.directions.back)
if castle_gate_group_value == nil and test_node_def.groups.castle_gate ~= nil then
castle_gate_group_value = test_node_def.groups.castle_gate -- read the group value from the first gate node encountered
end
if coplanar and test_node_def.groups.castle_gate then
if coplanar and test_node_def.groups.castle_gate == castle_gate_group_value then
local entry = {["pos"] = test_pos, ["node"] = test_node}
table.insert(door.all, entry)
if test_node_def._gate_hinge ~= nil then

View File

@ -43,6 +43,8 @@ castle_gates.register_gate_slot = function(material)
minetest.register_node(mod_name..":"..material.name.."_gate_slot", {
drawtype = "nodebox",
description = S("@1 Gate Slot", desc),
_doc_items_longdesc = castle_gates.doc.gate_slot_longdesc,
_doc_items_usagehelp = castle_gates.doc.gate_slot_usagehelp,
tiles = tile,
paramtype = "light",
paramtype2 = "facedir",
@ -66,6 +68,8 @@ castle_gates.register_gate_slot = function(material)
minetest.register_node(mod_name..":"..material.name.."_gate_slot_reverse", {
drawtype = "nodebox",
description = S("@1 Gate Slot Reverse", desc),
_doc_items_longdesc = castle_gates.doc.gate_slot_reverse_longdesc,
_doc_items_usagehelp = castle_gates.doc.gate_slot_reverse_usagehelp,
tiles = tile,
paramtype = "light",
paramtype2 = "facedir",

View File

@ -5,6 +5,8 @@ local S, NS = dofile(MP.."/intllib.lua")
minetest.register_node("castle_gates:portcullis_bars", {
drawtype = "nodebox",
description = S("Portcullis Bars"),
_doc_items_longdesc = castle_gates.doc.portcullis_bars_longdesc,
_doc_items_usagehelp = castle_gates.doc.portcullis_bars_usagehelp,
groups = {castle_gate = 1, choppy = 1, flow_through = 1},
tiles = {
"castle_steel.png^(default_wood.png^[transformR90^[mask:castle_portcullis_mask.png)",
@ -33,6 +35,8 @@ minetest.register_node("castle_gates:portcullis_bars", {
minetest.register_node("castle_gates:portcullis_bars_bottom", {
drawtype = "nodebox",
description = S("Portcullis Bottom"),
_doc_items_longdesc = castle_gates.doc.portcullis_bars_bottom_longdesc,
_doc_items_usagehelp = castle_gates.doc.portcullis_bars_bottom_usagehelp,
groups = {castle_gate = 1, choppy = 1, flow_through = 1},
tiles = {
"castle_steel.png^(default_wood.png^[transformR90^[mask:castle_portcullis_mask.png)",
@ -98,6 +102,8 @@ minetest.register_craft({
minetest.register_node("castle_gates:gate_panel", {
drawtype = "nodebox",
description = S("Gate Door"),
_doc_items_longdesc = castle_gates.doc.gate_panel_longdesc,
_doc_items_usagehelp = castle_gates.doc.gate_panel_usagehelp,
groups = {choppy = 1, castle_gate = 1},
tiles = {
"default_wood.png^[transformR90",
@ -128,6 +134,8 @@ minetest.register_craft({
minetest.register_node("castle_gates:gate_edge", {
drawtype = "nodebox",
description = S("Gate Door Edge"),
_doc_items_longdesc = castle_gates.doc.gate_edge_longdesc,
_doc_items_usagehelp = castle_gates.doc.gate_edge_usagehelp,
groups = {choppy = 1, castle_gate = 1},
tiles = {
"default_wood.png^[transformR90",
@ -165,6 +173,8 @@ minetest.register_craft({
minetest.register_node("castle_gates:gate_edge_handle", {
drawtype = "nodebox",
description = S("Gate Door With Handle"),
_doc_items_longdesc = castle_gates.doc.gate_edge_handle_longdesc,
_doc_items_usagehelp = castle_gates.doc.gate_edge_handle_usagehelp,
groups = {choppy = 1, castle_gate = 1},
tiles = {
"castle_steel.png^(default_wood.png^[mask:castle_door_side_mask.png^[transformR90)",
@ -206,6 +216,8 @@ minetest.register_craft({
minetest.register_node("castle_gates:gate_hinge", {
drawtype = "nodebox",
description = S("Gate Door With Hinge"),
_doc_items_longdesc = castle_gates.doc.gate_hinge_longdesc,
_doc_items_usagehelp = castle_gates.doc.gate_hinge_usagehelp,
groups = {choppy = 1, castle_gate = 1},
tiles = {
"default_wood.png^[transformR90",

View File

@ -1,6 +1,7 @@
castle_gates = {}
local modpath = minetest.get_modpath(minetest.get_current_modname())
dofile(modpath.."/doc.lua")
dofile(modpath.."/gate_functions.lua")
dofile(modpath.."/gate_slots.lua")
dofile(modpath.."/gates.lua")