Add wearables API

This commit is contained in:
Signal 2025-10-10 23:46:01 -04:00
parent 9e63d7fe3a
commit 5e4d2924e4
14 changed files with 181 additions and 0 deletions

22
mods/rgt_armor/init.lua Normal file
View file

@ -0,0 +1,22 @@
rgt_cosmetics.register_wearable {
name = "ic",
attachments = {
{
mesh = "rgt_armor_torso.gltf",
textures = {"rgt_iron_chestplate.png"},
bone = "Body"
},
{
mesh = "rgt_armor_right_arm.gltf",
textures = {"rgt_iron_chestplate.png"},
bone = "RightArm"
},
{
mesh = "rgt_armor_left_arm.gltf",
textures = {"rgt_iron_chestplate.png"},
bone = "LeftArm"
}
}
}

2
mods/rgt_armor/mod.conf Normal file
View file

@ -0,0 +1,2 @@
name = rgt_armor
depends = rgt_cosmetics

View file

@ -0,0 +1 @@
{"asset":{"version":"2.0","generator":"Blockbench 4.12.5 glTF exporter"},"scenes":[{"nodes":[1],"name":"blockbench_export"}],"scene":0,"nodes":[{"name":"cube","mesh":0},{"children":[0]}],"bufferViews":[{"buffer":0,"byteOffset":0,"byteLength":288,"target":34962,"byteStride":12},{"buffer":0,"byteOffset":288,"byteLength":288,"target":34962,"byteStride":12},{"buffer":0,"byteOffset":576,"byteLength":192,"target":34962,"byteStride":8},{"buffer":0,"byteOffset":768,"byteLength":72,"target":34963}],"buffers":[{"byteLength":840,"uri":"data:application/octet-stream;base64,AACAPwAA0D8AAKg/AACAPwAA0D8AAKi/AACAPwAA0MAAAKg/AACAPwAA0MAAAKi/AADQvwAA0D8AAKi/AADQvwAA0D8AAKg/AADQvwAA0MAAAKi/AADQvwAA0MAAAKg/AADQvwAA0D8AAKi/AACAPwAA0D8AAKi/AADQvwAA0D8AAKg/AACAPwAA0D8AAKg/AADQvwAA0MAAAKg/AACAPwAA0MAAAKg/AADQvwAA0MAAAKi/AACAPwAA0MAAAKi/AADQvwAA0D8AAKg/AACAPwAA0D8AAKg/AADQvwAA0MAAAKg/AACAPwAA0MAAAKg/AACAPwAA0D8AAKi/AADQvwAA0D8AAKi/AACAPwAA0MAAAKi/AADQvwAA0MAAAKi/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACAPQAAUD4AAAA+AABQPgAAgD0AANA+AAAAPgAA0D4AAEA+AABQPgAAgD4AAFA+AABAPgAA0D4AAIA+AADQPgAA8D4AAAA+AADQPgAAAD4AAPA+AACAPQAA0D4AAIA9AADwPgAAAD4AANA+AAAAPgAA8D4AAEA+AADQPgAAQD4AAAA+AABQPgAAQD4AAFA+AAAAPgAA0D4AAEA+AADQPgAAAAAAAFA+AACAPQAAUD4AAAAAAADQPgAAgD0AANA+AAACAAEAAgADAAEABAAGAAUABgAHAAUACAAKAAkACgALAAkADAAOAA0ADgAPAA0AEAASABEAEgATABEAFAAWABUAFgAXABUA"}],"accessors":[{"bufferView":0,"componentType":5126,"count":24,"max":[1,1.625,1.3125],"min":[-1.625,-6.5,-1.3125],"type":"VEC3"},{"bufferView":1,"componentType":5126,"count":24,"max":[1,1,1],"min":[-1,-1,-1],"type":"VEC3"},{"bufferView":2,"componentType":5126,"count":24,"max":[0.46875,0.40625],"min":[0,0.0625],"type":"VEC2"},{"bufferView":3,"componentType":5123,"count":36,"max":[23],"min":[0],"type":"SCALAR"}],"materials":[{"pbrMetallicRoughness":{"metallicFactor":0,"roughnessFactor":1,"baseColorTexture":{"index":0}},"alphaMode":"MASK","alphaCutoff":0.05,"doubleSided":true}],"textures":[{"sampler":0,"source":0,"name":"rgt_iron_chestplate"}],"samplers":[{"magFilter":9728,"minFilter":9728,"wrapS":33071,"wrapT":33071}],"images":[{"mimeType":"image/png","name":"rgt_iron_chestplate.png","uri":"rgt_iron_chestplate.png"}],"meshes":[{"primitives":[{"mode":4,"attributes":{"POSITION":0,"NORMAL":1,"TEXCOORD_0":2},"indices":3,"material":0}]}]}

