local S = classroom.S local FS = classroom.FS local infos = { { title = S"Shout?", type = "priv", privs = { shout = true }, }, { title = S"Fly?", type = "priv", privs = { fly = true }, }, { title = S"Fast?", type = "priv", privs = { fast = true }, }, } local function get_group(context) if context and context.groupname then return classroom.get_group_students(context.groupname) else return classroom.get_students() end end sfinv.register_page("classroom:edu", { title = S"Classroom", check_perm = function(self, player) return minetest.check_player_privs(player:get_player_name(), { teacher = true }) end, is_in_nav = function(self, player, context) return self:check_perm(player) end, get = function(self, player, context) if not self:check_perm(player) then return "label[0,0;" .. FS"Access denied" .. "]" end local fs = { "tablecolumns[color;text" } context.select_toggle = context.select_toggle or "all" for i, col in pairs(infos) do fs[#fs + 1] = ";color;text,align=center" if i == 1 then fs[#fs + 1] = ",padding=2" end end fs[#fs + 1] = "]" do fs[#fs + 1] = "tabheader[0.3,1.1;group;" fs[#fs + 1] = FS"All" local selected_group_idx = 1 local i = 2 for name, group in pairs(classroom.get_all_groups()) do fs[#fs + 1] = "," fs[#fs + 1] = minetest.formspec_escape(name) if context.groupname and name == context.groupname then selected_group_idx = i end i = i + 1 end fs[#fs + 1] = ";" fs[#fs + 1] = tostring(selected_group_idx) fs[#fs + 1] = "]" end fs[#fs + 1] = "table[0,0.8;5,8;students;,Name" for _, col in pairs(infos) do fs[#fs + 1] = ",," .. col.title end local students = get_group(context) local selection_id = "" context.students = table.copy(students) for i, student in pairs(students) do fs[#fs + 1] = ",," fs[#fs + 1] = minetest.formspec_escape(student) if student == context.selected_student then selection_id = tostring(i + 1) end for _, col in pairs(infos) do local color, value if col.type == "priv" then local has_priv = minetest.check_player_privs(student, col.privs) color = has_priv and "green" or "red" value = has_priv and FS"Yes" or FS"No" end fs[#fs + 1] = "," fs[#fs + 1] = color fs[#fs + 1] = "," fs[#fs + 1] = minetest.formspec_escape(value) end end fs[#fs + 1] = ";" fs[#fs + 1] = selection_id fs[#fs + 1] = "]" fs[#fs + 1] = "button[5.25,-0.2;1.4,1;new_group;" fs[#fs + 1] = FS"New Group" fs[#fs + 1] = "]" if context.groupname then fs[#fs + 1] = "button[6.65,-0.2;1.4,1;edit_group;" fs[#fs + 1] = FS"Edit Group" fs[#fs + 1] = "]" else fs[#fs + 1] = "box[6.65,-0.1;1.2,0.7;#222]" fs[#fs + 1] = "label[6.8,0.05;" fs[#fs + 1] = FS"Edit Group" fs[#fs + 1] = "]" fs[#fs + 1] = "tooltip[6.65,-0.2;1.4,1;" fs[#fs + 1] = FS"Please select a group first" fs[#fs + 1] = "]" end fs[#fs + 1] = "container[5.25,1.1]" fs[#fs + 1] = "box[-0.25,-0.3;3.1,1.15;#666]" fs[#fs + 1] = "label[0,-0.3;" fs[#fs + 1] = FS"Run actions on:" fs[#fs + 1] = "]" if context.select_toggle == "all" then fs[#fs + 1] = "box[0,0.1;0.8,0.7;#53ac56]" fs[#fs + 1] = "label[0.3,0.25;" fs[#fs + 1] = FS"All" fs[#fs + 1] = "]" else fs[#fs + 1] = "button[0,0;1,1;select_all;" fs[#fs + 1] = FS"All" fs[#fs + 1] = "]" end if not context.groupname then fs[#fs + 1] = "box[0.9,0.1;0.8,0.7;#333]" fs[#fs + 1] = "label[1.05,0.25;" fs[#fs + 1] = FS"Group" fs[#fs + 1] = "]" fs[#fs + 1] = "tooltip[0.9,0;1,1;" fs[#fs + 1] = FS"Please select a group first" fs[#fs + 1] = "]" elseif context.select_toggle == "group" then fs[#fs + 1] = "box[0.9,0.1;0.8,0.7;#53ac56]" fs[#fs + 1] = "label[1.05,0.25;" fs[#fs + 1] = FS"Group" fs[#fs + 1] = "]" else fs[#fs + 1] = "button[0.9,0;1,1;select_group;" fs[#fs + 1] = FS"Group" fs[#fs + 1] = "]" end if not context.selected_student then fs[#fs + 1] = "box[1.8,0.1;0.8,0.7;#333]" fs[#fs + 1] = "label[1.85,0.25;" fs[#fs + 1] = FS"Selected" fs[#fs + 1] = "]" fs[#fs + 1] = "tooltip[1.8,0;1,1;" fs[#fs + 1] = FS"Please select a student first" fs[#fs + 1] = "]" elseif context.select_toggle == "selected" then fs[#fs + 1] = "box[1.8,0.1;0.8,0.7;#53ac56]" fs[#fs + 1] = "label[1.85,0.25;" fs[#fs + 1] = FS"Selected" fs[#fs + 1] = "]" else fs[#fs + 1] = "button[1.8,0;1,1;select_selected;" fs[#fs + 1] = FS"Selected" fs[#fs + 1] = "]" end fs[#fs + 1] = "label[0,0.9;" fs[#fs + 1] = FS"Actions:" fs[#fs + 1] = "]" local x = 0 local y = 1.2 for _, action in pairs(classroom.get_actions()) do fs[#fs + 1] = "button[" fs[#fs + 1] = tostring(x) fs[#fs + 1] = "," fs[#fs + 1] = tostring(y) fs[#fs + 1] = ";1,1;action_" fs[#fs + 1] = action.name fs[#fs + 1] = ";" fs[#fs + 1] = minetest.formspec_escape(action.title) fs[#fs + 1] = "]" fs[#fs + 1] = "tooltip[action_" fs[#fs + 1] = action.name fs[#fs + 1] = ";" fs[#fs + 1] = minetest.formspec_escape(action.description) fs[#fs + 1] = "]" if x < 1.5 then x = x + 0.9 else x = 0 y = y + 0.8 end end y = y + 0.25 if context.selected_student then fs[#fs + 1] = "container[0," fs[#fs + 1] = tostring(y) fs[#fs + 1] = "]" fs[#fs + 1] = "label[0,-0.1;" fs[#fs + 1] = FS("Selected user: @1", context.selected_student) fs[#fs + 1] = "]" fs[#fs + 1] = "button[0,0.3;1.5,1;teleport;" fs[#fs + 1] = FS"Teleport to" fs[#fs + 1] = "]" fs[#fs + 1] = "container_end[]" end fs[#fs + 1] = "container_end[]" return sfinv.make_formspec(player, context, table.concat(fs, ""), false) end, on_player_receive_fields = function(self, player, context, fields) if not self:check_perm(player) then sfinv.set_page(player, sfinv.get_homepage_name(player)) return true end if fields.students then local evt = minetest.explode_table_event(fields.students) local i = (evt.row or 0) - 1 if evt.type == "CHG" and i >= 1 and i <= #context.students then context.selected_student = context.students[i] sfinv.set_player_inventory_formspec(player) return true end end if fields.group then if fields.group == "1" then context.groupname = nil else local i = 2 for name, _ in pairs(classroom.get_all_groups()) do if i == tonumber(fields.group) then context.groupname = name break end i = i + 1 end end sfinv.set_player_inventory_formspec(player) return true end if fields.select_all then context.select_toggle = "all" sfinv.set_player_inventory_formspec(player) return true elseif fields.select_group then context.select_toggle = "group" sfinv.set_player_inventory_formspec(player) return true elseif fields.select_selected then context.select_toggle = "selected" sfinv.set_player_inventory_formspec(player) return true end if fields.teleport and context.selected_student then local student = minetest.get_player_by_name(context.selected_student) if student then player:set_pos(student:get_pos()) return true else context.selected_student = nil sfinv.set_player_inventory_formspec(player) return true end end if fields.new_group then classroom.show_new_group(player) return true end if fields.edit_group and context.groupname then classroom.show_edit_group(player, context.groupname) return true end for _, action in pairs(classroom.get_actions()) do if fields["action_" .. action.name] then local selector if context.select_toggle == "all" then selector = "*" elseif context.select_toggle == "group" then selector = "group:" .. context.groupname elseif context.select_toggle == "selected" then selector = "user:" .. context.selected_student else error("Unknown selector") end classroom.run_action(action.name, player, selector) sfinv.set_player_inventory_formspec(player) return true end end end, }) local function on_grant_revoke(grantee, granter, priv) if priv ~= "teacher" then return end local player = minetest.get_player_by_name(grantee) if not player then return end minetest.after(0, function() sfinv.set_player_inventory_formspec(player) end) end minetest.register_on_priv_grant(on_grant_revoke) minetest.register_on_priv_revoke(on_grant_revoke) function classroom.show_new_group(player) if not minetest.check_player_privs(player:get_player_name(), { teacher = true }) then return end minetest.show_formspec(player:get_player_name(), "classroom:new_group", table.concat({ "size[5,1.8]", "field[0.2,0.4;5,1;name;", FS"Name", ";]", "button[1.5,1;2,1;create;", FS"Create", "]", }, "")) end minetest.register_on_player_receive_fields(function(player, formname, fields) if formname ~= "classroom:new_group" or not minetest.check_player_privs(player:get_player_name(), { teacher = true }) or not fields.create then return false end local group = classroom.create_group(fields.name) if group then sfinv.set_player_inventory_formspec(player) classroom.show_edit_group(player, group.name) else classroom.show_new_group(player, fields.name) end end) local _contexts = {} function classroom.show_edit_group(player, groupname) local name = player:get_player_name() if not minetest.check_player_privs(name, { teacher = true }) then return end local context = _contexts[name] or {} _contexts[name] = context context.groupname = groupname or context.groupname context.index_l = context.index_l or 1 context.index_r = context.index_r or 1 local fs = { "size[5.55,6]", "label[0,-0.1;", FS"Other students", "]", "label[3.3,-0.1;", FS("Students in group @1", context.groupname), "]", "button[2.25,0.5;1,1;go_right;", minetest.formspec_escape(">"), "]", "button[2.25,1.5;1,1;go_left;", minetest.formspec_escape("<"), "]", } local members = classroom.get_group_students(groupname) if #members > 0 then if context.index_r > #members then context.index_r = #members end fs[#fs + 1] = "textlist[3.25,0.5;2,5.5;right;" for i, member in pairs(members) do if i > 1 then fs[#fs + 1] = "," end fs[#fs + 1] = minetest.formspec_escape(member) end fs[#fs + 1] = ";" fs[#fs + 1] = tostring(context.index_r) fs[#fs + 1] = "]" else fs[#fs + 1] = "label[3.5,0.7;" fs[#fs + 1] = FS("No students") fs[#fs + 1] = "]" end local not_members = classroom.get_students_except(members) if #not_members > 0 then if context.index_l > #not_members then context.index_l = #members end fs[#fs + 1] = "textlist[0,0.5;2,5.5;left;" for i, member in pairs(not_members) do if i > 1 then fs[#fs + 1] = "," end fs[#fs + 1] = minetest.formspec_escape(member) end fs[#fs + 1] = ";" fs[#fs + 1] = tostring(context.index_l) fs[#fs + 1] = "]" else fs[#fs + 1] = "label[0.4,0.7;" fs[#fs + 1] = FS("No students") fs[#fs + 1] = "]" end minetest.show_formspec(player:get_player_name(), "classroom:edit_group", table.concat(fs, "")) end minetest.register_on_player_receive_fields(function(player, formname, fields) if formname ~= "classroom:edit_group" or not minetest.check_player_privs(player:get_player_name(), { teacher = true }) then return false end local context = _contexts[player:get_player_name()] if not context or not context.groupname then return false end if fields.left then local evt = minetest.explode_textlist_event(fields.left) if evt.type == "CHG" then context.index_l = evt.index return true end end if fields.right then local evt = minetest.explode_textlist_event(fields.right) if evt.type == "CHG" then context.index_r = evt.index return true end end if fields.quit then _contexts[player:get_player_name()] = nil end if fields.go_right and context.index_l then local students = classroom.get_group_students(context.groupname) local not_members = classroom.get_students_except(students) local student = not_members[context.index_l] if student then classroom.add_student_to_group(context.groupname, student) classroom.show_edit_group(player, context.groupname) sfinv.set_player_inventory_formspec(player) return true end end if fields.go_left and context.index_r then local students = classroom.get_group_students(context.groupname) local student = students[context.index_r] if student then classroom.remove_student_from_group(context.groupname, student) classroom.show_edit_group(player, context.groupname) sfinv.set_player_inventory_formspec(player) return true end end end) minetest.register_on_leaveplayer(function(player) _contexts[player:get_player_name()] = nil end)