自定义玩家的头:存储的是经过base64编码的JSON包裹的URL,而非图片
玩家的头物品的配置文件组件中包含 {textures:{SKIN:{url:…}}} 的base64编码。这就是为什么玩家的头的外观在制作时就已固定,以及为什么数据库可以包含数万个条目。
自定义玩家的头不包含图片。它包含一个材质哈希值,这个哈希值被包裹在JSON中,再被包裹在base64中,最终存储在物品的配置文件组件(profile component)里。
层级结构
从一个哈希值开始,命令的构建方式如下:
1. hash e3b0c44298fc1c149afbf4c8996fb924…
2. JSON {"textures":{"SKIN":{"url":"http://textures.minecraft.net/texture/<hash>"}}}
3. base64 eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6…
4. component /give @p player_head[profile={properties:[{name:"textures",value:"<base64>"}]}]
四层结构来表达“这个玩家的头看起来像那张图片”。属性名称始终是 textures,而值始终是该JSON结构的base64编码。
由此直接引出两点:
玩家的头是一个快照,而不是指向某个玩家的链接。 URL指向的是一个不可变的材质文件,而不是一个账号。无论制作玩家的头时该哈希值解析为何种材质,它将永远显示那种材质。
数据量极小。 一个玩家的头条目只包含名称、哈希值和一些标签——完全不包含任何图片字节。这就是为什么一个目录可以以纯静态JSON的形式存储数万个玩家的头,并且仍然能快速加载。
目录按类别加载的原因
这里的数据库是TheSilentPro的CC0玩家的头合集,它一次只获取一个类别,而不是一次性全部获取。一个索引列出了所有类别及其数量;选择一个类别只会获取该文件。
这不是偷懒的设计,而是这种规模下唯一可行的方式。如果整个合集作为一个单独的JSON文件,对于只想从一个类别中获取三个玩家的头的用户来说,下载量会很大。
300个物品的渲染上限是DOM限制,而非搜索限制
结果最多一次渲染300个。搜索仍然会遍历已加载类别中的所有内容——这个上限适用于有多少项被转换为DOM节点,而不是有多少项被纳入考虑。
当搜索结果显示前300项时,这种区别很重要:那些缺失的条目实际上已经被找到,只是没有显示在页面上,而不是被排除在查询之外。缩小搜索范围会使它们进入显示范围,而不是进行更深入的搜索。
这个上限的存在是为了防止一次性渲染数万个元素,它是一个实际的限制,而不是一个防御性的整数——一个如此大的网格在停止可渲染之前很久就会停止可滚动。
这里不上传任何内容
玩家的头数据是同源的静态JSON。唯一的第三方请求是来自mc-heads.net的 <img> 预览,它将哈希值解析为图片以供显示。/give 命令是根据哈希值在本地组装的,因此无论预览是否加载,该命令都能正常工作。