View file

@ -0,0 +1 @@
{"asset":{"version":"2.0","generator":"Blockbench 4.12.5 glTF exporter"},"scenes":[{"nodes":[1],"name":"blockbench_export"}],"scene":0,"nodes":[{"name":"cube","mesh":0},{"children":[0]}],"bufferViews":[{"buffer":0,"byteOffset":0,"byteLength":288,"target":34962,"byteStride":12},{"buffer":0,"byteOffset":288,"byteLength":288,"target":34962,"byteStride":12},{"buffer":0,"byteOffset":576,"byteLength":192,"target":34962,"byteStride":8},{"buffer":0,"byteOffset":768,"byteLength":72,"target":34963}],"buffers":[{"byteLength":840,"uri":"data:application/octet-stream;base64,AADQPwAA0D8AAKg/AADQPwAA0D8AAKi/AADQPwAA0MAAAKg/AADQPwAA0MAAAKi/AACAvwAA0D8AAKi/AACAvwAA0D8AAKg/AACAvwAA0MAAAKi/AACAvwAA0MAAAKg/AACAvwAA0D8AAKi/AADQPwAA0D8AAKi/AACAvwAA0D8AAKg/AADQPwAA0D8AAKg/AACAvwAA0MAAAKg/AADQPwAA0MAAAKg/AACAvwAA0MAAAKi/AADQPwAA0MAAAKi/AACAvwAA0D8AAKg/AADQPwAA0D8AAKg/AACAvwAA0MAAAKg/AADQPwAA0MAAAKg/AADQPwAA0D8AAKi/AACAvwAA0D8AAKi/AADQPwAA0MAAAKi/AACAvwAA0MAAAKi/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACwPgAAAAAAANA+AAAAAAAAsD4AAFA+AADQPgAAUD4AAAAAAADQPgAAgD0AANA+AAAAAAAAHD8AAIA9AAAcPwAAiD4AAPA+AABQPgAA8D4AAIg+AADQPgAAUD4AANA+AACoPgAA0D4AAIg+AADQPgAAqD4AAPA+AACIPgAA8D4AAMA+AABQPgAA4D4AAFA+AADAPgAA0D4AAOA+AADQPgAAoD4AAFA+AADAPgAAUD4AAKA+AADQPgAAwD4AANA+AAACAAEAAgADAAEABAAGAAUABgAHAAUACAAKAAkACgALAAkADAAOAA0ADgAPAA0AEAASABEAEgATABEAFAAWABUAFgAXABUA"}],"accessors":[{"bufferView":0,"componentType":5126,"count":24,"max":[1.625,1.625,1.3125],"min":[-1,-6.5,-1.3125],"type":"VEC3"},{"bufferView":1,"componentType":5126,"count":24,"max":[1,1,1],"min":[-1,-1,-1],"type":"VEC3"},{"bufferView":2,"componentType":5126,"count":24,"max":[0.4375,0.609375],"min":[0,0],"type":"VEC2"},{"bufferView":3,"componentType":5123,"count":36,"max":[23],"min":[0],"type":"SCALAR"}],"materials":[{"pbrMetallicRoughness":{"metallicFactor":0,"roughnessFactor":1,"baseColorTexture":{"index":0}},"alphaMode":"MASK","alphaCutoff":0.05,"doubleSided":true}],"textures":[{"sampler":0,"source":0,"name":"rgt_iron_chestplate"}],"samplers":[{"magFilter":9728,"minFilter":9728,"wrapS":33071,"wrapT":33071}],"images":[{"mimeType":"image/png","name":"rgt_iron_chestplate.png","uri":"rgt_iron_chestplate.png"}],"meshes":[{"primitives":[{"mode":4,"attributes":{"POSITION":0,"NORMAL":1,"TEXCOORD_0":2},"indices":3,"material":0}]}]}

