2227 lines
52 KiB
Lua
2227 lines
52 KiB
Lua
local MP = minetest.get_modpath(
|
|
minetest.get_current_modname(
|
|
)
|
|
)
|
|
|
|
local S, NS = dofile(
|
|
MP .. "/intllib.lua"
|
|
)
|
|
|
|
minetest.register_privilege(
|
|
'student',
|
|
{
|
|
description = S(
|
|
"player is affected by bulk commands targeted at students"
|
|
),
|
|
give_to_singleplayer = false,
|
|
}
|
|
)
|
|
|
|
minetest.register_privilege(
|
|
'teacher',
|
|
{
|
|
description = S(
|
|
"player can apply bulk commands targeted at students"
|
|
),
|
|
give_to_singleplayer = false,
|
|
}
|
|
)
|
|
|
|
local on_join_handlers = {
|
|
}
|
|
|
|
local last_one_shot = 0
|
|
|
|
local register_one_shot = function(
|
|
name,
|
|
action
|
|
)
|
|
last_one_shot = last_one_shot + 1
|
|
local this_one_shot = last_one_shot
|
|
local handler_id = "one_shot_" .. this_one_shot
|
|
on_join_handlers[
|
|
handler_id
|
|
] = {
|
|
func = function(
|
|
joining_player,
|
|
joining_name
|
|
)
|
|
if name == joining_name then
|
|
action(
|
|
joining_player,
|
|
joining_name
|
|
)
|
|
on_join_handlers[
|
|
handler_id
|
|
] = nil
|
|
end
|
|
end,
|
|
}
|
|
end
|
|
|
|
local for_all_students = function(
|
|
action
|
|
)
|
|
local found = 0
|
|
for _, player in pairs(
|
|
minetest.get_connected_players(
|
|
)
|
|
) do
|
|
local name = player:get_player_name(
|
|
)
|
|
local privs = minetest.get_player_privs(
|
|
name
|
|
)
|
|
if true == privs[
|
|
"student"
|
|
] then
|
|
found = found + 1
|
|
action(
|
|
player,
|
|
name
|
|
)
|
|
end
|
|
end
|
|
if 0 == found then
|
|
return false
|
|
else
|
|
return found
|
|
end
|
|
end
|
|
|
|
local for_all_students_within_area = function(
|
|
boundaries,
|
|
action
|
|
)
|
|
local found = 0
|
|
for _, player in pairs(
|
|
minetest.get_connected_players(
|
|
)
|
|
) do
|
|
local name = player:get_player_name(
|
|
)
|
|
local privs = minetest.get_player_privs(
|
|
name
|
|
)
|
|
if true == privs[
|
|
"student"
|
|
] then
|
|
local within_area = true
|
|
local pos = player:get_pos(
|
|
)
|
|
for axis, value in pairs(
|
|
pos
|
|
) do
|
|
if value < boundaries.min[
|
|
axis
|
|
] then
|
|
within_area = false
|
|
end
|
|
if boundaries.max[
|
|
axis
|
|
] < value then
|
|
within_area = false
|
|
end
|
|
end
|
|
if within_area then
|
|
found = found + 1
|
|
action(
|
|
player,
|
|
name
|
|
)
|
|
end
|
|
end
|
|
end
|
|
if 0 == found then
|
|
return false
|
|
else
|
|
return found
|
|
end
|
|
end
|
|
|
|
local digtime = 42
|
|
|
|
local caps = {
|
|
times = {
|
|
digtime,
|
|
digtime,
|
|
digtime
|
|
},
|
|
uses = 0,
|
|
maxlevel = 256
|
|
}
|
|
|
|
minetest.register_item(
|
|
"edutest_chatcommands:creative_hand",
|
|
{
|
|
type = "none",
|
|
wield_image = "wieldhand.png",
|
|
wield_scale = {
|
|
x = 1,
|
|
y = 1,
|
|
z = 2.5
|
|
},
|
|
range = 10,
|
|
tool_capabilities = {
|
|
full_punch_interval = 0.5,
|
|
max_drop_level = 3,
|
|
groupcaps = {
|
|
crumbly = caps,
|
|
cracky = caps,
|
|
snappy = caps,
|
|
choppy = caps,
|
|
oddly_breakable_by_hand = caps,
|
|
},
|
|
damage_groups = {
|
|
fleshy = 10
|
|
},
|
|
}
|
|
}
|
|
)
|
|
|
|
minetest.register_item(
|
|
"edutest_chatcommands:basic_hand",
|
|
{
|
|
type = "none",
|
|
wield_image = "wieldhand.png",
|
|
wield_scale = {
|
|
x = 1,
|
|
y = 1,
|
|
z = 2.5
|
|
},
|
|
tool_capabilities = {
|
|
full_punch_interval = 0.9,
|
|
max_drop_level = 0,
|
|
groupcaps = {
|
|
crumbly = {
|
|
times={
|
|
[2] = 3.00,
|
|
[3] = 0.70
|
|
},
|
|
uses = 0,
|
|
maxlevel = 1
|
|
},
|
|
snappy = {
|
|
times={
|
|
[3] = 0.40
|
|
},
|
|
uses = 0,
|
|
maxlevel = 1
|
|
},
|
|
oddly_breakable_by_hand = {
|
|
times = {
|
|
[1] = 3.50,
|
|
[2] = 2.00,
|
|
[3] = 0.70
|
|
},
|
|
uses = 0
|
|
}
|
|
},
|
|
damage_groups = {
|
|
fleshy = 1
|
|
},
|
|
}
|
|
}
|
|
)
|
|
|
|
local player_block_position = function(
|
|
name
|
|
)
|
|
local pos = minetest.get_player_by_name(
|
|
name
|
|
):getpos(
|
|
)
|
|
return {
|
|
x = math.floor(
|
|
pos.x + 0.5
|
|
),
|
|
y = math.floor(
|
|
pos.y + 0.5
|
|
),
|
|
z = math.floor(
|
|
pos.z + 0.5
|
|
),
|
|
}
|
|
end
|
|
|
|
local split_command = function(
|
|
command_string
|
|
)
|
|
local delimiter = ""
|
|
local params = ""
|
|
local command
|
|
local first = true
|
|
for argument in string.gmatch(
|
|
command_string,
|
|
"[^ ]+"
|
|
) do
|
|
if first then
|
|
command = argument
|
|
first = false
|
|
else
|
|
params = params .. delimiter .. argument
|
|
delimiter = " "
|
|
end
|
|
end
|
|
return command, params
|
|
end
|
|
|
|
local active_marker = nil
|
|
|
|
local highlight_marker_click_handler = function(
|
|
self,
|
|
clicker
|
|
)
|
|
end
|
|
|
|
local set_highlight_marker_click_handler = function(
|
|
handler
|
|
)
|
|
highlight_marker_click_handler = handler
|
|
end
|
|
|
|
local entity_selection_box = "selectionbox"
|
|
|
|
if not minetest.features.object_independent_selectionbox then
|
|
entity_selection_box = "collisionbox"
|
|
end
|
|
|
|
local player_highlighted = {
|
|
}
|
|
|
|
local player_markers = {
|
|
}
|
|
|
|
local player_groups = {
|
|
}
|
|
|
|
local marker_properties = {
|
|
initial_properties = {
|
|
visual = "upright_sprite",
|
|
textures = {
|
|
"area_highlight_hex.png"
|
|
},
|
|
physical = false,
|
|
},
|
|
on_activate = function(
|
|
self,
|
|
staticdata
|
|
)
|
|
local data = minetest.deserialize(
|
|
staticdata
|
|
)
|
|
if not data then
|
|
print(
|
|
"EDUtest no marker data given, removing"
|
|
)
|
|
self.object:remove(
|
|
)
|
|
return
|
|
end
|
|
if data[
|
|
"object_propertios"
|
|
] then
|
|
self.object:set_properties(
|
|
data[
|
|
"object_propertios"
|
|
]
|
|
)
|
|
data[
|
|
"object_propertios"
|
|
] = nil
|
|
end
|
|
if data[
|
|
"player_name"
|
|
] then
|
|
if not data[
|
|
"marker_id"
|
|
] then
|
|
print(
|
|
"EDUtest marker id missing, removing"
|
|
)
|
|
self.object:remove(
|
|
)
|
|
return
|
|
end
|
|
if not player_markers[
|
|
data[
|
|
"player_name"
|
|
]
|
|
] then
|
|
player_markers[
|
|
data[
|
|
"player_name"
|
|
]
|
|
] = {
|
|
}
|
|
end
|
|
player_markers[
|
|
data[
|
|
"player_name"
|
|
]
|
|
][
|
|
data[
|
|
"marker_id"
|
|
]
|
|
] = self.object
|
|
end
|
|
for k, v in pairs(
|
|
data
|
|
) do
|
|
self[
|
|
k
|
|
] = v
|
|
end
|
|
end,
|
|
on_step = function(
|
|
self,
|
|
dtime
|
|
)
|
|
if not active_marker then
|
|
self.object:remove(
|
|
)
|
|
end
|
|
end,
|
|
on_rightclick = function(
|
|
self,
|
|
clicker
|
|
)
|
|
return highlight_marker_click_handler(
|
|
self,
|
|
clicker
|
|
)
|
|
end,
|
|
get_staticdata = function(
|
|
self
|
|
)
|
|
local serializable = {
|
|
}
|
|
for k,v in pairs(
|
|
self
|
|
) do
|
|
local value_type = type(
|
|
v
|
|
)
|
|
if (
|
|
'userdata' ~= value_type
|
|
and 'function' ~= value_type
|
|
) then
|
|
serializable[
|
|
k
|
|
] = v
|
|
end
|
|
end
|
|
serializable[
|
|
"object_propertios"
|
|
] = self.object:get_properties(
|
|
)
|
|
return minetest.serialize(
|
|
serializable
|
|
)
|
|
end,
|
|
range = nil,
|
|
player_name = nil,
|
|
marker_id = nil,
|
|
}
|
|
|
|
minetest.register_entity(
|
|
":edutest:highlight_marker",
|
|
marker_properties
|
|
)
|
|
|
|
local set_highlight_marker_tooltip = function(
|
|
tooltip
|
|
)
|
|
minetest.registered_entities[
|
|
"edutest:highlight_marker"
|
|
].initial_properties.infotext = tooltip
|
|
end
|
|
|
|
local storage = minetest.get_mod_storage(
|
|
)
|
|
|
|
for group in string.gmatch(
|
|
storage:get_string(
|
|
"player_groups"
|
|
),
|
|
"[^ ]+"
|
|
) do
|
|
if "" ~= group then
|
|
player_groups[
|
|
group
|
|
] = {
|
|
}
|
|
end
|
|
end
|
|
|
|
for group, v in pairs(
|
|
player_groups
|
|
) do
|
|
for player in string.gmatch(
|
|
storage:get_string(
|
|
"player_group_" .. group
|
|
),
|
|
"[^ ]+"
|
|
) do
|
|
if "" ~= player then
|
|
player_groups[
|
|
group
|
|
][
|
|
player
|
|
] = 1
|
|
end
|
|
end
|
|
end
|
|
|
|
local collapse_keys = function(
|
|
collapsed
|
|
)
|
|
local delimiter = ""
|
|
local list = ""
|
|
for k, v in pairs(
|
|
collapsed
|
|
) do
|
|
list = list .. delimiter .. k
|
|
delimiter = " "
|
|
end
|
|
return list
|
|
end
|
|
|
|
local for_all_groups = function(
|
|
action
|
|
)
|
|
local found = 0
|
|
for name, content in pairs(
|
|
player_groups
|
|
) do
|
|
found = found + 1
|
|
action(
|
|
name,
|
|
content
|
|
)
|
|
end
|
|
if 0 == found then
|
|
return false
|
|
else
|
|
return found
|
|
end
|
|
end
|
|
|
|
local for_all_members = function(
|
|
group,
|
|
action
|
|
)
|
|
local found = 0
|
|
for name, v in pairs(
|
|
player_groups[
|
|
group
|
|
]
|
|
) do
|
|
found = found + 1
|
|
local player = minetest.get_player_by_name(
|
|
name
|
|
)
|
|
action(
|
|
player,
|
|
name
|
|
)
|
|
end
|
|
if 0 == found then
|
|
return false
|
|
else
|
|
return found
|
|
end
|
|
end
|
|
|
|
local edge_boundaries = function(
|
|
pos1,
|
|
pos2
|
|
)
|
|
local boundaries = {
|
|
}
|
|
for _, extreme in ipairs(
|
|
{
|
|
"min",
|
|
"max",
|
|
}
|
|
) do
|
|
boundaries[
|
|
extreme
|
|
] = {
|
|
}
|
|
for axis, value in pairs(
|
|
pos1
|
|
) do
|
|
boundaries[
|
|
extreme
|
|
][
|
|
axis
|
|
] = math[
|
|
extreme
|
|
](
|
|
value,
|
|
pos2[
|
|
axis
|
|
]
|
|
)
|
|
end
|
|
end
|
|
return boundaries
|
|
end
|
|
|
|
local highlight_positions = function(
|
|
name
|
|
)
|
|
active_marker = 1
|
|
local pos = edge_boundaries(
|
|
player_highlighted[
|
|
name
|
|
].pos1,
|
|
player_highlighted[
|
|
name
|
|
].pos2
|
|
)
|
|
local markers = {
|
|
}
|
|
for _, axis in ipairs(
|
|
{
|
|
{
|
|
displacement = "z",
|
|
range = "x",
|
|
rotation = 0,
|
|
},
|
|
{
|
|
displacement = "x",
|
|
range = "z",
|
|
rotation = math.pi / 2,
|
|
},
|
|
}
|
|
) do
|
|
for _, displaced in ipairs(
|
|
{
|
|
pos.min[
|
|
axis.displacement
|
|
] - 0.5,
|
|
pos.max[
|
|
axis.displacement
|
|
] + 0.5,
|
|
}
|
|
) do
|
|
local marker_pos = {
|
|
x = (
|
|
pos.min.x + pos.max.x
|
|
) / 2,
|
|
y = (
|
|
pos.min.y + pos.max.y
|
|
) / 2,
|
|
z = (
|
|
pos.min.z + pos.max.z
|
|
) / 2,
|
|
}
|
|
marker_pos[
|
|
axis.displacement
|
|
] = displaced
|
|
local marker = minetest.add_entity(
|
|
marker_pos,
|
|
"edutest:highlight_marker",
|
|
minetest.serialize(
|
|
{
|
|
}
|
|
)
|
|
)
|
|
marker:set_yaw(
|
|
axis.rotation
|
|
)
|
|
local selection_sizes = {
|
|
}
|
|
selection_sizes[
|
|
axis.range
|
|
] = 0.5 * (
|
|
pos.max[
|
|
axis.range
|
|
] - pos.min[
|
|
axis.range
|
|
] + 1
|
|
)
|
|
selection_sizes[
|
|
axis.displacement
|
|
] = 0.1
|
|
selection_sizes[
|
|
"y"
|
|
] = 0.5 * (
|
|
pos.max.y - pos.min.y + 1
|
|
)
|
|
local marker_properties = {
|
|
visual_size = {
|
|
x = pos.max[
|
|
axis.range
|
|
] - pos.min[
|
|
axis.range
|
|
] + 1,
|
|
y = pos.max.y - pos.min.y + 1,
|
|
},
|
|
}
|
|
marker_properties[
|
|
entity_selection_box
|
|
] = {
|
|
-1.0 * selection_sizes.x,
|
|
-1.0 * selection_sizes.y,
|
|
-1.0 * selection_sizes.z,
|
|
selection_sizes.x,
|
|
selection_sizes.y,
|
|
selection_sizes.z,
|
|
}
|
|
marker:get_luaentity(
|
|
).range = axis.range
|
|
local marker_id = axis.displacement .. displaced
|
|
marker:get_luaentity(
|
|
).marker_id = marker_id
|
|
marker:get_luaentity(
|
|
).player_name = name
|
|
marker:set_properties(
|
|
marker_properties
|
|
)
|
|
markers[
|
|
marker_id
|
|
] = marker
|
|
end
|
|
end
|
|
if player_markers[
|
|
name
|
|
] then
|
|
for k, v in pairs(
|
|
player_markers[
|
|
name
|
|
]
|
|
) do
|
|
v:remove(
|
|
)
|
|
end
|
|
end
|
|
player_markers[
|
|
name
|
|
] = markers
|
|
end
|
|
|
|
local adapt_highlighted_area = function(
|
|
name,
|
|
axis,
|
|
extreme,
|
|
adjustment
|
|
)
|
|
local selected_value = math[
|
|
extreme
|
|
](
|
|
player_highlighted[
|
|
name
|
|
].pos1[
|
|
axis
|
|
],
|
|
player_highlighted[
|
|
name
|
|
].pos2[
|
|
axis
|
|
]
|
|
)
|
|
local selected_edge = nil
|
|
for edge, coordinates in pairs(
|
|
player_highlighted[
|
|
name
|
|
]
|
|
) do
|
|
if selected_value == coordinates[
|
|
axis
|
|
] then
|
|
selected_edge = edge
|
|
end
|
|
end
|
|
player_highlighted[
|
|
name
|
|
][
|
|
selected_edge
|
|
][
|
|
axis
|
|
] = player_highlighted[
|
|
name
|
|
][
|
|
selected_edge
|
|
][
|
|
axis
|
|
] + adjustment
|
|
highlight_positions(
|
|
name
|
|
)
|
|
end
|
|
|
|
minetest.register_chatcommand(
|
|
"create_group",
|
|
{
|
|
params = "<" .. S(
|
|
"group name"
|
|
) .. ">",
|
|
description = S(
|
|
"create a group of players"
|
|
),
|
|
privs = {
|
|
teacher = true,
|
|
},
|
|
func = function(
|
|
own_name,
|
|
param
|
|
)
|
|
local name = nil
|
|
if "" == param then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. S(
|
|
"group name must be specified"
|
|
)
|
|
)
|
|
return
|
|
else
|
|
name = param
|
|
end
|
|
if player_groups[
|
|
name
|
|
] then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. S(
|
|
"group already exists"
|
|
)
|
|
)
|
|
return
|
|
end
|
|
player_groups[
|
|
name
|
|
] = {
|
|
}
|
|
storage:set_string(
|
|
"player_groups",
|
|
collapse_keys(
|
|
player_groups
|
|
)
|
|
)
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. string.format(
|
|
S(
|
|
"group named %s created"
|
|
),
|
|
name
|
|
)
|
|
)
|
|
end
|
|
}
|
|
)
|
|
|
|
minetest.register_chatcommand(
|
|
"delete_group",
|
|
{
|
|
params = "<" .. S(
|
|
"group name"
|
|
) .. ">",
|
|
description = S(
|
|
"delete a group of players"
|
|
),
|
|
privs = {
|
|
teacher = true,
|
|
},
|
|
func = function(
|
|
own_name,
|
|
param
|
|
)
|
|
local name = nil
|
|
if "" == param then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. S(
|
|
"group name must be specified"
|
|
)
|
|
)
|
|
return
|
|
else
|
|
name = param
|
|
end
|
|
if not player_groups[
|
|
name
|
|
] then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. S(
|
|
"group does not exists"
|
|
)
|
|
)
|
|
return
|
|
end
|
|
player_groups[
|
|
name
|
|
] = nil
|
|
storage:set_string(
|
|
"player_groups",
|
|
collapse_keys(
|
|
player_groups
|
|
)
|
|
)
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. string.format(
|
|
S(
|
|
"group named %s deleted"
|
|
),
|
|
name
|
|
)
|
|
)
|
|
end
|
|
}
|
|
)
|
|
|
|
minetest.register_chatcommand(
|
|
"enter_group",
|
|
{
|
|
params = "<" .. S(
|
|
"group name"
|
|
) .. "> <" .. S(
|
|
"player name"
|
|
) .. ">",
|
|
description = S(
|
|
"add a player to a group"
|
|
),
|
|
privs = {
|
|
teacher = true,
|
|
},
|
|
func = function(
|
|
own_name,
|
|
param
|
|
)
|
|
local player = nil
|
|
local group = nil
|
|
local first = true
|
|
for argument in string.gmatch(
|
|
param,
|
|
"[^ ]+"
|
|
) do
|
|
if player then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. S(
|
|
"too many parameters given"
|
|
)
|
|
)
|
|
return
|
|
end
|
|
if first then
|
|
group = argument
|
|
first = false
|
|
else
|
|
player = argument
|
|
local name = nil
|
|
end
|
|
end
|
|
if not group then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. S(
|
|
"group name must be specified"
|
|
)
|
|
)
|
|
return
|
|
end
|
|
if not player then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. S(
|
|
"player name must be specified"
|
|
)
|
|
)
|
|
return
|
|
end
|
|
if not player_groups[
|
|
group
|
|
] then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. S(
|
|
"group does not exists"
|
|
)
|
|
)
|
|
return
|
|
end
|
|
if player_groups[
|
|
group
|
|
][
|
|
player
|
|
] then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. S(
|
|
"player already belongs to the group"
|
|
)
|
|
)
|
|
return
|
|
end
|
|
player_groups[
|
|
group
|
|
][
|
|
player
|
|
] = 1
|
|
storage:set_string(
|
|
"player_group_" .. group,
|
|
collapse_keys(
|
|
player_groups[
|
|
group
|
|
]
|
|
)
|
|
)
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. string.format(
|
|
S(
|
|
"player %s added to group named %s"
|
|
),
|
|
player,
|
|
group
|
|
)
|
|
)
|
|
end
|
|
}
|
|
)
|
|
|
|
minetest.register_chatcommand(
|
|
"leave_group",
|
|
{
|
|
params = "<" .. S(
|
|
"group name"
|
|
) .. "> <" .. S(
|
|
"player name"
|
|
) .. ">",
|
|
description = S(
|
|
"remove a player from a group"
|
|
),
|
|
privs = {
|
|
teacher = true,
|
|
},
|
|
func = function(
|
|
own_name,
|
|
param
|
|
)
|
|
local player = nil
|
|
local group = nil
|
|
local first = true
|
|
for argument in string.gmatch(
|
|
param,
|
|
"[^ ]+"
|
|
) do
|
|
if player then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. S(
|
|
"too many parameters given"
|
|
)
|
|
)
|
|
return
|
|
end
|
|
if first then
|
|
group = argument
|
|
first = false
|
|
else
|
|
player = argument
|
|
local name = nil
|
|
end
|
|
end
|
|
if not group then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. S(
|
|
"group name must be specified"
|
|
)
|
|
)
|
|
return
|
|
end
|
|
if not player then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. S(
|
|
"player name must be specified"
|
|
)
|
|
)
|
|
return
|
|
end
|
|
if not player_groups[
|
|
group
|
|
] then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. S(
|
|
"group does not exists"
|
|
)
|
|
)
|
|
return
|
|
end
|
|
if not player_groups[
|
|
group
|
|
][
|
|
player
|
|
] then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. S(
|
|
"player does not belong to the group"
|
|
)
|
|
)
|
|
return
|
|
end
|
|
player_groups[
|
|
group
|
|
][
|
|
player
|
|
] = nil
|
|
storage:set_string(
|
|
"player_group_" .. group,
|
|
collapse_keys(
|
|
player_groups[
|
|
group
|
|
]
|
|
)
|
|
)
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. string.format(
|
|
S(
|
|
"player %s removed from group named %s"
|
|
),
|
|
player,
|
|
group
|
|
)
|
|
)
|
|
end
|
|
}
|
|
)
|
|
|
|
minetest.register_chatcommand(
|
|
"highlight_pos1",
|
|
{
|
|
params = "",
|
|
description = S(
|
|
"set position 1 of the highlighted area"
|
|
),
|
|
privs = {
|
|
},
|
|
func = function(
|
|
own_name,
|
|
param
|
|
)
|
|
local pos = player_block_position(
|
|
own_name
|
|
)
|
|
if not player_highlighted[
|
|
own_name
|
|
] then
|
|
player_highlighted[
|
|
own_name
|
|
] = {
|
|
}
|
|
end
|
|
player_highlighted[
|
|
own_name
|
|
].pos1 = pos
|
|
if not player_highlighted[
|
|
own_name
|
|
].pos2 then
|
|
player_highlighted[
|
|
own_name
|
|
].pos2 = player_highlighted[
|
|
own_name
|
|
].pos1
|
|
end
|
|
highlight_positions(
|
|
own_name
|
|
)
|
|
end
|
|
}
|
|
)
|
|
|
|
minetest.register_chatcommand(
|
|
"highlight_pos2",
|
|
{
|
|
params = "",
|
|
description = S(
|
|
"set position 2 of the highlighted area"
|
|
),
|
|
privs = {
|
|
},
|
|
func = function(
|
|
own_name,
|
|
param
|
|
)
|
|
local pos = player_block_position(
|
|
own_name
|
|
)
|
|
if not player_highlighted[
|
|
own_name
|
|
] then
|
|
player_highlighted[
|
|
own_name
|
|
] = {
|
|
}
|
|
end
|
|
player_highlighted[
|
|
own_name
|
|
].pos2 = pos
|
|
if not player_highlighted[
|
|
own_name
|
|
].pos1 then
|
|
player_highlighted[
|
|
own_name
|
|
].pos1 = player_highlighted[
|
|
own_name
|
|
].pos2
|
|
end
|
|
highlight_positions(
|
|
own_name
|
|
)
|
|
end
|
|
}
|
|
)
|
|
|
|
local highlighted_areas = function(
|
|
player_name
|
|
)
|
|
if not player_highlighted[
|
|
player_name
|
|
] then
|
|
return nil
|
|
end
|
|
local center = {
|
|
x = (
|
|
player_highlighted[
|
|
player_name
|
|
].pos1.x + player_highlighted[
|
|
player_name
|
|
].pos2.x
|
|
) / 2.0,
|
|
y = (
|
|
player_highlighted[
|
|
player_name
|
|
].pos1.y + player_highlighted[
|
|
player_name
|
|
].pos2.y
|
|
) / 2.0,
|
|
z = (
|
|
player_highlighted[
|
|
player_name
|
|
].pos1.z + player_highlighted[
|
|
player_name
|
|
].pos2.z
|
|
) / 2.0,
|
|
}
|
|
return areas:getAreasAtPos(
|
|
center
|
|
)
|
|
end
|
|
|
|
minetest.register_chatcommand(
|
|
"highlight_areas",
|
|
{
|
|
params = "<" .. S(
|
|
"command"
|
|
) .. "> [" .. S(
|
|
"parameters"
|
|
) .. "...]",
|
|
description = S(
|
|
"apply areas command on highlighted area"
|
|
),
|
|
privs = {
|
|
areas = true,
|
|
},
|
|
func = function(
|
|
own_name,
|
|
param
|
|
)
|
|
if not player_highlighted[
|
|
own_name
|
|
] then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. string.format(
|
|
S(
|
|
"no area highlighted yet"
|
|
)
|
|
)
|
|
)
|
|
return
|
|
end
|
|
minetest.chatcommands[
|
|
"area_pos1"
|
|
].func(
|
|
own_name,
|
|
player_highlighted[
|
|
own_name
|
|
].pos1.x .. " " .. player_highlighted[
|
|
own_name
|
|
].pos1.y .. " " .. player_highlighted[
|
|
own_name
|
|
].pos1.z
|
|
)
|
|
minetest.chatcommands[
|
|
"area_pos2"
|
|
].func(
|
|
own_name,
|
|
player_highlighted[
|
|
own_name
|
|
].pos2.x .. " " .. player_highlighted[
|
|
own_name
|
|
].pos2.y .. " " .. player_highlighted[
|
|
own_name
|
|
].pos2.z
|
|
)
|
|
local command, params = split_command(
|
|
param
|
|
)
|
|
minetest.chatcommands[
|
|
command
|
|
].func(
|
|
own_name,
|
|
params
|
|
)
|
|
end
|
|
}
|
|
)
|
|
|
|
minetest.register_chatcommand(
|
|
"highlight_set_owner_group",
|
|
{
|
|
params = "<" .. S(
|
|
"group name"
|
|
) .. "> <" .. S(
|
|
"area name"
|
|
) .. ">",
|
|
description = S(
|
|
"make the highlighted area owned by a group"
|
|
),
|
|
privs = {
|
|
areas = true,
|
|
},
|
|
func = function(
|
|
own_name,
|
|
param
|
|
)
|
|
local group, area = param:match(
|
|
'^(%S+)%s(.+)$'
|
|
)
|
|
if not group then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. string.format(
|
|
S(
|
|
"group and area name must be specified"
|
|
)
|
|
)
|
|
)
|
|
return
|
|
end
|
|
if not player_highlighted[
|
|
own_name
|
|
] then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. string.format(
|
|
S(
|
|
"no area highlighted yet"
|
|
)
|
|
)
|
|
)
|
|
return
|
|
end
|
|
minetest.chatcommands[
|
|
"area_pos1"
|
|
].func(
|
|
own_name,
|
|
player_highlighted[
|
|
own_name
|
|
].pos1.x .. " " .. player_highlighted[
|
|
own_name
|
|
].pos1.y .. " " .. player_highlighted[
|
|
own_name
|
|
].pos1.z
|
|
)
|
|
minetest.chatcommands[
|
|
"area_pos2"
|
|
].func(
|
|
own_name,
|
|
player_highlighted[
|
|
own_name
|
|
].pos2.x .. " " .. player_highlighted[
|
|
own_name
|
|
].pos2.y .. " " .. player_highlighted[
|
|
own_name
|
|
].pos2.z
|
|
)
|
|
local before = highlighted_areas(
|
|
own_name
|
|
)
|
|
minetest.chatcommands[
|
|
"set_owner"
|
|
].func(
|
|
own_name,
|
|
minetest.settings:get(
|
|
"name"
|
|
) .. " " .. area
|
|
)
|
|
local after = highlighted_areas(
|
|
own_name
|
|
)
|
|
for id, v in pairs(
|
|
before
|
|
) do
|
|
after[
|
|
id
|
|
] = nil
|
|
end
|
|
local new_area_id
|
|
for id, v in pairs(
|
|
after
|
|
) do
|
|
new_area_id = id
|
|
end
|
|
if not for_all_members(
|
|
group,
|
|
function(
|
|
player,
|
|
name
|
|
)
|
|
minetest.chatcommands[
|
|
"add_owner"
|
|
].func(
|
|
own_name,
|
|
new_area_id .. " " .. name .. " " .. area
|
|
)
|
|
end
|
|
) then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. string.format(
|
|
S(
|
|
"no group members found"
|
|
)
|
|
)
|
|
)
|
|
end
|
|
minetest.chatcommands[
|
|
"remove_area"
|
|
].func(
|
|
own_name,
|
|
new_area_id
|
|
)
|
|
end
|
|
}
|
|
)
|
|
|
|
minetest.register_chatcommand(
|
|
"creative_hand",
|
|
{
|
|
params = "[" .. S(
|
|
"player name"
|
|
) .. "]",
|
|
description = S(
|
|
"set the empty hand of a player to creative mode characteristics"
|
|
),
|
|
privs = {
|
|
privs = true,
|
|
},
|
|
func = function(
|
|
own_name,
|
|
param
|
|
)
|
|
local name = nil
|
|
if "" == param then
|
|
name = own_name
|
|
else
|
|
name = param
|
|
end
|
|
local player = minetest.get_player_by_name(
|
|
name
|
|
)
|
|
if not player then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. string.format(
|
|
S(
|
|
"cannot find a player named %s"
|
|
),
|
|
name
|
|
)
|
|
)
|
|
return
|
|
end
|
|
player:get_inventory(
|
|
):remove_item(
|
|
"hand",
|
|
"edutest_chatcommands:basic_hand"
|
|
)
|
|
player:get_inventory(
|
|
):add_item(
|
|
"hand",
|
|
"edutest_chatcommands:creative_hand"
|
|
)
|
|
end,
|
|
}
|
|
)
|
|
|
|
minetest.register_chatcommand(
|
|
"basic_hand",
|
|
{
|
|
params = "[" .. S(
|
|
"player name"
|
|
) .. "]",
|
|
description = S(
|
|
"set the empty hand of a player to survival mode characteristics"
|
|
),
|
|
privs = {
|
|
privs = true,
|
|
},
|
|
func = function(
|
|
own_name,
|
|
param
|
|
)
|
|
local name = nil
|
|
if "" == param then
|
|
name = own_name
|
|
else
|
|
name = param
|
|
end
|
|
local player = minetest.get_player_by_name(
|
|
name
|
|
)
|
|
if not player then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. string.format(
|
|
S(
|
|
"cannot find a player named %s"
|
|
),
|
|
name
|
|
)
|
|
)
|
|
return
|
|
end
|
|
player:get_inventory(
|
|
):remove_item(
|
|
"hand",
|
|
"edutest_chatcommands:creative_hand"
|
|
)
|
|
player:get_inventory(
|
|
):add_item(
|
|
"hand",
|
|
"edutest_chatcommands:basic_hand"
|
|
)
|
|
end,
|
|
}
|
|
)
|
|
|
|
minetest.register_chatcommand(
|
|
"student_join_keep_priv",
|
|
{
|
|
params = "<" .. S(
|
|
"privilege"
|
|
) .. ">",
|
|
description = S(
|
|
"keep privilege on student join"
|
|
),
|
|
privs = {
|
|
teacher = true,
|
|
},
|
|
func = function(
|
|
own_name,
|
|
param
|
|
)
|
|
on_join_handlers[
|
|
"privilege_" .. param
|
|
] = nil
|
|
end,
|
|
}
|
|
)
|
|
|
|
minetest.register_chatcommand(
|
|
"student_join_revoke",
|
|
{
|
|
params = "<" .. S(
|
|
"privilege"
|
|
) .. ">",
|
|
description = S(
|
|
"revoke privilege on student join"
|
|
),
|
|
privs = {
|
|
teacher = true,
|
|
},
|
|
func = function(
|
|
own_name,
|
|
param
|
|
)
|
|
on_join_handlers[
|
|
"privilege_" .. param
|
|
] = {
|
|
func = function(
|
|
player,
|
|
name
|
|
)
|
|
minetest.chatcommands[
|
|
"revoke"
|
|
].func(
|
|
own_name,
|
|
name .. " " .. param
|
|
)
|
|
end,
|
|
}
|
|
end,
|
|
}
|
|
)
|
|
|
|
minetest.register_chatcommand(
|
|
"student_join_grant",
|
|
{
|
|
params = "<" .. S(
|
|
"privilege"
|
|
) .. ">",
|
|
description = S(
|
|
"grant privilege on student join"
|
|
),
|
|
privs = {
|
|
teacher = true,
|
|
},
|
|
func = function(
|
|
own_name,
|
|
param
|
|
)
|
|
on_join_handlers[
|
|
"privilege_" .. param
|
|
] = {
|
|
func = function(
|
|
player,
|
|
name
|
|
)
|
|
minetest.chatcommands[
|
|
"grant"
|
|
].func(
|
|
own_name,
|
|
name .. " " .. param
|
|
)
|
|
end,
|
|
}
|
|
end,
|
|
}
|
|
)
|
|
|
|
minetest.register_chatcommand(
|
|
"list_students",
|
|
{
|
|
params = "",
|
|
description = S(
|
|
"list student player names"
|
|
),
|
|
privs = {
|
|
teacher = true,
|
|
},
|
|
func = function(
|
|
own_name,
|
|
param
|
|
)
|
|
if not for_all_students(
|
|
function(
|
|
player,
|
|
name
|
|
)
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. string.format(
|
|
S(
|
|
"found player %s"
|
|
),
|
|
name
|
|
)
|
|
)
|
|
end
|
|
) then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. string.format(
|
|
S(
|
|
"no student players found"
|
|
)
|
|
)
|
|
)
|
|
end
|
|
end,
|
|
}
|
|
)
|
|
|
|
minetest.register_chatcommand(
|
|
"list_groups",
|
|
{
|
|
params = "",
|
|
description = S(
|
|
"list group names"
|
|
),
|
|
privs = {
|
|
teacher = true,
|
|
},
|
|
func = function(
|
|
own_name,
|
|
param
|
|
)
|
|
if not for_all_groups(
|
|
function(
|
|
name,
|
|
players
|
|
)
|
|
local count = 0
|
|
for k, v in pairs(
|
|
players
|
|
) do
|
|
count = count + 1
|
|
end
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. string.format(
|
|
S(
|
|
"found group %s (player count %d)"
|
|
),
|
|
name,
|
|
count
|
|
)
|
|
)
|
|
end
|
|
) then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. string.format(
|
|
S(
|
|
"no groups configured"
|
|
)
|
|
)
|
|
)
|
|
end
|
|
end,
|
|
}
|
|
)
|
|
|
|
minetest.register_chatcommand(
|
|
"list_members",
|
|
{
|
|
params = "<" .. S(
|
|
"group name"
|
|
) .. ">",
|
|
description = S(
|
|
"list group member names"
|
|
),
|
|
privs = {
|
|
teacher = true,
|
|
},
|
|
func = function(
|
|
own_name,
|
|
param
|
|
)
|
|
local group = param
|
|
if not player_groups[
|
|
group
|
|
] then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. S(
|
|
"group does not exists"
|
|
)
|
|
)
|
|
return
|
|
end
|
|
if not for_all_members(
|
|
group,
|
|
function(
|
|
player,
|
|
name
|
|
)
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. string.format(
|
|
S(
|
|
"found player %s"
|
|
),
|
|
name
|
|
)
|
|
)
|
|
end
|
|
) then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. string.format(
|
|
S(
|
|
"no group members found"
|
|
)
|
|
)
|
|
)
|
|
end
|
|
end,
|
|
}
|
|
)
|
|
|
|
minetest.register_chatcommand(
|
|
"every_student",
|
|
{
|
|
params = "<" .. S(
|
|
"command"
|
|
) .. "> [" .. S(
|
|
"parameters"
|
|
) .. "...]",
|
|
description = S(
|
|
"apply command to all student players"
|
|
),
|
|
privs = {
|
|
teacher = true,
|
|
},
|
|
func = function(
|
|
own_name,
|
|
param
|
|
)
|
|
if not for_all_students(
|
|
function(
|
|
player,
|
|
name
|
|
)
|
|
local command, params = split_command(
|
|
string.gsub(
|
|
param,
|
|
"subject",
|
|
name
|
|
)
|
|
)
|
|
minetest.chatcommands[
|
|
command
|
|
].func(
|
|
own_name,
|
|
params
|
|
)
|
|
end
|
|
) then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. string.format(
|
|
S(
|
|
"no student players found"
|
|
)
|
|
)
|
|
)
|
|
end
|
|
end,
|
|
}
|
|
)
|
|
|
|
local edge_boundaries = function(
|
|
pos1,
|
|
pos2
|
|
)
|
|
local boundaries = {
|
|
}
|
|
for _, extreme in ipairs(
|
|
{
|
|
"min",
|
|
"max",
|
|
}
|
|
) do
|
|
boundaries[
|
|
extreme
|
|
] = {
|
|
}
|
|
for axis, value in pairs(
|
|
pos1
|
|
) do
|
|
boundaries[
|
|
extreme
|
|
][
|
|
axis
|
|
] = math[
|
|
extreme
|
|
](
|
|
value,
|
|
pos2[
|
|
axis
|
|
]
|
|
)
|
|
end
|
|
end
|
|
return boundaries
|
|
end
|
|
|
|
minetest.register_chatcommand(
|
|
"every_highlighted",
|
|
{
|
|
description = S(
|
|
"apply command to all student players within the highlighted area"
|
|
),
|
|
privs = {
|
|
teacher = true,
|
|
},
|
|
func = function(
|
|
own_name,
|
|
param
|
|
)
|
|
if not player_highlighted[
|
|
own_name
|
|
] then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. string.format(
|
|
S(
|
|
"no area highlighted yet"
|
|
)
|
|
)
|
|
)
|
|
return
|
|
end
|
|
local boundaries = edge_boundaries(
|
|
player_highlighted[
|
|
own_name
|
|
].pos1,
|
|
player_highlighted[
|
|
own_name
|
|
].pos2
|
|
)
|
|
if not for_all_students_within_area(
|
|
boundaries,
|
|
function(
|
|
player,
|
|
name
|
|
)
|
|
local command, params = split_command(
|
|
string.gsub(
|
|
param,
|
|
"subject",
|
|
name
|
|
)
|
|
)
|
|
minetest.chatcommands[
|
|
command
|
|
].func(
|
|
own_name,
|
|
params
|
|
)
|
|
end
|
|
) then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. string.format(
|
|
S(
|
|
"no student players found within the highlighted area"
|
|
)
|
|
)
|
|
)
|
|
end
|
|
end,
|
|
}
|
|
)
|
|
|
|
minetest.register_chatcommand(
|
|
"every_member",
|
|
{
|
|
params = "<" .. S(
|
|
"group name"
|
|
) .. "> <" .. S(
|
|
"command"
|
|
) .. "> [" .. S(
|
|
"parameters"
|
|
) .. "...]",
|
|
description = S(
|
|
"apply command to all group members"
|
|
),
|
|
privs = {
|
|
teacher = true,
|
|
},
|
|
func = function(
|
|
own_name,
|
|
param
|
|
)
|
|
local group, param = split_command(
|
|
param
|
|
)
|
|
if not player_groups[
|
|
group
|
|
] then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. S(
|
|
"group does not exists"
|
|
)
|
|
)
|
|
return
|
|
end
|
|
if not for_all_members(
|
|
group,
|
|
function(
|
|
player,
|
|
name
|
|
)
|
|
local command, params = split_command(
|
|
string.gsub(
|
|
param,
|
|
"subject",
|
|
name
|
|
)
|
|
)
|
|
minetest.chatcommands[
|
|
command
|
|
].func(
|
|
own_name,
|
|
params
|
|
)
|
|
end
|
|
) then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. string.format(
|
|
S(
|
|
"no group members found"
|
|
)
|
|
)
|
|
)
|
|
end
|
|
end,
|
|
}
|
|
)
|
|
|
|
minetest.register_chatcommand(
|
|
"visitation",
|
|
{
|
|
params = "<X>,<Y>,<Z> | <" .. S(
|
|
"destination player"
|
|
) .. "> | <" .. S(
|
|
"teleported player"
|
|
) .. "> <X>,<Y>,<Z> | <" .. S(
|
|
"teleported player"
|
|
) .. "> <" .. S(
|
|
"destination player"
|
|
) .. ">",
|
|
description = S(
|
|
"reversibly teleport self or other players"
|
|
),
|
|
privs = {
|
|
},
|
|
func = function(
|
|
own_name,
|
|
param
|
|
)
|
|
local teleportee_name = nil
|
|
local target = nil
|
|
teleportee_name, target = string.match(
|
|
param,
|
|
"^([^ ]+) +(.+)$"
|
|
)
|
|
if not teleportee_name then
|
|
teleportee_name = own_name
|
|
end
|
|
local teleportee = minetest.get_player_by_name(
|
|
teleportee_name
|
|
)
|
|
if not teleportee then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. string.format(
|
|
S(
|
|
"cannot find a player named %s"
|
|
),
|
|
teleportee_name
|
|
)
|
|
)
|
|
return
|
|
end
|
|
local return_positions = teleportee:get_attribute(
|
|
"return_positions"
|
|
)
|
|
if return_positions then
|
|
return_positions = minetest.deserialize(
|
|
return_positions
|
|
)
|
|
end
|
|
local old_pos = teleportee:get_pos(
|
|
)
|
|
teleportee:set_attribute(
|
|
"return_positions",
|
|
minetest.serialize(
|
|
{
|
|
head = old_pos,
|
|
tail = return_positions,
|
|
}
|
|
)
|
|
)
|
|
minetest.chatcommands[
|
|
"teleport"
|
|
].func(
|
|
own_name,
|
|
param
|
|
)
|
|
end,
|
|
}
|
|
)
|
|
|
|
minetest.register_chatcommand(
|
|
"setnextpos",
|
|
{
|
|
params = "<" .. S(
|
|
"player"
|
|
) .. ">",
|
|
description = S(
|
|
"have a player start at the current position on the next login"
|
|
),
|
|
privs = {
|
|
teacher = true,
|
|
},
|
|
func = function(
|
|
own_name,
|
|
param
|
|
)
|
|
local positioned = minetest.get_player_by_name(
|
|
param
|
|
)
|
|
if not positioned then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. string.format(
|
|
S(
|
|
"cannot find a player named %s"
|
|
),
|
|
param
|
|
)
|
|
)
|
|
return
|
|
end
|
|
local current_pos = positioned:get_pos(
|
|
)
|
|
teleportee:set_attribute(
|
|
"next_login_position",
|
|
minetest.serialize(
|
|
current_pos
|
|
)
|
|
)
|
|
register_one_shot(
|
|
param,
|
|
function(
|
|
player,
|
|
name
|
|
)
|
|
local login_position = player:get_attribute(
|
|
"next_login_position"
|
|
)
|
|
if login_position then
|
|
login_position = minetest.deserialize(
|
|
login_position
|
|
)
|
|
end
|
|
player:set_pos(
|
|
login_position
|
|
)
|
|
end
|
|
)
|
|
end,
|
|
}
|
|
)
|
|
|
|
minetest.register_chatcommand(
|
|
"return",
|
|
{
|
|
params = "[" .. S(
|
|
"player name"
|
|
) .. "]",
|
|
description = S(
|
|
"teleport to location before the last visitation command"
|
|
),
|
|
privs = {
|
|
},
|
|
func = function(
|
|
own_name,
|
|
param
|
|
)
|
|
local teleportee_name = nil
|
|
if "" == param then
|
|
teleportee_name = own_name
|
|
else
|
|
teleportee_name = param
|
|
end
|
|
local teleportee = minetest.get_player_by_name(
|
|
teleportee_name
|
|
)
|
|
if not teleportee then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. string.format(
|
|
S(
|
|
"cannot find a player named %s"
|
|
),
|
|
teleportee_name
|
|
)
|
|
)
|
|
return
|
|
end
|
|
local return_positions = teleportee:get_attribute(
|
|
"return_positions"
|
|
)
|
|
if return_positions then
|
|
return_positions = minetest.deserialize(
|
|
return_positions
|
|
)
|
|
end
|
|
if not return_positions then
|
|
minetest.chat_send_player(
|
|
own_name,
|
|
"EDUtest: " .. S(
|
|
"no previous position stored"
|
|
)
|
|
)
|
|
return
|
|
end
|
|
local old_pos = return_positions.head
|
|
teleportee:set_attribute(
|
|
"return_positions",
|
|
minetest.serialize(
|
|
return_positions.tail
|
|
)
|
|
)
|
|
minetest.chatcommands[
|
|
"teleport"
|
|
].func(
|
|
own_name,
|
|
teleportee_name .. " " .. old_pos.x .. "," .. old_pos.y .. "," .. old_pos.z
|
|
)
|
|
end,
|
|
}
|
|
)
|
|
|
|
minetest.register_on_joinplayer(
|
|
function (player)
|
|
local name = player:get_player_name(
|
|
)
|
|
local privs = minetest.get_player_privs(
|
|
name
|
|
)
|
|
if true == privs[
|
|
"student"
|
|
] then
|
|
for k, v in pairs(
|
|
on_join_handlers
|
|
) do
|
|
if nil ~= v.func then
|
|
v.func(
|
|
player,
|
|
name
|
|
)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
)
|
|
|
|
edutest = {
|
|
adapt_highlighted_area = adapt_highlighted_area,
|
|
set_highlight_marker_click_handler = set_highlight_marker_click_handler,
|
|
set_highlight_marker_tooltip = set_highlight_marker_tooltip,
|
|
for_all_students = for_all_students,
|
|
for_all_members = for_all_members,
|
|
for_all_groups = for_all_groups,
|
|
}
|