Files
GeyserWebsite/_site/geyser/custom-skulls/index.html
T

562 lines
25 KiB
HTML
Raw Normal View History

2023-11-07 19:40:55 -06:00
<!doctype html>
<html lang="en" data-bs-theme="dark">
<head>
<meta charset="utf-8">
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>GeyserMC Wiki: Custom skulls with Geyser</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.3/font/bootstrap-icons.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/css/style.css">
<link rel="stylesheet" href="/css/darcula.css">
<meta name="author" content="GeyserMC">
<meta name="description" content="This is the wiki for all of GeyserMC's projects.">
<meta name="theme-color" content="#2b3035">
<meta property="og:type" content="website">
<meta property="og:url" content="http://localhost:4000">
<meta property="og:title" content="GeyserMC Wiki: Custom skulls with Geyser">
<meta property="og:description" content="This is the wiki for all of GeyserMC's projects.">
<meta property="og:image" content="/android-chrome-192x192.png">
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
<link rel="icon" type="image/x-icon" href="/favicon.ico">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="192x192" href="/android-chrome-192x192.png">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#248f00">
</head>
<body>
<header>
<nav class="navbar navbar-expand-lg bg-body-tertiary fixed-top">
<div class="container-fluid">
<a class="navbar-brand" href="/"><img src="/android-chrome-512x512.png" alt="geyser logo" height="32"> GeyserMC Wiki</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarLinks" aria-controls="navbarLinks" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarLinks">
<ul class="navbar-nav ms-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link" href="https://geysermc.org/"><i class="bi bi-house pe-1"></i> Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="https://geysermc.org/download"><i class="bi bi-download pe-1"></i> Download</a>
</li>
</ul>
<form class="d-flex" role="search" action="/search/">
<div class="input-group">
<button class="btn btn-outline-secondary" type="submit" id="button-search"><i class="bi bi-search"></i></button>
<input type="text" name="q" class="form-control" placeholder="Search the site..." aria-label="Search the site..." aria-describedby="button-search">
</div>
</form>
</div>
</div>
</nav>
</header>
<div id="page-content" class="container-fluid">
<div class="row">
<div class="col-12 col-md-3 col-xl-2">
<div class="sticky-top">
<div class="sidebar py-2 text-break">
<nav class="navbar navbar-expand-md">
<div class="container-fluid">
<div class="d-block d-md-none">Wiki Navigation</div>
<button class="navbar-toggler mb-2" type="button" data-bs-toggle="collapse" data-bs-target="#sidebarNav" aria-controls="sidebarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse flex-column align-items-start" id="sidebarNav">
<div class="nav-item dropdown">
<a class="nav-link dropdown-toggle fw-bold show" href="#" role="button" data-bs-toggle="dropdown" data-bs-auto-close="false" aria-expanded="false">Geyser Documentation</a>
<ul class="pe-3 pt-0 dropdown-menu position-relative border-0 list-disc show">
<li class="ms-4">
<a href="/geyser/setup/">Setting up Geyser</a>
<ul>
<li>
<a href="/geyser/supported-hosting-providers/">Supported Hosting Providers</a>
</li>
<li>
<a href="/geyser/using-geyser-with-consoles/">Using Geyser with Consoles</a>
</li>
<li>
<a href="/geyser/playit-gg/">Using playit.gg with Geyser</a>
</li>
<li>
<a href="/geyser/creating-a-startup-script/">Creating a Startup Script</a>
</li>
</ul>
</li>
<li class="ms-4">
<a href="/geyser/common-issues/">Common Issues</a>
<ul>
<li>
<a href="/geyser/fixing-unable-to-connect-to-world/">Fixing 'Unable to Connect to World'</a>
</li>
</ul>
</li>
<li class="ms-4">
<a href="/geyser/understanding-the-config/">Configuring Geyser</a>
<ul>
<li>
<a href="/geyser/commands/">Commands</a>
</li>
<li>
<a href="/geyser/geyser-command-line-arguments-and-system-properties/">Geyser Command Line Arguments and System Properties</a>
</li>
</ul>
</li>
<li class="ms-4">
<a href="/geyser/faq/">FAQ</a>
<ul>
<li>
<a href="/geyser/anticheat-compatibility/">Anticheat Compatibility</a>
</li>
<li>
<a href="/geyser/current-limitations/">Current Limitations</a>
</li>
</ul>
</li>
<li class="ms-4">
<a href="/geyser/custom-items/">Custom items with Geyser</a>
<ul>
<li>
<a href="/geyser/custom-items/#json-mappings">JSON mappings</a>
</li>
<li>
<a href="/geyser/custom-items/#geyser-extensions">Geyser extensions</a>
</li>
<li>
<a href="/geyser/custom-items/#resource-pack">Resource pack</a>
</li>
</ul>
</li>
<li class="ms-4">
<a href="/geyser/custom-blocks/">Custom blocks with Geyser</a>
<ul>
<li>
<a href="/geyser/custom-blocks/#enabling-custom-blocks">Enabling custom blocks</a>
</li>
<li>
<a href="/geyser/custom-blocks/#json-mappings">JSON mappings</a>
</li>
<li>
<a href="/geyser/custom-blocks/#geyser-extensions">Geyser extensions</a>
</li>
</ul>
</li>
<li class="ms-4">
<a href="/geyser/custom-skulls/">Custom skulls with Geyser</a>
<ul>
<li>
<a href="/geyser/custom-skulls/#enabling-custom-skulls">Enabling custom skulls</a>
</li>
<li>
<a href="/geyser/custom-skulls/#custom-skullsyml">custom-skulls.yml</a>
</li>
</ul>
</li>
<li class="ms-4">
<a href="/geyser/api/">Geyser API</a>
<ul>
<li>
<a href="/geyser/getting-started-with-the-api/">Getting Started</a>
</li>
<li>
<a href="/geyser/api/#short-overview-of-the-geyser-api">Overview</a>
</li>
<li>
<a href="/geyser/events/">Events</a>
</li>
<li>
<a href="/geyser/forms/">Forms and Cumulus</a>
</li>
</ul>
</li>
<li class="ms-4">
<a href="/geyser/extensions/">Geyser Extensions</a>
<ul>
<li>
<a href="/geyser/extensions/#creating-the-main-class">Main class</a>
</li>
<li>
<a href="/geyser/extensions/#creating-commands-with-geyser-extensions">Creating Commands</a>
</li>
</ul>
</li>
<li class="ms-4">
<a href="/geyser/global-api/">Global API</a>
</li>
</ul>
</div>
<div class="nav-item dropdown">
<a class="nav-link dropdown-toggle fw-bold" href="#" role="button" data-bs-toggle="dropdown" data-bs-auto-close="false" aria-expanded="false">Floodgate Documentation</a>
<ul class="pe-3 pt-0 dropdown-menu position-relative border-0 list-disc">
<li class="ms-4">
<a href="/floodgate/setup/">Setup</a>
</li>
<li class="ms-4">
<a href="/floodgate/issues/">Issues</a>
</li>
<li class="ms-4">
<a href="/floodgate/faq/">FAQ</a>
</li>
<li class="ms-4">
<a href="/floodgate/features/">Features</a>
<ul>
<li>
<a href="/floodgate/features/#whitelist-command">Whitelist command</a>
</li>
<li>
<a href="/floodgate/commands/">Commands</a>
</li>
<li>
<a href="/floodgate/features/#what-is-skin-uploading">Skin Uploading</a>
</li>
</ul>
</li>
<li class="ms-4">
<a href="/floodgate/api/">Floodgate API</a>
<ul>
<li>
<a href="/floodgate/player/">FloodgatePlayer</a>
</li>
<li>
<a href="/geyser/forms/">Forms and Cumulus</a>
</li>
</ul>
</li>
<li class="ms-4">
<a href="/floodgate/linking/">Linking</a>
<ul>
<li>
<a href="/floodgate/linking/#what-is-global-linking">Global Linking</a>
</li>
<li>
<a href="/floodgate/linking/#local-linking">Local Linking</a>
</li>
</ul>
</li>
</ul>
</div>
<div class="nav-item dropdown">
<a class="nav-link dropdown-toggle fw-bold" href="#" role="button" data-bs-toggle="dropdown" data-bs-auto-close="false" aria-expanded="false">Other</a>
<ul class="pe-3 pt-0 dropdown-menu position-relative border-0 list-disc">
<li class="ms-4">
<a href="/other/geyseroptionalpack/">GeyserOptionalPack</a>
</li>
<li class="ms-4">
<a href="/other/hurricane/">Hurricane</a>
</li>
<li class="ms-4">
<a href="/other/geyserconnect/">GeyserConnect</a>
</li>
<li class="ms-4">
<a href="/other/community-geyser-projects/">Community Geyser Projects</a>
</li>
<li class="ms-4">
<a href="/other/test-server/">Test Server</a>
</li>
<li class="ms-4">
<a href="/other/developer-guide/">Developer Guide</a>
</li>
<li class="ms-4">
<a href="/other/discord-bot-usage/">Geyser Discord Bot Usage</a>
</li>
</ul>
</div>
</div>
</div>
</nav>
</div>
</div>
</div>
<main class="col-12 col-md-9 col-xl-8" role="main">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="http://localhost:4000/geyser/">Geyser</a></li>
<li class="breadcrumb-item active" aria-current="page">Custom skulls with Geyser</li>
</ol>
</nav>
<h1 id="custom-skulls-with-geyser">Custom skulls with Geyser</h1>
<p>Unlike Java Edition, Bedrock does not have native support for custom skull items. As a result, any method to display custom skulls with Geyser is, to some extent, a workaround. Geyser has long supported in-world custom skulls via the spawning of player entities. This, however, does not allow for the use of custom skulls in inventories, nor does it allow them to be worn by entities. To resolve this, Geyser now allows for the pre-registration of custom skulls via a config file. Geyser will then use this config file to generate a custom resource pack on start that contains the geometry and textures for the pre-registered custom skulls. To the client, these skulls are blocks. Therefore, they can be held in player inventories. In additional, attachables are defined for each skull block so that it is displayed correctly when worn and held by entities.</p>
<p>To setup custom skulls in geyser, you have to choose how you are going to register your blocks. The easiest is <a href="#custom-skullsyml">using custom-skulls.yml</a> but you can also <a href="#geyser-extensions">use a Geyser extension</a>.</p>
<h2 id="enabling-custom-skulls">Enabling custom skulls</h2>
<p>To enable custom skulls, you must set <code class="language-plaintext highlighter-rouge">add-non-bedrock-items</code> to <code class="language-plaintext highlighter-rouge">true</code> in the <code class="language-plaintext highlighter-rouge">config.yml</code> file. This will enable the generation of the custom resource pack and the translation of custom skulls to custom blocks. You can then add custom skulls to the <code class="language-plaintext highlighter-rouge">custom-skulls.yml</code> file.</p>
<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Whether to add any items and blocks which normally does not exist in Bedrock Edition.</span>
<span class="c1"># This should only need to be disabled if using a proxy that does not use the "transfer packet" style of server switching.</span>
<span class="c1"># If this is disabled, furnace minecart items will be mapped to hopper minecart items.</span>
<span class="c1"># Geyser's block, item, and skull mappings systems will also be disabled.</span>
<span class="c1"># This option requires a restart of Geyser in order to change its setting.</span>
<span class="na">add-non-bedrock-items</span><span class="pi">:</span> <span class="no">true</span>
</code></pre></div></div>
<h2 id="custom-skullsyml">custom-skulls.yml</h2>
<p>The configuration file <code class="language-plaintext highlighter-rouge">custom-skulls.yml</code> is present in Geyser’s configuration folder and is laid out as follows:</p>
<div class="language-yml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># --------------------------------</span>
<span class="c1"># Geyser Custom Skull Configuration Files</span>
<span class="c1">#</span>
<span class="c1"># This file is ignored with `add-custom-skull-blocks` disabled.</span>
<span class="c1"># See `config.yml` for the main set of configuration values</span>
<span class="c1">#</span>
<span class="c1"># Custom skulls with the player username, UUID, or texture specified in this file</span>
<span class="c1"># will be translated as custom blocks and be displayed in the inventory and on entities.</span>
<span class="c1"># --------------------------------</span>
<span class="c1"># Java player usernames</span>
<span class="c1"># Skins will be updated when Geyser starts and players will have to re-download</span>
<span class="c1"># the resource pack if any players had changed their skin.</span>
<span class="na">player-usernames</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">GeyserMC</span>
<span class="c1"># Java player UUIDs</span>
<span class="c1"># Skins will be updated when Geyser starts and players will have to re-download</span>
<span class="c1"># the resource pack if any players had changed their skin.</span>
<span class="na">player-uuids</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">8b8d8e8f-2759-47c6-acb5-5827de8a72b8</span>
<span class="c1"># The long string of characters found in the NBT of custom player heads</span>
<span class="na">player-profiles</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">ewogICJ0aW1lc3RhbXAiIDogMTY1NzMyMjIzOTgzMywKICAicHJvZmlsZUlkIiA6ICJjZGRiZTUyMGQwNDM0YThiYTFjYzlmYzkyZmRlMmJjZiIsCiAgInByb2ZpbGVOYW1lIiA6ICJBbWJlcmljaHUiLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTkwNzkwYzU3ZTE4MWVkMTNhZGVkMTRjNDdlZTJmN2M4ZGUzNTMzZTAxN2JhOTU3YWY3YmRmOWRmMWJkZTk0ZiIsCiAgICAgICJtZXRhZGF0YSIgOiB7CiAgICAgICAgIm1vZGVsIiA6ICJzbGltIgogICAgICB9CiAgICB9CiAgfQp9</span>
<span class="c1"># The hash of the skin on Minecraft's skin server</span>
<span class="na">skin-hashes</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">a90790c57e181ed13aded14c47ee2f7c8de3533e017ba957af7bdf9df1bde94f</span>
</code></pre></div></div>
<h3 id="player-usernames">Player usernames</h3>
<p>Skulls can be registered in this section via player usernames. These will be updated when Geyser starts. As a result, they may change if the player’s username or skin changes.</p>
<h3 id="player-uuids">Player UUIDs</h3>
<p>Skulls can be registered in this section via player UUIDs. These will be updated when Geyser starts. As a result, they may change if skin changes.</p>
<h3 id="player-profiles">Player profiles</h3>
<p>Skulls can be registered in this section via the texture string found in the NBT of custom player heads. Unless the value is changed manually, these will not be updated when Geyser starts. As a result, they will not change if the player’s username or skin changes. The data is simply base64 encoded JSON. For instance, the example given in the config decodes as follows:</p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
</span><span class="nl">"timestamp"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="mi">1657322239833</span><span class="p">,</span><span class="w">
</span><span class="nl">"profileId"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"cddbe520d0434a8ba1cc9fc92fde2bcf"</span><span class="p">,</span><span class="w">
</span><span class="nl">"profileName"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"Amberichu"</span><span class="p">,</span><span class="w">
</span><span class="nl">"textures"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"SKIN"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"url"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"http://textures.minecraft.net/texture/a90790c57e181ed13aded14c47ee2f7c8de3533e017ba957af7bdf9df1bde94f"</span><span class="p">,</span><span class="w">
</span><span class="nl">"metadata"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"model"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"slim"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<p>If on a paper server, this data can be obtained for a skull by holding the item in hand, and running the command <code class="language-plaintext highlighter-rouge">/paper dumpitem</code>. This will output the NBT data of the item to chat and console. The texture string is found in the <code class="language-plaintext highlighter-rouge">SkullOwner</code> tag, under the <code class="language-plaintext highlighter-rouge">Properties</code> tag, under the <code class="language-plaintext highlighter-rouge">textures</code> tag, under the <code class="language-plaintext highlighter-rouge">Value</code> tag. For example:</p>
<pre><code class="language-log">[05:58:07 INFO]: .KastleFirefox issued server command: /paper dumpitem
[05:58:07 INFO]: minecraft:player_head{display: {Name: '{"text":"Test"}'}, SkullOwner: {Properties: {textures: [{Value: "ewogICJ0aW1lc3RhbXAiIDogMTY1NzMyMjIzOTgzMywKICAicHJvZmlsZUlkIiA6ICJjZGRiZTUyMGQwNDM0YThiYTFjYzlmYzkyZmRlMmJjZiIsCiAgInByb2ZpbGVOYW1lIiA6ICJkYXZjaG9vIiwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2E5MDc5MGM1N2UxODFlZDEzYWRlZDE0YzQ3ZWUyZjdjOGRlMzUzM2UwMTdiYTk1N2FmN2JkZjlkZjFiZGU5NGYiLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ"}]}, Id: [I; -229048314, -553040501, -1407961158, 465313087]}}
</code></pre>
<h3 id="skin-hashes">Skin Hashes</h3>
<p>Skulls can be registered in this section via the hash of the skin on Minecraft’s skin server. This is found at the end of the URL. For example, in the URL <code class="language-plaintext highlighter-rouge">http://textures.minecraft.net/texture/a90790c57e181ed13aded14c47ee2f7c8de3533e017ba957af7bdf9df1bde94f</code> the hash is <code class="language-plaintext highlighter-rouge">a90790c57e181ed13aded14c47ee2f7c8de3533e017ba957af7bdf9df1bde94f</code>.Unless the value is changed manually, these will not be updated when Geyser starts. As a result, they will not change if the player’s username or skin changes.</p>
<p>This can be obtained by decoding the base64 data obtained from a player profile.</p>
<h2 id="geyser-extensions">Geyser extensions</h2>
<p>In this example, we will register a custom skull from a player profile. We will use the player profile from the example above.</p>
<p>First, create a class that implements Geyser’s Extension class:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">RegisterCustomSkull</span> <span class="kd">implements</span> <span class="nc">Extension</span> <span class="o">{</span>
<span class="c1">//...</span>
<span class="o">}</span>
</code></pre></div></div>
<p>Next, create a method to register your blocks in the <code class="language-plaintext highlighter-rouge">GeyserDefineCustomSkullsEvent</code>:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">RegisterCustomSkull</span> <span class="kd">implements</span> <span class="nc">Extension</span> <span class="o">{</span>
<span class="nd">@Subscribe</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">onDefineCustomSkulls</span><span class="o">(</span><span class="nc">GeyserDefineCustomSkullsEvent</span> <span class="n">event</span><span class="o">)</span> <span class="o">{</span>
<span class="c1">//...</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p>Finally, register your skull in the event. Use the enum SkullTextureType to specify that the value being passed is a player profile:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">RegisterCustomSkull</span> <span class="kd">implements</span> <span class="nc">Extension</span> <span class="o">{</span>
<span class="nd">@Subscribe</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">onDefineCustomSkulls</span><span class="o">(</span><span class="nc">GeyserDefineCustomSkullsEvent</span> <span class="n">event</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">String</span> <span class="n">profile</span> <span class="o">=</span> <span class="s">"ewogICJ0aW1lc3RhbXAiIDogMTY1NzMyMjIzOTgzMywKICAicHJvZmlsZUlkIiA6ICJjZGRiZTUyMGQwNDM0YThiYTFjYzlmYzkyZmRlMmJjZiIsCiAgInByb2ZpbGVOYW1lIiA6ICJkYXZjaG9vIiwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2E5MDc5MGM1N2UxODFlZDEzYWRlZDE0YzQ3ZWUyZjdjOGRlMzUzM2UwMTdiYTk1N2FmN2JkZjlkZjFiZGU5NGYiLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ"</span>
<span class="n">event</span><span class="o">.</span><span class="na">registerCustomSkull</span><span class="o">(</span><span class="n">profile</span><span class="o">,</span> <span class="nc">SkullTextureType</span><span class="o">.</span><span class="na">PROFILE</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<h2 id="scraping-custom-skulls-from-a-world">Scraping custom skulls from a world</h2>
<p>Custom skulls can be extracted from an existing world for easy implementation via mappings or API using the tool <a href="https://github.com/davchoo/HeadExtractor">HeadExtractor</a> made by Amberichu. See the linked repository for usage instructions.</p>
</main>
<div class="col-2 d-none d-xl-block">
<div class="sticky-top">
<div class="sidebar py-2">
<a class="d-block text-decoration-none" href="https://github.com/GeyserMC/GeyserWiki/edit/master/_docs/geyser/custom-skulls.md" target="_blank"><i class="bi bi-pencil"></i> Edit this page</a>
<a class="d-block text-decoration-none" href="https://github.com/GeyserMC/GeyserWiki/issues/new?labels=question&title=Question:&body=Question on: _docs/geyser/custom-skulls.md" target="_blank"><i class="bi bi-github"></i> Create Wiki issue/bug report</a>
<a class="d-block text-decoration-none" href="/issues/new" target="_blank"><i class="bi bi-list-check"></i> Create Geyser issue/bug report</a>
<div id="page-nav" class="py-3 "></div>
</div>
</div>
</div>
</div>
</div>
<!-- <footer class="p-4 text-center bg-body-tertiary">
&copy; 2023 GeyserMC
</footer> -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js" integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN" crossorigin="anonymous"></script>
<script src="/js/page-nav.js"></script>
</body>
</html>