View file

@ -0,0 +1 @@
{"asset":{"version":"2.0","generator":"Blockbench 4.12.5 glTF exporter"},"scenes":[{"nodes":[1],"name":"blockbench_export"}],"scene":0,"nodes":[{"name":"cube","mesh":0},{"children":[0]}],"bufferViews":[{"buffer":0,"byteOffset":0,"byteLength":288,"target":34962,"byteStride":12},{"buffer":0,"byteOffset":288,"byteLength":288,"target":34962,"byteStride":12},{"buffer":0,"byteOffset":576,"byteLength":192,"target":34962,"byteStride":8},{"buffer":0,"byteOffset":768,"byteLength":72,"target":34963}],"buffers":[{"byteLength":840,"uri":"data:application/octet-stream;base64,AAAuQAAAoD4AAKA/AAAuQAAAoD4AAKC/AAAuQAAA+sAAAKA/AAAuQAAA+sAAAKC/AAAuwAAAoD4AAKC/AAAuwAAAoD4AAKA/AAAuwAAA+sAAAKC/AAAuwAAA+sAAAKA/AAAuwAAAoD4AAKC/AAAuQAAAoD4AAKC/AAAuwAAAoD4AAKA/AAAuQAAAoD4AAKA/AAAuwAAA+sAAAKA/AAAuQAAA+sAAAKA/AAAuwAAA+sAAAKC/AAAuQAAA+sAAAKC/AAAuwAAAoD4AAKA/AAAuQAAAoD4AAKA/AAAuwAAA+sAAAKA/AAAuQAAA+sAAAKA/AAAuQAAAoD4AAKC/AAAuwAAAoD4AAKC/AAAuQAAA+sAAAKC/AAAuwAAA+sAAAKC/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACAPgAAUD4AAKA+AABQPgAAgD4AANA+AACgPgAA0D4AAJA+AAAAAAAAsD4AAAAAAACQPgAAUD4AALA+AABQPgAADD8AAIA9AADQPgAAgD0AAAw/AAAAAAAA0D4AAAAAAABQPgAA0D4AAIA9AADQPgAAUD4AAPA+AACAPQAA8D4AABA+AAAAAAAAkD4AAAAAAAAQPgAAUD4AAJA+AABQPgAAAAAAAAAAAAAQPgAAAAAAAAAAAABQPgAAED4AAFA+AAACAAEAAgADAAEABAAGAAUABgAHAAUACAAKAAkACgALAAkADAAOAA0ADgAPAA0AEAASABEAEgATABEAFAAWABUAFgAXABUA"}],"accessors":[{"bufferView":0,"componentType":5126,"count":24,"max":[2.71875,0.3125,1.25],"min":[-2.71875,-7.8125,-1.25],"type":"VEC3"},{"bufferView":1,"componentType":5126,"count":24,"max":[1,1,1],"min":[-1,-1,-1],"type":"VEC3"},{"bufferView":2,"componentType":5126,"count":24,"max":[0.546875,0.46875],"min":[0,0],"type":"VEC2"},{"bufferView":3,"componentType":5123,"count":36,"max":[23],"min":[0],"type":"SCALAR"}],"materials":[{"pbrMetallicRoughness":{"metallicFactor":0,"roughnessFactor":1,"baseColorTexture":{"index":0}},"alphaMode":"MASK","alphaCutoff":0.05,"doubleSided":true}],"textures":[{"sampler":0,"source":0,"name":"rgt_iron_chestplate"}],"samplers":[{"magFilter":9728,"minFilter":9728,"wrapS":33071,"wrapT":33071}],"images":[{"mimeType":"image/png","name":"rgt_iron_chestplate.png","uri":"rgt_iron_chestplate.png"}],"meshes":[{"primitives":[{"mode":4,"attributes":{"POSITION":0,"NORMAL":1,"TEXCOORD_0":2},"indices":3,"material":0}]}]}

View file

