Initial skins mod based on NCC server mod

- Currently all skins must be pre-loaded into the mod texture
  folder at startup time; server restart required to change a
  player skin.
- Currently has partial support for the wieldhand (uninjured only)
- Some configuration added (adjustable rescaling, optional priv)
master
Aaron Suen 2021-07-27 07:01:18 -04:00
commit 2ba34c454e
11 changed files with 173 additions and 0 deletions

3
.luacheckrc Normal file
View File

@ -0,0 +1,3 @@
globals = {"minetest", "ItemStack", "VoxelArea", "vector", "nodecore", "include", "SecureRandom"}
color = false
quiet = 1

8
.lualocals Normal file
View File

@ -0,0 +1,8 @@
~print
minetest
ItemStack
VoxelArea
vector
nodecore
include
SecureRandom

9
TODO Normal file
View File

@ -0,0 +1,9 @@
------------------------------------------------------------------------
Switch to dynamic media for all skins?
Optionally detect and apply new skins periodically at runtime
Optional HTTP fetch API for new players and updates
------------------------------------------------------------------------

22
api_priv.lua Normal file
View File

@ -0,0 +1,22 @@
-- LUALOCALS < ---------------------------------------------------------
local minetest
= minetest
-- LUALOCALS > ---------------------------------------------------------
local modname = minetest.get_current_modname()
local api = _G[modname]
if minetest.settings:get_bool(modname .. "_nopriv") then
function api.skin_allowed() return true end
return
end
minetest.register_privilege(modname, {
description = "Custom skin use allowed",
give_to_singleplayer = true,
give_to_admin = false
})
function api.skin_allowed(pname)
return minetest.check_player_privs(pname, modname)
end

19
api_rescale.lua Normal file
View File

@ -0,0 +1,19 @@
-- LUALOCALS < ---------------------------------------------------------
local minetest, tonumber
= minetest, tonumber
-- LUALOCALS > ---------------------------------------------------------
local modname = minetest.get_current_modname()
local api = _G[modname]
local function scalecore(skin, suff)
local scale = tonumber(minetest.settings:get(modname .. "_" .. suff))
if not (scale and scale > 0) then return skin end
return skin .. "^[resize:" .. scale .. "x" .. scale
end
function api.rescale(skin)
if not skin then return skin end
skin = scalecore(skin, "downscale")
skin = scalecore(skin, "upscale")
return skin
end

26
api_skindb.lua Normal file
View File

@ -0,0 +1,26 @@
-- LUALOCALS < ---------------------------------------------------------
local minetest, pairs
= minetest, pairs
-- LUALOCALS > ---------------------------------------------------------
local modname = minetest.get_current_modname()
local api = _G[modname]
local skincache = {}
local pref = modname .. "_player_"
local modpath = minetest.get_modpath(modname)
for _, name in pairs(minetest.get_dir_list(modpath .. "/textures", false)) do
if name:sub(1, #pref) == pref and name:sub(-4) == ".png" then
local key = name:sub(#pref + 1, -5):lower()
skincache[key] = api.rescale(name)
end
end
function api.get_skin(pname)
if not api.skin_allowed(pname) then return end
return skincache[pname]
end
function api.all_loaded_skins()
return skincache
end

14
init.lua Normal file
View File

@ -0,0 +1,14 @@
-- LUALOCALS < ---------------------------------------------------------
local include, minetest, rawset
= include, minetest, rawset
-- LUALOCALS > ---------------------------------------------------------
local modname = minetest.get_current_modname()
local api = {}
rawset(_G, modname, api)
include('api_priv')
include('api_skindb')
include('skin_model')
include('skin_wieldhand')

2
mod.conf Normal file
View File

@ -0,0 +1,2 @@
name = nc_skins
description = Custom skins for NodeCore

22
settingtypes.txt Normal file
View File

@ -0,0 +1,22 @@
nc_skins_nopriv
# If enabled, the nc_skins privilege is not registered and all players
# are allowed to use custom skins unconditionally. If disabled, only
# players with the nc_skins privilege are checked for custom skins.
nc_skins_nopriv (Bypass privilege requirement) bool false
# If set, downscale the skin to fit in within a minimum resolution,
# to ensure custom skins don't exceed an allowed size.
nc_skins_downscale (Limit skin resolution) float
# If set, upscale skins to force square pixelation under filtration,
# i.e. achieve the effects of texture_min_size. This is necessary because
# texture_min_size is intended for 16px textures but the player skin is
# 64px at the same physical resolution, and thus will need 4x the
# amount of scaling to achieve the same effect.
nc_skins_upscale (Limit skin resolution) float
# If enabled, generate custom wieldhands for players. WARNING: this
# uses node definitions, only supports skins that are present at
# start time, and only supports the uninjured hand.
nc_skins_wieldhands (Enable custom wieldhand) bool true

14
skin_model.lua Normal file
View File

@ -0,0 +1,14 @@
-- LUALOCALS < ---------------------------------------------------------
local minetest, nodecore
= minetest, nodecore
-- LUALOCALS > ---------------------------------------------------------
local modname = minetest.get_current_modname()
local api = _G[modname]
local base = nodecore.player_skin
function nodecore.player_skin(player, options, ...)
local pname = options.playername or player and player:get_player_name()
local skin = pname and api.get_skin(pname)
return skin or base(player, options, ...)
end

34
skin_wieldhand.lua Normal file
View File

@ -0,0 +1,34 @@
-- LUALOCALS < ---------------------------------------------------------
local minetest, pairs
= minetest, pairs
-- LUALOCALS > ---------------------------------------------------------
local modname = minetest.get_current_modname()
local api = _G[modname]
local hands = {}
for pname, texture in pairs(api.all_loaded_skins()) do
local hname = modname .. ":hand_" .. minetest.sha1(pname)
hands[pname] = hname
minetest.register_node(hname, {
drawtype = "mesh",
mesh = "nc_player_hand.obj",
tiles = {texture},
use_texture_alpha = "clip",
wield_scale = {x = 2, y = 2, z = 2},
virtual_item = true,
on_punch = minetest.remove_node
})
end
minetest.register_on_joinplayer(function(player)
local pname = player:get_player_name()
local hand = hands[pname]
if not hand then return end
minetest.after(0, function()
player = minetest.get_player_by_name(pname)
if not player then return end
player:get_inventory():set_stack("hand", 1, hand)
end)
end)