Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Item Skull Owner #7174

Open
wants to merge 12 commits into
base: dev/feature
Choose a base branch
from
92 changes: 66 additions & 26 deletions src/main/java/ch/njol/skript/expressions/ExprSkullOwner.java
Original file line number Diff line number Diff line change
@@ -1,45 +1,55 @@
package ch.njol.skript.expressions;

import ch.njol.skript.aliases.ItemType;
import ch.njol.skript.bukkitutil.ItemUtils;
import ch.njol.skript.classes.Changer.ChangeMode;
import ch.njol.skript.doc.Description;
import ch.njol.skript.doc.Examples;
import ch.njol.skript.doc.Name;
import ch.njol.skript.doc.Since;
import ch.njol.skript.expressions.base.SimplePropertyExpression;
import ch.njol.skript.util.slot.Slot;
import ch.njol.util.coll.CollectionUtils;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.Skull;
import org.bukkit.event.Event;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.SkullMeta;
import org.bukkit.profile.PlayerProfile;
import org.jetbrains.annotations.Nullable;

import java.util.function.Consumer;

@Name("Skull Owner")
@Description("The skull owner of a player skull.")
@Examples({
"set {_owner} to the skull owner of event-block",
"set skull owner of {_block} to \"Njol\" parsed as offlineplayer"
"set skull owner of {_block} to \"Njol\" parsed as offlineplayer",
"set head owner of player's tool to {_player}"
})
@Since("2.9.0")
public class ExprSkullOwner extends SimplePropertyExpression<Block, OfflinePlayer> {
@Since("2.9.0, INSERT VERSION (of items)")
public class ExprSkullOwner extends SimplePropertyExpression<Object, OfflinePlayer> {

static {
register(ExprSkullOwner.class, OfflinePlayer.class, "(head|skull) owner", "blocks");
register(ExprSkullOwner.class, OfflinePlayer.class, "(head|skull) owner", "slots/itemtypes/itemstacks/blocks");
}

@Override
public @Nullable OfflinePlayer convert(Block block) {
BlockState state = block.getState();
if (!(state instanceof Skull))
return null;
return ((Skull) state).getOwningPlayer();
public @Nullable OfflinePlayer convert(Object object) {
if (object instanceof Block block && block.getState() instanceof Skull skull) {
return skull.getOwningPlayer();
} else {
ItemStack skullItem = ItemUtils.asItemStack(object);
if (skullItem == null || !(skullItem.getItemMeta() instanceof SkullMeta skullMeta))
return null;
return skullMeta.getOwningPlayer();
}
}

@Override
@Nullable
public Class<?>[] acceptChange(ChangeMode mode) {
public Class<?> @Nullable [] acceptChange(ChangeMode mode) {
if (mode == ChangeMode.SET)
return CollectionUtils.array(OfflinePlayer.class);
return null;
Expand All @@ -48,25 +58,55 @@ public Class<?>[] acceptChange(ChangeMode mode) {
@Override
public void change(Event event, Object @Nullable [] delta, ChangeMode mode) {
OfflinePlayer offlinePlayer = (OfflinePlayer) delta[0];
for (Block block : getExpr().getArray(event)) {
BlockState state = block.getState();
if (!(state instanceof Skull))
continue;

Skull skull = (Skull) state;
if (offlinePlayer.getName() != null) {
skull.setOwningPlayer(offlinePlayer);
} else if (ItemUtils.CAN_CREATE_PLAYER_PROFILE) {
//noinspection deprecation
skull.setOwnerProfile(Bukkit.createPlayerProfile(offlinePlayer.getUniqueId(), ""));
Consumer<Skull> blockChanger = getBlockChanger(offlinePlayer);
Consumer<SkullMeta> metaChanger = getMetaChanger(offlinePlayer);
for (Object object : getExpr().getArray(event)) {
if (object instanceof Block block && block.getState() instanceof Skull skull) {
blockChanger.accept(skull);
skull.update(true, false);
} else {
//noinspection deprecation
skull.setOwner("");
ItemStack skullItem = ItemUtils.asItemStack(object);
if (skullItem == null || !(skullItem.getItemMeta() instanceof SkullMeta skullMeta))
continue;
metaChanger.accept(skullMeta);
if (object instanceof Slot slot) {
skullItem.setItemMeta(skullMeta);
slot.setItem(skullItem);
} else if (object instanceof ItemType itemType) {
itemType.setItemMeta(skullMeta);
} else if (object instanceof ItemStack itemStack) {
itemStack.setItemMeta(skullMeta);
}
}
skull.update(true, false);
}
}

private Consumer<Skull> getBlockChanger(OfflinePlayer offlinePlayer) {
if (offlinePlayer.getName() != null) {
return skull -> skull.setOwningPlayer(offlinePlayer);
} else if (ItemUtils.CAN_CREATE_PLAYER_PROFILE) {
//noinspection deprecation
PlayerProfile profile = Bukkit.createPlayerProfile(offlinePlayer.getUniqueId(), "");
//noinspection deprecation
return skull -> skull.setOwnerProfile(profile);
}
//noinspection deprecation
return skull -> skull.setOwner("");
}

private Consumer<SkullMeta> getMetaChanger(OfflinePlayer offlinePlayer) {
if (offlinePlayer.getName() != null) {
return skullMeta -> skullMeta.setOwningPlayer(offlinePlayer);
} else if (ItemUtils.CAN_CREATE_PLAYER_PROFILE) {
//noinspection deprecation
PlayerProfile profile = Bukkit.createPlayerProfile(offlinePlayer.getUniqueId(), "");
//noinspection deprecation
return skullMeta -> skullMeta.setOwnerProfile(profile);
}
//noinspection deprecation
return skullMeta -> skullMeta.setOwner("");
}

@Override
public Class<? extends OfflinePlayer> getReturnType() {
return OfflinePlayer.class;
Expand Down
16 changes: 16 additions & 0 deletions src/test/skript/tests/syntaxes/expressions/ExprSkullOwner.sk
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
test "skull owner - block":
set {_loc} to test-location
set {_old} to block at {_loc}
set block at {_loc} to player head
assert skull owner of (block at {_loc}) is not set with "Block Skull Owner should not be set"
set {_player} to "Sovde" parsed as offline player
set skull owner of (block at {_loc}) to {_player}
assert skull owner of (block at {_loc}) is {_player} with "Block Skull Owner did not change"
set block at {_loc} to {_old}

test "skull owner - item":
set {_skull} to a player head
assert skull owner of {_skull} is not set with "Item Skull Owner should not be set"
set {_player} to "Sovde" parsed as offline player
set skull owner of {_skull} to {_player}
assert skull owner of {_skull} is {_player} with "Item Skull Owner did not change"
Loading