commit 2ba34c454ef324db92524640f55a94a2f408ac6f Author: Aaron Suen Date: Tue Jul 27 07:01:18 2021 -0400 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) diff --git a/.luacheckrc b/.luacheckrc new file mode 100644 index 0000000..ba6434e --- /dev/null +++ b/.luacheckrc @@ -0,0 +1,3 @@ +globals = {"minetest", "ItemStack", "VoxelArea", "vector", "nodecore", "include", "SecureRandom"} +color = false +quiet = 1 diff --git a/.lualocals b/.lualocals new file mode 100644 index 0000000..4128e08 --- /dev/null +++ b/.lualocals @@ -0,0 +1,8 @@ +~print +minetest +ItemStack +VoxelArea +vector +nodecore +include +SecureRandom diff --git a/TODO b/TODO new file mode 100644 index 0000000..52575a4 --- /dev/null +++ b/TODO @@ -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 + +------------------------------------------------------------------------ diff --git a/api_priv.lua b/api_priv.lua new file mode 100644 index 0000000..ffa3ffa --- /dev/null +++ b/api_priv.lua @@ -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 diff --git a/api_rescale.lua b/api_rescale.lua new file mode 100644 index 0000000..1e2543b --- /dev/null +++ b/api_rescale.lua @@ -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 diff --git a/api_skindb.lua b/api_skindb.lua new file mode 100644 index 0000000..5db5c55 --- /dev/null +++ b/api_skindb.lua @@ -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 diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..489c1f0 --- /dev/null +++ b/init.lua @@ -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') diff --git a/mod.conf b/mod.conf new file mode 100644 index 0000000..97661c4 --- /dev/null +++ b/mod.conf @@ -0,0 +1,2 @@ +name = nc_skins +description = Custom skins for NodeCore \ No newline at end of file diff --git a/settingtypes.txt b/settingtypes.txt new file mode 100644 index 0000000..9639b5e --- /dev/null +++ b/settingtypes.txt @@ -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 \ No newline at end of file diff --git a/skin_model.lua b/skin_model.lua new file mode 100644 index 0000000..27736c2 --- /dev/null +++ b/skin_model.lua @@ -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 diff --git a/skin_wieldhand.lua b/skin_wieldhand.lua new file mode 100644 index 0000000..e1968d0 --- /dev/null +++ b/skin_wieldhand.lua @@ -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)