2 local function initialize_data(meta
)
3 local commands
= minetest
.formspec_escape(meta
:get_string("commands"))
6 local function construct(pos
)
7 local meta
= minetest
.get_meta(pos
)
9 meta
:set_string("commands", "")
13 local function after_place(pos
, placer
)
15 local meta
= minetest
.get_meta(pos
)
20 local function resolve_commands(commands
, pos
)
21 local players
= minetest
.get_connected_players()
23 -- No players online: remove all commands containing
24 -- @nearest, @farthest and @random
26 commands
= commands
:gsub("[^\r\n]+", function (line
)
27 if line
:find("@nearest") then return "" end
28 if line
:find("@farthest") then return "" end
29 if line
:find("@random") then return "" end
35 local nearest
, farthest
= nil, nil
36 local min_distance
, max_distance
= math
.huge
, -1
37 for index
, player
in pairs(players
) do
38 local distance
= vector
.distance(pos
, player
:getpos())
39 if distance
< min_distance
then
40 min_distance
= distance
41 nearest
= player
:get_player_name()
43 if distance
> max_distance
then
44 max_distance
= distance
45 farthest
= player
:get_player_name()
48 local random = players
[math
.random(#players
)]:get_player_name()
49 commands
= commands
:gsub("@nearest", nearest
)
50 commands
= commands
:gsub("@farthest", farthest
)
51 commands
= commands
:gsub("@random", random)
55 local function check_commands(commands
, player_name
)
56 for _
, command
in pairs(commands
:split("\n")) do
57 local pos
= command
:find(" ")
58 local cmd
, param
= command
, ""
60 cmd
= command
:sub(1, pos
- 1)
62 local cmddef
= minetest
.chatcommands
[cmd
]
64 -- Invalid chat command
65 msg
= "Error: The command “"..cmd
.."” does not exist; your command block has not been changed. Use the “help” chat command for a list of available commands."
66 if string.sub(cmd
, 1, 1) == "/" then
67 msg
= msg
.. " Hint: Try to remove the trailing slash."
72 local player_privs
= minetest
.get_player_privs(player_name
)
74 for cmd_priv
, _
in pairs(cmddef
.privs
) do
75 if player_privs
[cmd_priv
] ~= true then
76 local msg
= "Error: You have insufficient privileges to use the command “"..cmd
.."” (missing privilege: "..cmd_priv
..")! The command block has not been changed."
85 local function commandblock_action_on(pos
, node
)
86 if node
.name
~= "mesecons_commandblock:commandblock_off" then
90 minetest
.swap_node(pos
, {name
= "mesecons_commandblock:commandblock_on"})
92 local meta
= minetest
.get_meta(pos
)
94 local commands
= resolve_commands(meta
:get_string("commands"), pos
)
95 for _
, command
in pairs(commands
:split("\n")) do
96 local pos
= command
:find(" ")
97 local cmd
, param
= command
, ""
99 cmd
= command
:sub(1, pos
- 1)
100 param
= command
:sub(pos
+ 1)
102 local cmddef
= minetest
.chatcommands
[cmd
]
104 -- Invalid chat command
107 local dummy_player
= ""
108 cmddef
.func(dummy_player
, param
)
112 local function commandblock_action_off(pos
, node
)
113 if node
.name
== "mesecons_commandblock:commandblock_on" then
114 minetest
.swap_node(pos
, {name
= "mesecons_commandblock:commandblock_off"})
118 local on_rightclick
= function(pos
, node
, player
, itemstack
, pointed_thing
)
119 -- Only allow access in Creative Mode
120 if not minetest
.settings
:get_bool("creative_mode") then
123 local privs
= minetest
.get_player_privs(player
:get_player_name())
124 if not privs
.maphack
then
125 minetest
.chat_send_player(player
:get_player_name(), "Access denied. You need the “maphack” privilege to edit command blocks.")
129 local meta
= minetest
.get_meta(pos
)
130 local commands
= meta
:get_string("commands")
131 local formspec
= "invsize[9,5;]" ..
132 "textarea[0.5,0.5;8.5,4;commands;Commands;"..commands
.."]" ..
133 "button_exit[3.3,4.5;2,1;submit;Submit]" ..
134 "image_button[8,4.5;1,1;doc_button_icon_lores.png;doc;]" ..
136 minetest
.show_formspec(player
:get_player_name(), "commandblock_"..pos
.x
.."_"..pos
.y
.."_"..pos
.z
, formspec
)
139 local on_place
= function(itemstack
, placer
, pointed_thing
)
140 if pointed_thing
.type ~= "node" then
144 -- Use pointed node's on_rightclick function first, if present
145 local node
= minetest
.get_node(pointed_thing
.under
)
146 if placer
and not placer
:get_player_control().sneak
then
147 if minetest
.registered_nodes
[node
.name
] and minetest
.registered_nodes
[node
.name
].on_rightclick
then
148 return minetest
.registered_nodes
[node
.name
].on_rightclick(pointed_thing
.under
, node
, placer
, itemstack
) or itemstack
152 local privs
= minetest
.get_player_privs(placer
:get_player_name())
153 if not privs
.maphack
then
154 minetest
.chat_send_player(placer
:get_player_name(), "Placement denied. You need the “maphack” privilege to place command blocks.")
158 return minetest
.item_place_node(itemstack
, placer
, pointed_thing
)
161 minetest
.register_node("mesecons_commandblock:commandblock_off", {
162 description
= "Command Block",
164 _doc_items_longdesc
=
165 "Command blocks are mighty redstone components which are able to alter reality itself. In other words, they cause the server to execute server commands when they are supplied with redstone power.",
166 _doc_items_usagehelp
=
167 [[To use an already existing command block, just supply it with redstone power and see what happens. This will execute the commands once. To execute the commands again, turn the redstone power off and on again.
169 To place a command block and change the commands, you need to be in Creative Mode and must have the “maphack” privilege. A new command block does not have any commands and does nothing. Rightclick the command block (in Creative Mode!) to edit its commands. Read the help entry “Advanced topics > Server Commands” to understand how they work. Each line contains a single command. You enter them like you would in the console, but without the leading slash. The commands will be executed from top to bottom.
171 You can optionally use the following placeholders in your commands:
172 • “@nearest” is replaced by the name of the player nearest to the command block
173 • “@farthest” is replaced by the name of the player farthest away from the command block
174 • “@random” is replaced by the name of a random player currently connected
179 Sets the game clock to 12:00
182 give @nearest mcl_core:apple 5
184 → Gives the nearest player 5 apples]],
186 tiles
= {{name
="jeija_commandblock_off.png", animation
={type="vertical_frames", aspect_w
=32, aspect_h
=32, length
=2}}},
187 groups
= {creative_breakable
=1, mesecon_effector_off
=1},
189 on_blast
= function() end,
190 on_construct
= construct
,
191 is_ground_content
= false,
193 after_place_node
= after_place
,
194 on_rightclick
= on_rightclick
,
195 sounds
= mcl_sounds
.node_sound_stone_defaults(),
196 mesecons
= {effector
= {
197 action_on
= commandblock_action_on
,
198 rules
= mesecon
.rules
.alldirs
,
200 _mcl_blast_resistance
= 18000000,
204 minetest
.register_node("mesecons_commandblock:commandblock_on", {
205 tiles
= {{name
="jeija_commandblock_off.png", animation
={type="vertical_frames", aspect_w
=32, aspect_h
=32, length
=2}}},
206 groups
= {creative_breakable
=1, mesecon_effector_on
=1, not_in_creative_inventory
=1},
208 on_blast
= function() end,
209 on_construct
= construct
,
210 is_ground_content
= false,
212 after_place_node
= after_place
,
213 on_rightclick
= on_rightclick
,
214 sounds
= mcl_sounds
.node_sound_stone_defaults(),
215 mesecons
= {effector
= {
216 action_off
= commandblock_action_off
,
217 rules
= mesecon
.rules
.alldirs
,
219 _mcl_blast_resistance
= 18000000,
223 minetest
.register_on_player_receive_fields(function(player
, formname
, fields
)
224 if string.sub(formname
, 1, 13) == "commandblock_" then
225 if not fields
.submit
and not fields
.doc
then
228 local privs
= minetest
.get_player_privs(player
:get_player_name())
229 if not privs
.maphack
then
230 minetest
.chat_send_player(player
:get_player_name(), "Access denied. You need the “maphack” privilege to edit command blocks.")
234 if fields
.doc
and minetest
.get_modpath("doc") then
235 doc
.show_entry(player
:get_player_name(), "nodes", "mesecons_commandblock:commandblock_off", true)
238 local index
, _
, x
, y
, z
= string.find(formname
, "commandblock_(-?%d+)_(-?%d+)_(-?%d+)")
239 if index
~= nil and x
~= nil and y
~= nil and z
~= nil then
240 local pos
= {x
=tonumber(x
), y
=tonumber(y
), z
=tonumber(z
)}
241 local meta
= minetest
.get_meta(pos
)
242 if not minetest
.settings
:get_bool("creative_mode") then
243 minetest
.chat_send_player(player
:get_player_name(), "Editing the command block has failed! You can only change the command block in Creative Mode!")
246 local check
, error_message
= check_commands(fields
.commands
, player
:get_player_name())
247 if check
== false then
248 -- Command block rejected
249 minetest
.chat_send_player(player
:get_player_name(), error_message
)
252 meta
:set_string("commands", fields
.commands
)
253 initialize_data(meta
)
256 minetest
.chat_send_player(player
:get_player_name(), "Editing the command block has failed! The command block is gone.")
261 -- Add entry alias for the Help
262 if minetest
.get_modpath("doc") then
263 doc
.add_entry_alias("nodes", "mesecons_commandblock:commandblock_off", "nodes", "mesecons_commandblock:commandblock_on")