Compare commits

...

No commits in common. "v7" and "master" have entirely different histories.
v7 ... master

5 changed files with 57 additions and 72 deletions

43
.gitignore vendored
View file

@ -1,43 +0,0 @@
# ---> Lua
# Compiled Lua sources
luac.out
# luarocks build files
*.src.rock
*.zip
*.tar.gz
# Object files
*.o
*.os
*.ko
*.obj
*.elf
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
*.def
*.exp
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex

View file

@ -1,3 +0,0 @@
# libskinupload
A Minetest mod that allows players to upload custom skins to a server.

View file

@ -41,6 +41,17 @@ if minetest.get_modpath("u_skins") then
end end
end end
-- Shim for Nodecore
if minetest.global_exists("nodecore") then
local _player_skin = nodecore.player_skin
function nodecore.player_skin(player, options, ...)
local pname = options and options.playername or player and player:get_player_name()
local skin = pname and libskinupload.get_skin(pname)
return skin or _player_skin(player, options, ...)
end
end
-- Polyfill for older versions -- Polyfill for older versions
if not minetest.hypertext_escape then if not minetest.hypertext_escape then
local hypertext_escapes = { local hypertext_escapes = {
@ -55,12 +66,7 @@ if not minetest.hypertext_escape then
end end
local function player_model(p, tx, slim_arms) local function player_model(p, tx, slim_arms)
if mcl then return p:get_properties().mesh..";"..tx..",blank.png,blank.png,blank.png"
return (slim_arms and "mcl_armor_character_female.b3d" or "mcl_armor_character.b3d")..";"..tx..",blank.png"
elseif it then
return "player.b3d;"..tx
end
return "character.b3d;"..tx..",blank.png"
end end
local db = minetest.get_mod_storage() local db = minetest.get_mod_storage()
@ -86,12 +92,14 @@ else
for _, x in pairs(dl) do for _, x in pairs(dl) do
minetest.log("action", "Merging file "..x.."...") minetest.log("action", "Merging file "..x.."...")
local id = x:match "libskinupload_uploaded_skin_(%d*).json" local id = x:match "libskinupload_uploaded_skin_(%d*).json"
if id then
local file = io.open(storage_dir_meta..x) local file = io.open(storage_dir_meta..x)
local data = file:read("a") local data = file:read("a")
file:close() file:close()
out = out..(i == 0 and ("\""..id.."\":") or (",\""..id.."\":"))..data out = out..(i == 0 and ("\""..id.."\":") or (",\""..id.."\":"))..data
i = i +1 i = i +1
end end
end
local f = io.open(meta_file, "w+") local f = io.open(meta_file, "w+")
f:write(out.."}") f:write(out.."}")
f:flush() f:flush()
@ -133,9 +141,11 @@ function libskinupload.add_skin_media(id, fname, cb)
else else
meta = libskinupload.get_skin_meta(x) meta = libskinupload.get_skin_meta(x)
end end
if not meta.p then
mcl_skins.register_simple_skin{texture = x, slim_arms = meta.msa or false} mcl_skins.register_simple_skin{texture = x, slim_arms = meta.msa or false}
end end
end end
end
if not optimize_media then if not optimize_media then
for _, x in ipairs(minetest.get_dir_list(storage_dir, false)) do for _, x in ipairs(minetest.get_dir_list(storage_dir, false)) do
@ -155,10 +165,6 @@ minetest.register_privilege("skin_review", {
give_to_singleplayer = false, give_to_singleplayer = false,
give_to_admin = false give_to_admin = false
}) })
minetest.register_privilege("no_skin_upload", {
give_to_singleplayer = false,
give_to_admin = false
})
libskinupload.notifications = minetest.deserialize(db:get_string("notifications")) or {} libskinupload.notifications = minetest.deserialize(db:get_string("notifications")) or {}
libskinupload.reviewers = minetest.deserialize(db:get_string("reviewers")) or {} libskinupload.reviewers = minetest.deserialize(db:get_string("reviewers")) or {}
@ -219,12 +225,21 @@ minetest.register_on_joinplayer(function(p)
if minetest.check_player_privs(p, {skin_review = true}) then if minetest.check_player_privs(p, {skin_review = true}) then
local newskins = db:get_int("newrequests") local newskins = db:get_int("newrequests")
if newskins > 0 then minetest.chat_send_player(p:get_player_name(), minetest.colorize("#579a1e", "[libskinupload] "..newskins.." new skin request"..(newskins == 1 and " has" or "s have").." been submitted. Run /skinreview to see "..(newskins == 1 and "it" or "them")..".")) end if newskins > 0 then minetest.chat_send_player(p:get_player_name(), minetest.colorize("#579a1e", "[libskinupload] "..newskins.." new skin request"..(newskins == 1 and " has" or "s have").." been submitted. Run /skinreview to see "..(newskins == 1 and "it" or "them")..".")) end
elseif p:get_player_name() == "singleplayer" then
minetest.change_player_privs(p:get_player_name(), {skin_review = true})
end end
end) end)
function libskinupload.can_player_upload_skins(p)
if db:get("upload_permitted:"..p:get_player_name()) == "false" then
return false
end
return true
end
function libskinupload.queue(p, req) function libskinupload.queue(p, req)
local data = req.data local data = req.data
if minetest.check_player_privs(p, {no_skin_upload = true}) then if not libskinupload.can_player_upload_skins(p) then
minetest.chat_send_player(p:get_player_name(), "Insufficient permissions.") minetest.chat_send_player(p:get_player_name(), "Insufficient permissions.")
return "No permission." return "No permission."
end end
@ -353,6 +368,10 @@ local upload_state = {}
function libskinupload.show_upload_dialog(name, args) function libskinupload.show_upload_dialog(name, args)
if not args or type(args) == "string" then args = {err = ""} end if not args or type(args) == "string" then args = {err = ""} end
local p = minetest.get_player_by_name(name) local p = minetest.get_player_by_name(name)
if not libskinupload.can_player_upload_skins(p) then
minetest.chat_send_player(name, "Insufficient privileges.")
return
end
if not upload_state[name] then upload_state[name] = {} end if not upload_state[name] then upload_state[name] = {} end
local m = upload_state[name] local m = upload_state[name]
local size = (minetest.get_player_window_information(name) or {}).max_formspec_size or {x = 20, y = 11.5} local size = (minetest.get_player_window_information(name) or {}).max_formspec_size or {x = 20, y = 11.5}
@ -405,12 +424,11 @@ function libskinupload.show_upload_dialog(name, args)
style[help:hovered;bgcolor=#0000;border=false;bgimg=]\ style[help:hovered;bgcolor=#0000;border=false;bgimg=]\
style[help:pressed;bgcolor=#0000;border=false;bgimg=]\ style[help:pressed;bgcolor=#0000;border=false;bgimg=]\
button[0,0;"..size.x..","..size.y..";help;]\ button[0,0;"..size.x..","..size.y..";help;]\
hypertext["..(size.x /4)..","..(size.y /4)..";"..(size.x /2)..","..(size.y /2)..";;<tag name=clr color=#ffbc5b>"..minetest.formspec_escape("To upload a skin, paste the base64-encoded image into the Data field below. This can be obtained from a terminal by running <clr><b>`base64 -i <filepath>`</b></clr> (e.g. <clr><b>`base64 -i ~/Desktop/skins/my_skin.png`</b></clr>) and copying the output. Alternatively, you can use a web tool (search <clr>'base64-encode an image'</clr> or similar). Once a request is sbmitted, it will need to be reviewed. You will be notified when your request is accepted or denied. Note that you can only have one skin request pending approval at a time; if you send another request before the previous one is approved or rejected, the later request will overwrite the previous one.").."]" or "")) hypertext["..(size.x /4)..","..(size.y /4)..";"..(size.x /2)..","..(size.y /2)..";;<tag name=clr color=#ffbc5b>"..minetest.formspec_escape("To upload a skin, paste the base64-encoded image into the Data field below. This can be obtained from a terminal by running <clr><b>`base64 -i <filepath>`</b></clr> (e.g. <clr><b>`base64 -i ~/Desktop/skins/my_skin.png`</b></clr>) and copying the output. Alternatively, you can use a web tool (search <clr>'base64-encode an image'</clr> or similar). Once a request is sbmitted, it will need to be reviewed. You will be notified when your request is accepted or denied. Note that you can only have one skin request pending approval at a time; if you send another request before the previous one is approved or rejected, the later request will overwrite the previous one.\nIf the preview for the skin you're uploading looks wrong, the image was probably in a layout that won't work with the player model. Usually, this is because you're trying to upload a Minecraft skin, which is incompatible with most Minetest player models. In that case, you can fix it by simply cropping off the bottom 32 pixels of the original 64x64 image and trying again.").."]" or ""))
end end
minetest.register_chatcommand("skinupload", { minetest.register_chatcommand("skinupload", {
description = "Show the skin upload dialog.", description = "Show the skin upload dialog.",
func = libskinupload.show_upload_dialog, func = libskinupload.show_upload_dialog
privs = {no_skin_upload = false}
}) })
local review_state = {} local review_state = {}
@ -763,7 +781,7 @@ minetest.register_chatcommand("skinlimit", {
params = "<name> <limit>", params = "<name> <limit>",
description = "Set the maximum concurrent skin requests allowed for player <name> to <limit>.", description = "Set the maximum concurrent skin requests allowed for player <name> to <limit>.",
func = function(name, args) func = function(name, args)
local pn, num = args:match "(%w+)%s+(%d+)" local pn, num = args:match "([%w_-]+)%s+(%d+)"
num = tonumber(num) num = tonumber(num)
if pn and pn ~= "" and num and num > 0 then if pn and pn ~= "" and num and num > 0 then
db:set_int("reqmax:"..pn, num) db:set_int("reqmax:"..pn, num)
@ -796,7 +814,7 @@ end
minetest.register_chatcommand("skinmanage", { minetest.register_chatcommand("skinmanage", {
privs = {skin_review = true}, privs = {skin_review = true},
params = "cull | list | (meta <id>) | alter <id> <newkey>=<newvalue>[,<newkey2>=<newvalue2>]*", params = "cull | list | meta <id> | grant <name> | revoke <name> | privs <name> | alter <id> <newkey>=<newvalue>[,<newkey2>=<newvalue2>]*",
func = function(name, args) func = function(name, args)
if args == "cull" then if args == "cull" then
local i = 0 local i = 0
@ -865,6 +883,17 @@ minetest.register_chatcommand("skinmanage", {
elseif args:match "^remove_fragmented_meta" then elseif args:match "^remove_fragmented_meta" then
minetest.rmdir(storage_dir_meta, true) minetest.rmdir(storage_dir_meta, true)
minetest.chat_send_player(name, "Removed all fragmented meta.") minetest.chat_send_player(name, "Removed all fragmented meta.")
elseif args:match "^grant" then
local pname = args:match "grant%s+([%w_-]+)"
db:set_string("upload_permitted:"..pname, "")
minetest.chat_send_player(name, "Granted skin upload privileges to player "..pname..".")
elseif args:match "^revoke" then
local pname = args:match "revoke%s+([%w_-]+)"
db:set_string("upload_permitted:"..pname, "false")
minetest.chat_send_player(name, "Revoked skin upload privileges from player "..pname..".")
elseif args:match "^privs" then
local pname = args:match "privs%s+([%w_-]+)"
minetest.chat_send_player(name, "Player "..pname.." is "..(db:get("upload_permitted:"..pname) == "false" and "not " or "").."allowed to upload skins.")
else else
minetest.chat_send_player(name, "Invalid arguments, see /help skinmanage for accepted subcommands.") minetest.chat_send_player(name, "Invalid arguments, see /help skinmanage for accepted subcommands.")
end end
@ -928,7 +957,8 @@ function libskinupload.get_skin_id(name)
end end
function libskinupload.get_skin(name) function libskinupload.get_skin(name)
return "libskinupload_uploaded_skin_"..db:get_string("skin:"..name)..".png" local id = db:get("skin:"..name)
return id and "libskinupload_uploaded_skin_"..id..".png"
end end
function libskinupload.get_skin_meta(skin) function libskinupload.get_skin_meta(skin)
@ -952,6 +982,7 @@ function libskinupload.get_skin_meta(skin)
else else
local res = minetest.parse_json(f:read("a")) local res = minetest.parse_json(f:read("a"))
f:close() f:close()
if not res then return {n = "Unnamed", d = "Nondescript", c = "<Unknown>"} end
return res[string.gsub(string.sub(skin, string.len("libskinupload_uploaded_skin_."), -1), ".png", "")] or {n = "Unnamed", d = "Nondescript", c = "<Unknown>"} return res[string.gsub(string.sub(skin, string.len("libskinupload_uploaded_skin_."), -1), ".png", "")] or {n = "Unnamed", d = "Nondescript", c = "<Unknown>"}
end end
end end
@ -1031,7 +1062,7 @@ end
minetest.register_on_player_receive_fields(function(p, name, data) minetest.register_on_player_receive_fields(function(p, name, data)
if name == "libskinupload:upload" then if name == "libskinupload:upload" then
if minetest.check_player_privs(p, {no_skin_upload = true}) then if not libskinupload.can_player_upload_skins(p) then
minetest.chat_send_player(p:get_player_name(), "Insufficient permissions.") minetest.chat_send_player(p:get_player_name(), "Insufficient permissions.")
minetest.close_formspec(p:get_player_name(), name) minetest.close_formspec(p:get_player_name(), name)
return true return true

View file

@ -1,2 +1,2 @@
name = libskinupload name = libskinupload
optional_depends = unified_inventory, u_skins, mcl_skins, 3d_armor optional_depends = unified_inventory, u_skins, mcl_skins, 3d_armor, nc_player_model