diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..053c24b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+target/
+server/
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..e0f15db
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "java.configuration.updateBuildConfiguration": "automatic"
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..163a1cb
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,48 @@
+
+
+
+ 4.0.0
+
+ de.thojo0
+ moreheadsounds
+ 1.0-SNAPSHOT
+
+ moreheadsounds
+
+
+ jar
+
+
+ UTF-8
+ 1.8
+ 1.8
+
+
+
+
+ spigot-repo
+ https://hub.spigotmc.org/nexus/content/repositories/snapshots/
+
+
+
+
+ org.spigotmc
+ spigot-api
+ 1.21-R0.1-SNAPSHOT
+ provided
+
+
+
+ ${project.basedir}/src/main/java
+
+
+ ${project.basedir}/src/main/resources
+
+ plugin.yml
+ config.yml
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/de/thojo0/moreheadsounds/App.java b/src/main/java/de/thojo0/moreheadsounds/App.java
new file mode 100644
index 0000000..9e6eb4c
--- /dev/null
+++ b/src/main/java/de/thojo0/moreheadsounds/App.java
@@ -0,0 +1,16 @@
+package de.thojo0.moreheadsounds;
+
+import org.bukkit.plugin.java.JavaPlugin;
+
+public class App extends JavaPlugin {
+ @Override
+ public void onEnable() {
+ saveDefaultConfig();
+ getServer().getPluginManager().registerEvents(new EventListener(getConfig()), this);
+ getLogger().info("MoreHeadSounds activated!");
+ }
+ @Override
+ public void onDisable() {
+ getLogger().info("MoreHeadSounds deactivated!");
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/de/thojo0/moreheadsounds/EventListener.java b/src/main/java/de/thojo0/moreheadsounds/EventListener.java
new file mode 100644
index 0000000..90d5d90
--- /dev/null
+++ b/src/main/java/de/thojo0/moreheadsounds/EventListener.java
@@ -0,0 +1,136 @@
+package de.thojo0.moreheadsounds;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.bukkit.Instrument;
+import org.bukkit.Material;
+import org.bukkit.NamespacedKey;
+import org.bukkit.Sound;
+import org.bukkit.block.Block;
+import org.bukkit.block.BlockFace;
+import org.bukkit.block.Skull;
+import org.bukkit.block.data.type.NoteBlock;
+import org.bukkit.configuration.MemorySection;
+import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.entity.Item;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.block.Action;
+import org.bukkit.event.block.BlockDropItemEvent;
+import org.bukkit.event.player.PlayerInteractEvent;
+import org.bukkit.inventory.meta.SkullMeta;
+
+public class EventListener implements Listener {
+ // Mapping from texture hashes to lists of NamespacedKeys for sounds
+ private HashMap> textureToSounds = new HashMap<>();
+
+ /**
+ * Constructor: initializes the textureToSounds map based on the configuration
+ *
+ * @param config The FileConfiguration object containing sound mappings.
+ */
+ EventListener(FileConfiguration config) {
+ // Get all configuration values
+ Map configValues = config.getValues(false);
+ // Iterate over all available sounds
+ for (Sound sound : Sound.values()) {
+ // Get the NamespacedKey for the current sound
+ NamespacedKey soundKey = sound.getKey();
+ // Iterate over the configuration values
+ configValues.forEach((textureHash, c) -> {
+ // Get the list of excluded sounds for the current texture
+ List exclude = ((MemorySection) c).getStringList("exclude");
+ for (String ex : exclude) {
+ // Split the exclude string into namespace and key
+ String[] splitEx = ex.split(":");
+ String namespace = NamespacedKey.MINECRAFT;
+ String excludeKey = splitEx[0];
+ if (splitEx.length > 1) {
+ namespace = splitEx[0];
+ excludeKey = splitEx[1];
+ }
+ // Skip the sound if it is in the exclude list
+ if (namespace.equals(soundKey.getNamespace()) && soundKey.getKey().startsWith(excludeKey))
+ return;
+ }
+ // Get the list of included sounds for the current texture
+ List include = ((MemorySection) c).getStringList("include");
+ for (String in : include) {
+ // Split the include string into namespace and key
+ String[] splitIn = in.split(":");
+ String namespace = NamespacedKey.MINECRAFT;
+ String includeKey = splitIn[0];
+ if (splitIn.length > 1) {
+ namespace = splitIn[0];
+ includeKey = splitIn[1];
+ }
+ // Add the sound to the textureToSounds map if it is in the include list
+ if (namespace.equals(soundKey.getNamespace()) && soundKey.getKey().startsWith(includeKey)) {
+ textureToSounds.computeIfAbsent(textureHash, k -> new ArrayList<>()).add(soundKey);
+ return;
+ }
+ }
+ });
+ }
+ }
+
+ @SuppressWarnings("deprecation") // Suppress warning for deprecated method getId()
+ @EventHandler
+ public void onPlayerInteract(PlayerInteractEvent event) {
+ // Get the block that was clicked
+ Block block = event.getClickedBlock();
+ // Check if the action was a right-click on a note block
+ if (event.getAction() != Action.RIGHT_CLICK_BLOCK || block.getType() != Material.NOTE_BLOCK) {
+ return;
+ }
+ // Get the data for the note block
+ NoteBlock blockdata = (NoteBlock) block.getBlockData();
+ // Check if the note block is associated with a custom head
+ if (blockdata.getInstrument() != Instrument.CUSTOM_HEAD) {
+ return;
+ }
+ // Get the block above the note block
+ Block usedHead = block.getRelative(BlockFace.UP);
+ // Check if the block above is a player head
+ if (usedHead.getType() != Material.PLAYER_HEAD) {
+ return;
+ }
+ // Get the skull data and texture hash for the player head
+ Skull skull = (Skull) usedHead.getState();
+ String[] textureUrl = skull.getOwnerProfile().getTextures().getSkin().toString().split("/");
+ String textureHash = textureUrl[textureUrl.length - 1];
+
+ // Get the possible sounds for the texture hash
+ ArrayList possibleSounds = textureToSounds.get(textureHash);
+ // Set the note block sound based on the note value
+ skull.setNoteBlockSound(possibleSounds.get(((blockdata.getNote().getId() + 1) % 25) % possibleSounds.size()));
+ // Update the skull without sending updates to clients or applying physics
+ skull.update(false, false);
+ }
+
+ @EventHandler
+ public void onBlockDropItem(BlockDropItemEvent event) {
+ // Iterate over the items dropped from the block
+ for (Item item : event.getItems()) {
+ // Check if the item is a player head
+ if (item.getItemStack().getType() != Material.PLAYER_HEAD)
+ continue;
+
+ // Get the metadata for the player head and its texture hash
+ SkullMeta metaData = (SkullMeta) item.getItemStack().getItemMeta();
+
+ // Extracts the texture hash from the player head's skin URL
+ String[] textureUrl = metaData.getOwnerProfile().getTextures().getSkin().toString().split("/");
+ String textureHash = textureUrl[textureUrl.length - 1];
+
+ // If the texture hash is in the textureToSounds map, remove the sound from the
+ // metadata
+ if (textureToSounds.containsKey(textureHash)) {
+ metaData.setNoteBlockSound(null);
+ item.getItemStack().setItemMeta(metaData);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
new file mode 100644
index 0000000..759e6d6
--- /dev/null
+++ b/src/main/resources/config.yml
@@ -0,0 +1,251 @@
+e50294a1747310f104124c6373cc639b712baa57b7d926297b645188b7bb9ab9:
+ include:
+ - entity.allay.
+8b91b13d0b33607a9587e8ba17d86035625cb3627c5dbef9cf00e8bae9f0f52a:
+ include:
+ - entity.axolotl.
+6681a72da7263ca9aef066542ecca7a180c40e328c0463fcb114cb3b83057552:
+ include:
+ - entity.bat.
+abcaf32c512cc878cf3920c1d8ea857ab90936485da8993768ab046f6334832e:
+ include:
+ - entity.cat.
+ca3582ce4889333dad329e4e24372a03a5daa2c34280c56256af5283edb043f8:
+ include:
+ - entity.chicken.
+7892d7dd6aadf35f86da27fb63da4edda211df96d2829f691462a4fb1cab0:
+ include:
+ - entity.cod.
+dd4ef7938dfdc87c989ca5d9231e23d1e368d21f8100f827316d70e541f4d315:
+ include:
+ - entity.cow.
+ca11ad10ab7d8c18603474f4ae3758325381b5c7000120f08eb5c5d37993ff9d:
+ include:
+ - entity.donkey.
+be49109db74884434580bdf32dd0cf3218478b1e2aee0fdc27197019b6bb6886:
+ include:
+ - entity.fox.
+672b9e663741fff07b0aaf514aebb70bb814f1688e79846823cb4f91470d561:
+ include:
+ - entity.frog.
+55e2b46e52ac92d419a2ddbcc9cdce7b451cb48ae739d85d607db0502a008ce0:
+ include:
+ - entity.glow_squid.
+29ac1eab3d6959394b4ef9c6d3f62eda65dc41ad18b816a783eba7074ec5bea0:
+ include:
+ - entity.horse.
+4c9f583094278541144409a89d11883fba27a37fba671fac350c4bb6aecf271b:
+ include:
+ - entity.mooshroom.
+46dcda265e57e4f51b145aacbf5b59bdc6099ffd3cce0a661b2c0065d80930d8:
+ include:
+ - entity.mule.
+8c433c1347313b23b67eec92f8807aed2566ec29fd416bdf7a59c22596628355:
+ include:
+ - entity.ocelot.
+a3c34722ac64496c9b84d0c54019daae6185d6094990133ad6810eea3d24067a:
+ include:
+ - entity.parrot.
+ exclude:
+ - entity.parrot.imitate.
+b6a0249a78a999037ff7806338bc0b3c8dbac6793dc312c376d7e9ddf46bc614:
+ include:
+ - entity.pig.
+292350c9f0993ed54db2c7113936325683ffc20104a9b622aa457d37e708d931:
+ include:
+ - entity.pufferfish.
+d27d5c0dd6ff514edb3aa392107702501d50bf90bc5e5822aecb1d86c2d4ba92:
+ include:
+ - entity.rabbit.
+8aeb21a25e46806ce8537fbd6668281cf176ceafe95af90e94a5fd84924878:
+ include:
+ - entity.salmon.
+30f50394c6d7dbc03ea59fdf504020dc5d6548f9d3bc9dcac896bb5ca08587a:
+ include:
+ - entity.sheep.
+47effce35132c86ff72bcae77dfbb1d22587e94df3cbc2570ed17cf8973a:
+ include:
+ - entity.skeleton_horse.
+1fdfd1f7538c040258be7a91446da89ed845cc5ef728eb5e690543378fcf4:
+ include:
+ - entity.snow_golem.
+464bdc6f600656511bef596c1a16aab1d3f5dbaae8bee19d5c04de0db21ce92c:
+ include:
+ - entity.squid.
+e245e4760abf10f2900626914cf42f80440cd53099ae5529534f59824067dad6:
+ include:
+ - entity.strider.
+987035f5352334c2cba6ac4c65c2b9059739d6d0e839c1dd98d75d2e77957847:
+ include:
+ - entity.tadpole.
+d6dd5e6addb56acbc694ea4ba5923b1b25688178feffa72290299e2505c97281:
+ include:
+ - entity.tropical_fish.
+0a4050e7aacc4539202658fdc339dd182d7e322f9fbcc4d5f99b5718a:
+ include:
+ - entity.turtle.
+126ec1ca185b47aad39f931db8b0a8500ded86a127a204886ed4b3783ad1775c:
+ include:
+ - entity.villager.
+5f1379a82290d7abe1efaabbc70710ff2ec02dd34ade386bc00c930c461cf932:
+ include:
+ - entity.wandering_trader.
+d710f9aa326c7205038392aeb12f45ce22cf6a1336b82129668bea1fc46d4285:
+ include:
+ - entity.bee.
+53d18dad0bd90f02ac08754a75358b1c27da579b3ca35b69e6bb10a7a5c2dbda:
+ include:
+ - entity.cave_spider.
+1415d2c543e34bb88ede94d79b9427691fc9be72daad8831a9ef297180546e18:
+ include:
+ - entity.dolphin.
+120baf2ed7f2326803165ad801fc056d002243be8ccf2d87ea26b9c76dc3fa6e:
+ include:
+ - entity.enderman.
+457a0d538fa08a7affe312903468861720f9fa34e86d44b89dcec5639265f03:
+ include:
+ - entity.goat.
+e13f34227283796bc017244cb46557d64bd562fa9dab0e12af5d23ad699cf697:
+ include:
+ - entity.iron_golem.
+de703ab031ed66622f12957ef59a8b5c8a269cebd18f9326248b68c3bbe20163:
+ include:
+ - entity.llama.
+ba6e3ad823f96d4a80a14556d8c9c7632163bbd2a876c0118b458925d87a5513:
+ include:
+ - entity.panda.
+9d24991435e4e7fb1a9ad23db75c80aec300d003ec0c5963e0ed658634027889:
+ include:
+ - entity.piglin.
+c4fe926922fbb406f343b34a10bb98992cee4410137d3f88099427b22de3ab90:
+ include:
+ - entity.polar_bear.
+a3ead81326ed5d5aa97b53b0f540b825b79cbf4855ce9b90fe73ea2311eb3a:
+ include:
+ - entity.spider.
+15ad6b69cc6b4769d3516a0ce98b99b2a5d406fea4912dec570ea4a4f2bcc0ff:
+ include:
+ - entity.trader_llama.
+19f6fb7b76adcfc38b0e7f877f019eaef008eb1d8f85429a6f39f565a1699f97:
+ include:
+ - entity.wolf.
+7eabaecc5fae5a8a49c8863ff4831aaa284198f1a2398890c765e0a8de18da8c:
+ include:
+ - entity.zombified_piglin.
+b20657e24b56e1b2f8fc219da1de788c0c24f36388b1a409d0cd2d8dba44aa3b:
+ include:
+ - entity.blaze.
+831ba39a16ca442cab935040ddc726edad9dd276ecfaf6fee9976768bb276bc0:
+ include:
+ - entity.creeper.
+c3f7ccf61dbc3f9fe9a6333cde0c0e14399eb2eea71d34cf223b3ace22051:
+ include:
+ - entity.drowned.
+4340a268f25fd5cc276ca147a8446b2630a55867a2349f7ca107c26eb58991:
+ include:
+ - entity.elder_guardian.
+5a1a0831aa03afb4212adcbb24e5dfaa7f476a1173fce259ef75a85855:
+ include:
+ - entity.endermite.
+e79f133a85fe00d3cf252a04d6f2eb2521fe299c08e0d8b7edbf962740a23909:
+ include:
+ - entity.evoker.
+de8a38e9afbd3da10d19b577c55c7bfd6b4f2e407e44d4017b23be9167abff02:
+ include:
+ - entity.ghast.
+a0bf34a71e7715b6ba52d5dd1bae5cb85f773dc9b0d457b4bfc5f9dd3cc7c94:
+ include:
+ - entity.guardian.
+9bb9bc0f01dbd762a08d9e77c08069ed7c95364aa30ca1072208561b730e8d75:
+ include:
+ - entity.hoglin.
+d48a5a5e4df90528dba35e0667cdc0a7ddc025740a2b19bf355a68ab899a2fe7:
+ include:
+ - entity.husk.
+a1c97a06efde04d00287bf20416404ab2103e10f08623087e1b0c1264a1c0f0c:
+ include:
+ - entity.magma_cube.
+adfe51801761660ebf6dae70e9cad588b2ef5e6cb2b3194d028a40ac0eebcdf5:
+ include:
+ - entity.phantom.
+3e300e9027349c4907497438bac29e3a4c87a848c50b34c21242727b57f4e1cf:
+ include:
+ - entity.piglin_brute.
+32fb80a6b6833e31d9ce8313a54777645f9c1e55b810918a706e7bcc8d35a5a2:
+ include:
+ - entity.pillager.
+5c73e16fa2926899cf18434360e2144f84ef1eb981f996148912148dd87e0b2a:
+ include:
+ - entity.ravager.
+537a294f6b7b4ba437e5cb35fb20f46792e7ac0a490a66132a557124ec5f997a:
+ include:
+ - entity.shulker.
+da91dab8391af5fda54acd2c0b18fbd819b865e1a8f1d623813fa761e924540:
+ include:
+ - entity.silverfish.
+c4070b639225b2d4f2a9f794f5acc48cb696eec49d72ebd54817f8bb52d59f34:
+ include:
+ - entity.skeleton.
+bb13133a8fb4ef00b71ef9bab639a66fbc7d5cffcc190c1df74bf2161dfd3ec7:
+ include:
+ - entity.slime.
+78ddf76e555dd5c4aa8a0a5fc584520cd63d489c253de969f7f22f85a9a2d56:
+ include:
+ - entity.stray.
+5e7330c7d5cd8a0a55ab9e95321535ac7ae30fe837c37ea9e53bea7ba2de86b:
+ include:
+ - entity.vex.
+6deaec344ab095b48cead7527f7dee61b063ff791f76a8fa76642c8676e2173:
+ include:
+ - entity.vindicator.
+cf6481c7c435c34f21dff1043a4c7034c445a383a5435fa1f2a503a348afd62f:
+ include:
+ - entity.warden.
+7e71a6eb303ab7e6f70ed54df9146a80eadf396417cee9495773ffbebfad887c:
+ include:
+ - entity.witch.
+f5ec964645a8efac76be2f160d7c9956362f32b6517390c59c3085034f050cff:
+ include:
+ - entity.wither_skeleton.
+3c8c7c5d0556cd6629716e39188b21e7c0477479f242587bf19e0bc76b322551:
+ include:
+ - entity.zoglin.
+ad5c16262e13fa8f277620b496316d5b1ea709eeb9a324b1c3cfd5cb1f06367e:
+ include:
+ - entity.herobrine.
+64528b3229660f3dfab42414f59ee8fd01e80081dd3df30869536ba9b414e089:
+ include:
+ - entity.zombie.
+fb552c90f212e855d12255d5cd62ed38b9cd7e30e73f0ea779d1764330e69264:
+ include:
+ - entity.zombie_villager.
+ffcdae586b52403b92b1857ee4331bac636af08bab92ba5750a54a83331a6353:
+ include:
+ - entity.ender_dragon.
+b95d875140b99235ec5e4486242a70da881a7c183b650ceafae0084bceb66182:
+ include:
+ - entity.wither.
+64528b3229660f3dfab42414f59ee8fd01e80081dd3df30869536ba9b414e089:
+ include:
+ - entity.giant.
+171ce469cba4426c811f69be5d958a09bfb9b1b2bb649d3577a0c2161ad2f524:
+ include:
+ - entity.zombie_horse.
+4639d325f4494258a473a93a3b47f34a0c51b3fceaf59fee87205a5e7ff31f68:
+ include:
+ - entity.illusioner.
+ba4c95bfa0b61722255389141b505cf1a38bad9b0ef543de619f0cc9221ed974:
+ include:
+ - entity.camel.
+3d6c9f43510cb90d24493e07b7cf8ca9f54132d09a257f20b7048022e3b1b707:
+ include:
+ - entity.sniffer.
+a3b9003ba2d05562c75119b8a62185c67130e9282f7acbac4bc2824c21eb95d9:
+ include:
+ - entity.bogged.
+a275728af7e6a29c88125b675a39d88ae9919bb61fdc200337fed6ab0c49d65c:
+ include:
+ - entity.breeze.
+9852b33ba294f560090752d113fe728cbc7dd042029a38d5382d65a2146068b7:
+ include:
+ - entity.armadillo.
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
new file mode 100644
index 0000000..f10e8b1
--- /dev/null
+++ b/src/main/resources/plugin.yml
@@ -0,0 +1,5 @@
+main: de.thojo0.moreheadsounds.App
+name: MoreHeadSounds
+version: 1.0
+authors: [thojo0, PYZ]
+description: Allows the use of player heads for minecraft sounds