@ -0,0 +1 @@
{"asset":{"version":"2.0","generator":"Blockbench 4.12.5 glTF exporter"},"scenes":[{"nodes":[2],"name":"blockbench_export"}],"scene":0,"nodes":[{"name":"cube","mesh":0},{"name":"cube","mesh":1},{"children":[0,1]}],"bufferViews":[{"buffer":0,"byteOffset":0,"byteLength":288,"target":34962,"byteStride":12},{"buffer":0,"byteOffset":288,"byteLength":288,"target":34962,"byteStride":12},{"buffer":0,"byteOffset":576,"byteLength":192,"target":34962,"byteStride":8},{"buffer":0,"byteOffset":768,"byteLength":72,"target":34963},{"buffer":0,"byteOffset":840,"byteLength":288,"target":34962,"byteStride":12},{"buffer":0,"byteOffset":1128,"byteLength":288,"target":34962,"byteStride":12},{"buffer":0,"byteOffset":1416,"byteLength":192,"target":34962,"byteStride":8},{"buffer":0,"byteOffset":1608,"byteLength":72,"target":34963}],"buffers":[{"byteLength":1680,"uri":"data:application/octet-stream;base64,AAAqQAAA3EAAACpAAAAqQAAA3EAAACrAAAAqQAAA8D8AACpAAAAqQAAA8D8AACrAAAAqwAAA3EAAACrAAAAqwAAA3EAAACpAAAAqwAAA8D8AACrAAAAqwAAA8D8AACpAAAAqwAAA3EAAACrAAAAqQAAA3EAAACrAAAAqwAAA3EAAACpAAAAqQAAA3EAAACpAAAAqwAAA8D8AACpAAAAqQAAA8D8AACpAAAAqwAAA8D8AACrAAAAqQAAA8D8AACrAAAAqwAAA3EAAACpAAAAqQAAA3EAAACpAAAAqwAAA8D8AACpAAAAqQAAA8D8AACpAAAAqQAAA3EAAACrAAAAqwAAA3EAAACrAAAAqQAAA8D8AACrAAAAqwAAA8D8AACrAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACgPgAAgD4AABA/AACAPgAAoD4AAAA/AAAQPwAAAD8AABA/AAAAAAAAUD8AAAAAAAAQPwAAgD4AAFA/AACAPgAAUD8AAAA/AAAQPwAAAD8AAFA/AACAPgAAED8AAIA+AABQPwAAAD8AABA/AAAAPwAAUD8AAEA/AAAQPwAAQD8AAKA+AAAAPwAAED8AAAA/AACgPgAAQD8AABA/AABAPwAAoD4AAAAAAAAQPwAAAAAAAKA+AACAPgAAED8AAIA+AAACAAEAAgADAAEABAAGAAUABgAHAAUACAAKAAkACgALAAkADAAOAA0ADgAPAA0AEAASABEAEgATABEAFAAWABUAFgAXABUAAABcQAAA8D8AAFxAAABcQAAA8D8AAFzAAABcQAAAAAAAAFxAAABcQAAAAAAAAFzAAABcwAAA8D8AAFzAAABcwAAA8D8AAFxAAABcwAAAAAAAAFzAAABcwAAAAAAAAFxAAABcwAAA8D8AAFzAAABcQAAA8D8AAFzAAABcwAAA8D8AAFxAAABcQAAA8D8AAFxAAABcwAAAAAAAAFxAAABcQAAAAAAAAFxAAABcwAAAAAAAAFzAAABcQAAAAAAAAFzAAABcwAAA8D8AAFxAAABcQAAA8D8AAFxAAABcwAAAAAAAAFxAAABcQAAAAAAAAFxAAABcQAAA8D8AAFzAAABcwAAA8D8AAFzAAABcQAAAAAAAAFzAAABcwAAAAAAAAFzAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAMD8AAKA+AAAwPwAAAAAAAEA/AACgPgAAQD8AAKA+AABAPwAAID8AAEA/AACgPgAAUD8AACA/AABQPwAAoD4AAKA+AAAAAAAAoD4AAKA+AAAAAAAAAAAAAAAAAACgPgAAoD4AAAAAAACgPgAAoD4AACA/AAAAAAAAID8AAAAAAABAPwAAoD4AAEA/AAAAAAAAUD8AAKA+AABQPwAAAAAAACA/AACgPgAAID8AAAAAAAAwPwAAoD4AADA/AAACAAEAAgADAAEABAAGAAUABgAHAAUACAAKAAkACgALAAkADAAOAA0ADgAPAA0AEAASABEAEgATABEAFAAWABUAFgAXABUA"}],"accessors":[{"bufferView":0,"componentType":5126,"count":24,"max":[2.65625,6.875,2.65625],"min":[-2.65625,1.875,-2.65625],"type":"VEC3"},{"bufferView":1,"componentType":5126,"count":24,"max":[1,1,1],"min":[-1,-1,-1],"type":"VEC3"},{"bufferView":2,"componentType":5126,"count":24,"max":[0.8125,0.75],"min":[0.3125,0],"type":"VEC2"},{"bufferView":3,"componentType":5123,"count":36,"max":[23],"min":[0],"type":"SCALAR"},{"bufferView":4,"componentType":5126,"count":24,"max":[3.4375,1.875,3.4375],"min":[-3.4375,0,-3.4375],"type":"VEC3"},{"bufferView":5,"componentType":5126,"count":24,"max":[1,1,1],"min":[-1,-1,-1],"type":"VEC3"},{"bufferView":6,"componentType":5126,"count":24,"max":[0.625,0.8125],"min":[0,0],"type":"VEC2"},{"bufferView":7,"componentType":5123,"count":36,"max":[23],"min":[0],"type":"SCALAR"}],"materials":[{"pbrMetallicRoughness":{"metallicFactor":0,"roughnessFactor":1,"baseColorTexture":{"index":0}},"alphaMode":"MASK","alphaCutoff":0.05,"doubleSided":true}],"textures":[{"sampler":0,"source":0,"name":"rgt_top_hat"}],"samplers":[{"magFilter":9728,"minFilter":9728,"wrapS":33071,"wrapT":33071}],"images":[{"mimeType":"image/png","name":"rgt_top_hat.png","uri":"rgt_top_hat.png"}],"meshes":[{"primitives":[{"mode":4,"attributes":{"POSITION":0,"NORMAL":1,"TEXCOORD_0":2},"indices":3,"material":0}]},{"primitives":[{"mode":4,"attributes":{"POSITION":4,"NORMAL":5,"TEXCOORD_0":6},"indices":7,"material":0}]}]}

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 513 B

