-
-
Notifications
You must be signed in to change notification settings - Fork 79
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
91 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,60 +1,122 @@ | ||
## Set a skull's skin | ||
|
||
// TODO broken link | ||
|
||
#### We will be using [this head](https://minecraft-heads.com/custom-heads/food%20&%20drinks/28194-cup-of-soda) as example. | ||
#### We will be using [this head](https://minecraft-heads.com/custom-heads/head/28194-cup-of-soda) as example. | ||
|
||
```java | ||
// This is the base64 texture value from the bottom of the previously mentioned website. | ||
final String textureValue = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTQyY2M5MjAzYzkwYjg5YmRhYzFkZjI4NDE2NzI2NmI5NTNkZmViZjNjNDY5MGE3Y2QwYjE1NzkxYTYyZTU4MiJ9fX0="; | ||
|
||
|
||
// Creating ItemStack | ||
|
||
// For Minecraft 1.12 and below | ||
// For Minecraft 1.12.2 and below | ||
final ItemStack item = new ItemStack(Material.SKULL_ITEM); | ||
item.setDurability((short) 3); | ||
|
||
// For Minecraft 1.13 and newer | ||
final ItemStack item = new ItemStack(Material.PLAYER_HEAD); | ||
|
||
|
||
// Applying nbt | ||
|
||
// For Minecraft 1.20.4 and below | ||
NBT.modify(item, nbt -> { | ||
final ReadWriteNBT skullOwnerCompound = nbt.getOrCreateCompound("SkullOwner"); | ||
ReadWriteNBT skullOwnerCompound = nbt.getOrCreateCompound("SkullOwner"); | ||
|
||
// The owner UUID. Note that skulls with the same UUID but different textures will misbehave and only one texture will load. | ||
// They will share the texture. To avoid this limitation, it is recommended to use a random UUID. | ||
skullOwnerCompound.setUUID("Id", UUID.randomUUID()); | ||
|
||
// The owner UUID. Note that skulls with the same UUID but different textures will misbehave and only one texture will load. | ||
// They will share the texture. To avoid this limitation, it is recommended to use a random UUID. | ||
skullOwnerCompound.setUUID("Id", UUID.randomUUID()); | ||
skullOwnerCompound.getOrCreateCompound("Properties") | ||
.getCompoundList("textures") | ||
.addCompound() | ||
.setString("Value", textureValue); | ||
}); | ||
|
||
skullOwnerCompound.getOrCreateCompound("Properties") | ||
.getCompoundList("textures") | ||
.addCompound() | ||
.setString("Value", textureValue); | ||
// Workaround for Minecraft 1.20.5+ | ||
NBT.modifyComponents(item, nbt -> { | ||
ReadWriteNBT profileNbt = nbt.getOrCreateCompound("minecraft:profile"); | ||
profileNbt.setUUID("id", uuid); | ||
ReadWriteNBT propertiesNbt = profileNbt.getCompoundList("properties").addCompound(); | ||
propertiesNbt.setString("name", "textures"); | ||
propertiesNbt.setString("value", textureValue); | ||
}); | ||
``` | ||
|
||
> [!TIP] | ||
> If you are using Paper API on 1.12.2+, you may use the following code to create textured skulls | ||
// TODO 1.20.5+ example | ||
// TODO A note/example about alternative in Paper API? | ||
```java | ||
SkullMeta meta = (SkullMeta) item.getItemMeta(); | ||
PlayerProfile playerProfile = Bukkit.createProfile(uuid); | ||
playerProfile.setProperty(new ProfileProperty("textures", textureValue)); | ||
meta.setPlayerProfile(playerProfile); | ||
// You can also use item.editMeta(SkullMeta.class, meta -> {}); on 1.17+ | ||
item.setItemMeta(meta); | ||
``` | ||
|
||
## Zombie that can pick up loot and does 0.5 hearts of damage | ||
|
||
This code should serve only as a reference, the nbt structure might change between versions. | ||
|
||
```java | ||
Zombie zombie = (Zombie) world.spawnEntity(location, EntityType.ZOMBIE); | ||
Zombie zombie = location.getWorld().spawn(location, Zombie.class); | ||
|
||
String attributeName = "minecraft:generic.attack_damage"; // Or generic.attackDamage prior to 1.16 | ||
double damageValue = 0.5; | ||
|
||
// Modify vanilla data | ||
NBT.modify(zombie, nbt -> { | ||
nbt.setByte("CanPickUpLoot", (byte) 1); | ||
nbt.setBoolean("CanPickUpLoot", true); | ||
|
||
ReadWriteNBTCompoundList list = nbt.getCompoundList("Attributes"); | ||
for(int i = 0; i < list.size(); i++){ | ||
ReadWriteNBT lc = list.get(i); | ||
if(lc.getString("Name").equals("generic.attackDamage")){ | ||
lc.setDouble("Base", 0.5d); | ||
} | ||
|
||
// Check if zombie already has attribute set. If so, modify it | ||
for (ReadWriteNBT listEntryNbt : list) { | ||
if (!listEntryNbt.getString("Name").equals(attributeName)) continue; | ||
|
||
listEntryNbt.setDouble("Base", damageValue); | ||
|
||
return; | ||
} | ||
|
||
// Attribute is missing, add it instead | ||
ReadWriteNBT listEntryNbt = list.addCompound(); | ||
listEntryNbt.setString("Name", attributeName); | ||
listEntryNbt.setDouble("Base", damageValue); | ||
}); | ||
|
||
// TODO is this valid in newer versions? | ||
// Modify custom data | ||
NBT.modifyPersistentData(zombie, nbt -> { | ||
// Let's mark our zombie as a custom one | ||
nbt.setBoolean("custom_zombie", true); | ||
}); | ||
``` | ||
|
||
## Reading world data | ||
|
||
```java | ||
// TODO | ||
// Get main world's folder | ||
File worldDataFolder = Bukkit.getWorlds().getFirst().getWorldFolder(); | ||
|
||
// Read level data | ||
NBTFile levelNbtFile = new NBTFile(new File(worldDataFolder, "level.dat")); | ||
|
||
// Obtain world name | ||
String worldName = levelNbtFile.resolveOrNull("Data.LevelName", String.class); | ||
|
||
// Read some player's data | ||
UUID playerUuid; | ||
File playerFile = new File(worldDataFolder, "playerdata/" + playerUuid + ".dat"); | ||
if (!playerFile.exists()) { | ||
// No offline player data for provided uuid | ||
return; | ||
} | ||
|
||
NBTFile playerNbtFile = new NBTFile(playerFile); | ||
|
||
// Change player's health | ||
float health = playerNbtFile.getFloat("Health"); | ||
playerNbtFile.setFloat("Health", health + 5); | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters