1313 * see <http://www.gnu.org/licenses/>.
1414 */
1515
16- package org .enginehub .craftbook .mechanics .headdrops ;
16+ package org .enginehub .craftbook .bukkit . mechanics .headdrops ;
1717
1818import com .destroystokyo .paper .profile .PlayerProfile ;
19+ import com .destroystokyo .paper .profile .ProfileProperty ;
1920import com .google .common .collect .Maps ;
2021import com .sk89q .util .yaml .YAMLProcessor ;
22+ import com .sk89q .worldedit .bukkit .BukkitAdapter ;
2123import com .sk89q .worldedit .util .formatting .text .TextComponent ;
2224import com .sk89q .worldedit .util .formatting .text .TranslatableComponent ;
2325import net .kyori .adventure .text .Component ;
2426import net .kyori .adventure .text .format .Style ;
2527import net .kyori .adventure .text .format .TextDecoration ;
28+ import org .bukkit .Bukkit ;
2629import org .bukkit .GameMode ;
2730import org .bukkit .Material ;
2831import org .bukkit .NamespacedKey ;
4548import org .bukkit .inventory .meta .ItemMeta ;
4649import org .bukkit .inventory .meta .SkullMeta ;
4750import org .bukkit .persistence .PersistentDataType ;
48- import org .enginehub .craftbook .AbstractCraftBookMechanic ;
4951import org .enginehub .craftbook .CraftBook ;
5052import org .enginehub .craftbook .CraftBookPlayer ;
5153import org .enginehub .craftbook .bukkit .CraftBookPlugin ;
5254import org .enginehub .craftbook .mechanic .CraftBookMechanic ;
5355import org .enginehub .craftbook .mechanic .MechanicCommandRegistrar ;
5456import org .enginehub .craftbook .mechanic .MechanicType ;
57+ import org .enginehub .craftbook .mechanics .headdrops .HeadDrops ;
58+ import org .enginehub .craftbook .mechanics .headdrops .SkinData ;
5559import org .enginehub .craftbook .util .EventUtil ;
5660import org .jspecify .annotations .Nullable ;
5761
5862import java .util .HashMap ;
5963import java .util .List ;
6064import java .util .Map ;
6165import java .util .Objects ;
66+ import java .util .Set ;
67+ import java .util .UUID ;
6268import java .util .concurrent .ThreadLocalRandom ;
69+ import java .util .stream .Collectors ;
6370
64- public class HeadDrops extends AbstractCraftBookMechanic implements Listener {
71+ public class BukkitHeadDrops extends HeadDrops implements Listener {
6572
6673 private static final Map <EntityType , PlayerProfile > TEXTURE_MAP = Maps .newHashMap ();
74+ protected static final String HEAD_NAME = "cb-headdrops" ;
75+ private static final UUID DEFAULT_UUID = UUID .fromString ("a233eb4b-4cab-42cd-9fd9-7e7b9a3f74be" );
76+
77+ protected static PlayerProfile createProfile (String texture ) {
78+ PlayerProfile profile = Bukkit .createProfile (DEFAULT_UUID , HEAD_NAME );
79+ profile .setProperty (new ProfileProperty ("textures" , texture ));
80+
81+ return profile ;
82+ }
6783
6884 static {
6985 // skip if the CRAFTBOOK_DOCGEN environment variable is set
7086 // This breaks docgen currently.
7187 if (System .getenv ("CRAFTBOOK_DOCGEN" ) == null ) {
72- SkinData .addDefaultSkinData (TEXTURE_MAP );
88+ SkinData .addDefaultSkinData ((entityType , textureString ) -> {
89+ if (entityType != null ) {
90+ TEXTURE_MAP .put (BukkitAdapter .adapt (entityType ), createProfile (textureString ));
91+ }
92+ });
7393 }
7494 }
7595
7696 private final NamespacedKey headDropsEntityKey = new NamespacedKey ("craftbook" , "head_drops_entity" );
7797
78- public HeadDrops (MechanicType <? extends CraftBookMechanic > mechanicType ) {
98+ public BukkitHeadDrops (MechanicType <? extends CraftBookMechanic > mechanicType ) {
7999 super (mechanicType );
80100 }
81101
@@ -204,7 +224,7 @@ public void onPlayerInteract(PlayerInteractEvent event) {
204224 }
205225 } else {
206226 PlayerProfile profile = skull .getPlayerProfile ();
207- if (profile == null || profile .getName () == null || profile .getName ().equals (SkinData . HEAD_NAME )) {
227+ if (profile == null || profile .getName () == null || profile .getName ().equals (HEAD_NAME )) {
208228 return ;
209229 }
210230
@@ -319,38 +339,12 @@ private NamespacedKey parseKey(String name) {
319339 }
320340 }
321341
322- private boolean enableMobs ;
323- private boolean enablePlayers ;
324- private boolean playerKillsOnly ;
325- private boolean overrideNatural ;
326- private double dropRate ;
327- private double lootingModifier ;
328- private boolean nameOnClick ;
329342 private HashMap <NamespacedKey , Double > customDropRates ;
330343 private HashMap <NamespacedKey , PlayerProfile > customSkins ;
331344
332345 @ Override
333346 public void loadFromConfiguration (YAMLProcessor config ) {
334- config .setComment ("drop-mob-heads" , "Whether mobs should drop their heads when killed." );
335- enableMobs = config .getBoolean ("drop-mob-heads" , true );
336-
337- config .setComment ("drop-player-heads" , "Whether players should drop their heads when killed." );
338- enablePlayers = config .getBoolean ("drop-player-heads" , true );
339-
340- config .setComment ("require-player-killer" , "Only drop heads when killed by a player. (Allows requiring permission)" );
341- playerKillsOnly = config .getBoolean ("require-player-killer" , true );
342-
343- config .setComment ("override-natural-head-drops" , "Override natural head drops, this will cause natural head drops to use the chances provided by CraftBook. (Eg, Wither Skeleton Heads)" );
344- overrideNatural = config .getBoolean ("override-natural-head-drops" , false );
345-
346- config .setComment ("drop-rate" , "A value between 1 and 0 which dictates the global chance of heads being dropped. This can be overridden per-entity type." );
347- dropRate = config .getDouble ("drop-rate" , 0.05 );
348-
349- config .setComment ("looting-rate-modifier" , "This amount is added to the chance for every looting level on an item. Eg, a chance of 0.05(5%) and a looting mod of 0.05(5%) on a looting 3 sword, would give a 0.20 chance (20%)." );
350- lootingModifier = config .getDouble ("looting-rate-modifier" , 0.05 );
351-
352- config .setComment ("show-name-right-click" , "When enabled, right clicking a placed head will say the owner of the head." );
353- nameOnClick = config .getBoolean ("show-name-right-click" , true );
347+ super .loadFromConfiguration (config );
354348
355349 config .setComment ("drop-rates" , "A list of custom drop rates for different mobs" );
356350 customDropRates = new HashMap <>();
@@ -366,10 +360,31 @@ public void loadFromConfiguration(YAMLProcessor config) {
366360 customSkins = new HashMap <>();
367361 if (config .getKeys ("custom-skins" ) != null ) {
368362 for (String key : config .getKeys ("custom-skins" )) {
369- customSkins .put (parseKey (key ), SkinData . createProfile (config .getString ("custom-skins." + key )));
363+ customSkins .put (parseKey (key ), createProfile (config .getString ("custom-skins." + key )));
370364 }
371365 } else {
372366 config .addNode ("custom-skins" );
373367 }
374368 }
369+
370+ private static final Set <EntityType > IGNORED_ENTITIES = Set .of (
371+ EntityType .PLAYER , EntityType .ZOMBIE , EntityType .CREEPER ,
372+ EntityType .SKELETON , EntityType .WITHER_SKELETON ,
373+ EntityType .ARMOR_STAND , EntityType .ENDER_DRAGON , EntityType .PIGLIN ,
374+ EntityType .UNKNOWN , EntityType .MANNEQUIN
375+ );
376+
377+ @ SuppressWarnings ("unused" )
378+ private static void printMissingSkins () {
379+ String missingText = Registry .ENTITY_TYPE .stream ()
380+ .filter (type -> !IGNORED_ENTITIES .contains (type ) && type .isAlive ())
381+ .filter (type -> !TEXTURE_MAP .containsKey (type ))
382+ .map (EntityType ::getKey )
383+ .map (NamespacedKey ::toString )
384+ .collect (Collectors .joining (", " ));
385+
386+ if (!missingText .isEmpty ()) {
387+ CraftBook .LOGGER .warn (missingText );
388+ }
389+ }
375390}
0 commit comments