View file

@ -3,6 +3,8 @@ rgt_cosmetics = {
} }
local ns = rgt_cosmetics local ns = rgt_cosmetics
include "wearables.lua"
--[[ --[[
{ {
name = "", -- Technical name name = "", -- Technical name

View file

@ -0,0 +1,118 @@
local ns = rgt_cosmetics
ns.wearables = {}
--[[
{
name = "", -- Name of the wearable
attachments = { -- List of individual attachments managed by this wearable (in case one wearable involves multiple bones)
mesh = "", -- The wearable's mesh
textures = {"", ...}, -- The wearable's textures
bone = ", -- Name of the player bone to attach to
pos = <vector>, -- Attachment offset
rot = <vector>, -- Attachment rotation
}
}
--]]
function ns.register_wearable(def)
ns.wearables[def.name] = def
end
minetest.register_entity("rgt_cosmetics:wearable", {
initial_properties = {
visual = "mesh",
pointable = false,
static_save = false
},
on_activate = function(e)
e.object:set_armor_groups{immortal = 1}
end,
represent = function(e, form)
e.form = form
e.object:set_properties {
mesh = form.mesh,
textures = form.textures
}
e.object:set_attach(e.owner.object, form.bone, form.pos, form.rot)
if form.animation then
e.object:set_animation(form.animation, form.animation.frame_speed or 1, nil, form.animation.loop)
end
end,
on_deactivate = function(e, removed)
-- Reactivate immediately if we were not explicitly marked for removal.
-- This is to prevent wearables from being lost to unloading, and to
-- minimize interference from mods that might try to remove objects
-- they shouldn't try to remove. Note that we must check get_pos() here
-- because, since on_leaveplayer is called _after_ mapblock unloading,
-- the entity may otherwise attempt to reactivate itself when its
-- owner has left the game (causing a crash).
if not e._remove and e.owner.object:get_pos() then
e.owner.wearing[e.form.name][e.index] = ns.apply_wearable_part(e.owner, e.form, e.index)
end
end
})
function ns.apply_wearable_part(m, w, i)
local obj = minetest.add_entity(m.pos, "rgt_cosmetics:wearable")
local e = obj:get_luaentity()
e.owner = m
e.index = i
e:represent(w)
return obj
end
function ns.apply_wearable(m, wearable)
local w = type(wearable) == "string" and ns.wearables[wearable] or wearable
-- Do nothing if we're already wearing this.
if m.wearing[w.name] then return end
local item = {}
for i, x in ipairs(w.attachments) do
x.name = w.name
item[i] = ns.apply_wearable_part(m, x, i)
end
m.wearing[w.name] = item
end
function ns.remove_wearable(m, wearable)
if m.wearing[wearable] then
for _, x in pairs(m.wearing[wearable]) do
-- Explicitly mark the object for removal.
x:get_luaentity()._remove = true
x:remove()
end
m.wearing[wearable] = nil
end
end
minetest.register_on_leaveplayer(function(p)
local m = rgt.players[p:get_player_name()]
for k in pairs(m.wearing) do
ns.remove_wearable(m, k)
end
end)
ns.register_wearable {
name = "top_hat",
attachments = {
{
mesh = "rgt_top_hat.gltf",
textures = {"rgt_top_hat.png"},
bone = "Head",
pos = vector.new(0, 3.5, 0),
rot = vector.new(0, 0, 0)
}
}
}
minetest.register_chatcommand("wear", {
func = function(name, args)
ns.apply_wearable(rgt.players[name], args)
end
})
minetest.register_chatcommand("unwear", {
func = function(name, args)
ns.remove_wearable(rgt.players[name], args)
end
})

View file

@ -43,10 +43,40 @@ Player = {
e.hud = {} e.hud = {}
e.poi = {} e.poi = {}
e.wearing = {}
e:update_hp(p:get_hp()) e:update_hp(p:get_hp())
e:update_inv()
return e return e
end, end,
update_inv = function(m)
m.object:set_formspec_prepend [[
bgcolor[#000;true]
background9[0,0;0,0;rgt_container_bg.png;true;16,16]
style_type[button;border=false;bgimg=rgt_button_bg.png;bgimg_middle=8,8]
listcolors[#fff0;#fff3;#0000;#444;#aaa]
]]
local fs = "\
formspec_version[10]\
size[12,10]\
"
for x = 0, 7 do
for y = 0, 3 do
fs = fs.."\
image["..(x *1.25 +1 -0.0625)..","..(y *1.25 +4.5 -0.0625)..";1.14,1.14;rgt_other_button_bg.png;8,8]\
"
end
end
fs = fs.."\
list[current_player;main;1,4.5;8,4;]\
list[current_player;craft;3,0.5;3,3;]\
listring[]\
list[current_player;craftpreview;7,1;1,1;]\
"
m.object:set_inventory_formspec(fs)
end,
update_hp = function(m, hp) update_hp = function(m, hp)
if not (m.health_display and m.health_display:is_valid()) then if not (m.health_display and m.health_display:is_valid()) then
local pos = m.object:get_pos() or vector.zero() local pos = m.object:get_pos() or vector.zero()
@ -109,6 +139,8 @@ Player = {
wield_item = def.name wield_item = def.name
} }
m.wielditem_display:set_attach(m.object, "RightArm", pos, rot) m.wielditem_display:set_attach(m.object, "RightArm", pos, rot)
-- Apparently this forces a resend so that properties and attachment position will sync up?
m.wielditem_display:set_pos(m.wielditem_display:get_pos())
end, end,
tick = function(m, dtime) tick = function(m, dtime)
local time = minetest.get_us_time() local time = minetest.get_us_time()
@ -333,6 +365,7 @@ Player = {
end, end,
deinit = function(m) deinit = function(m)
m.health_display:remove() m.health_display:remove()
m.wielditem_display:remove()
rgt.players[m.name] = nil rgt.players[m.name] = nil
end end
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 327 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 494 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 B