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

add /skin skull command #1068

Draft
wants to merge 21 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions api/src/main/java/net/skinsrestorer/api/SkullSource.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* SkinsRestorer
*
* Copyright (C) 2022 SkinsRestorer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
*/
package net.skinsrestorer.api;
/**
* Data source that can be used for skulls
* <p>
* {@link #MOJANGPLAYER}
* {@link #PLAYER}
* {@link #SKIN}
* {@link #SKINURL}
* {@link #TEXTUREVALUE}
*/
public enum SkullSource {
/**
* The username of a premium (mojang registred) player
*/
MOJANGPLAYER,
/**
* An in game player that can have a custom skin
*/
PLAYER,
/**
* The name of a skin in the SkinsRestorer database
*/
SKIN,
/**
* A url to a skin image (png)
*/
SKINURL,
/**
* Base64 encoded texture value (without signature)
*/
TEXTUREVALUE

}
18 changes: 14 additions & 4 deletions api/src/main/java/net/skinsrestorer/api/bukkit/BukkitHeadAPI.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
import net.skinsrestorer.api.reflection.exception.FieldNotFoundException;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.SkullMeta;
import org.bukkit.profile.PlayerProfile;
import org.jetbrains.annotations.Nullable;

import java.util.Objects;
import java.util.UUID;
Expand All @@ -35,10 +38,6 @@ public class BukkitHeadAPI {
private BukkitHeadAPI() {
}

public static void setSkull(ItemStack head, IProperty property) {
setSkull(head, property.getValue());
}

@SuppressWarnings("unchecked")
public static void setSkull(ItemStack head, String b64stringTexture) {
GameProfile profile = new GameProfile(UUID.randomUUID(), null);
Expand All @@ -61,4 +60,15 @@ public static void setSkull(ItemStack head, String b64stringTexture) {

head.setItemMeta(headMeta);
}

@Nullable
public static PropertyMap getSkullProperty (ItemStack head) {
try {
SkullMeta skull = (SkullMeta) head.getItemMeta();
GameProfile profile = (GameProfile) skull.getOwnerProfile();
return profile.getProperties();
} catch (Exception ignored) {
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,19 @@
public interface IProperty {
String TEXTURES_NAME = "textures";

/**
* @return The name of the skin (not skin / texture owner).
*/
String getName();

/**
* @return The b64stringTexture value of the property.
*/
String getValue();

/**
* @return The signature of the property which is needed when applying the skin .
*/
String getSignature();

default Object getHandle() {
Expand Down
110 changes: 110 additions & 0 deletions bukkit/src/main/java/net/skinsrestorer/bukkit/SkinSkull.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* SkinsRestorer
*
* Copyright (C) 2022 SkinsRestorer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
*/
package net.skinsrestorer.bukkit;

import com.cryptomorin.xseries.XMaterial;
import lombok.RequiredArgsConstructor;
import net.skinsrestorer.api.bukkit.BukkitHeadAPI;
import net.skinsrestorer.shared.utils.C;
import net.skinsrestorer.shared.utils.log.SRLogger;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.SkullMeta;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;

@RequiredArgsConstructor
public class SkinSkull extends ItemStack {
private final SkinsRestorer plugin;
private final SRLogger log;

public static boolean giveSkull(SkinsRestorer plugin, Player targetPlayer, @Nullable String lore, @Nullable OfflinePlayer skullOwner, @Nullable String b64stringTexture) {
try {
ItemStack skull = createSkull(plugin, lore, skullOwner, b64stringTexture);
HashMap<Integer, ItemStack> fullInventory = targetPlayer.getInventory().addItem(skull);
if (fullInventory.isEmpty()) {
targetPlayer.sendMessage("Skull given"); //todo: add to lang
} else {
targetPlayer.sendMessage("Inventory is full, skull could not be given"); //todo: add to lang
return true;
}
} catch (Exception e) {
plugin.getSrLogger().warning("Error while giving skull to " + targetPlayer.getName() + ": " + e.getMessage());
}
return false;
}

public static boolean updateSkull(SkinsRestorer plugin, Player targetPlayer, String lore, @Nullable OfflinePlayer SkullOwner, @Nullable String b64stringTexture) {
try {
ItemStack skull = targetPlayer.getInventory().getItemInMainHand();
if (skull.getType() != XMaterial.PLAYER_HEAD.parseMaterial()) {
targetPlayer.sendMessage("You must be holding a skull in your main hand"); //todo: add to lang
return false;
}

SkullMeta sm = (SkullMeta) skull.getItemMeta();
sm.setOwningPlayer(SkullOwner);
skull.setItemMeta(sm);

targetPlayer.getInventory().setItemInMainHand(skull);
return true;
} catch (Exception e) {
plugin.getSrLogger().warning("Error while updating skull of " + targetPlayer.getName() + ": " + e.getMessage());
}
return false;
}

private static ItemStack createSkull(SkinsRestorer plugin, String lore, @Nullable OfflinePlayer skullOwner, @Nullable String b64stringTexture) {
if (skullOwner == null && b64stringTexture == null) {
return null;
}

ItemStack is = XMaterial.PLAYER_HEAD.parseItem();
SkullMeta sm = (SkullMeta) Objects.requireNonNull(is).getItemMeta();

// Set skull owner if player is premium
if (skullOwner != null && sm != null) {
sm.setOwningPlayer(skullOwner);
}

if (skullOwner != null && lore != null) {
List<String> itemLore = new ArrayList<>();
itemLore.add(C.c(" " + lore + " Head")); // todo make customizable locale
sm.setLore(itemLore);

is.setItemMeta(sm);
}

if (b64stringTexture != null) {
try {
BukkitHeadAPI.setSkull(is, b64stringTexture);
} catch (Exception e) {
plugin.getSrLogger().warning("ERROR: could not add skin data to skull, skin might be corrupted or invalid!");
e.printStackTrace();
}
}
return is;
}
}
15 changes: 14 additions & 1 deletion bukkit/src/main/java/net/skinsrestorer/bukkit/SkinsRestorer.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import net.skinsrestorer.api.serverinfo.ServerVersion;
import net.skinsrestorer.bukkit.commands.GUICommand;
import net.skinsrestorer.bukkit.commands.SkinCommand;
import net.skinsrestorer.bukkit.commands.SkullCommand;
import net.skinsrestorer.bukkit.commands.SrCommand;
import net.skinsrestorer.bukkit.listener.InventoryListener;
import net.skinsrestorer.bukkit.listener.PlayerJoin;
Expand Down Expand Up @@ -61,6 +62,7 @@
import org.bstats.charts.SingleLineChart;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.OfflinePlayer;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
Expand Down Expand Up @@ -308,6 +310,16 @@ public void pluginStartup() throws InitializeException {
Inventory inventory = SkinsGUI.createGUI(this, wrapPlayer(player), page, skinList);

Bukkit.getScheduler().scheduleSyncDelayedTask(this, () -> player.openInventory(inventory));
} else if (subChannel.equalsIgnoreCase("GiveSkull")) {
Player targetPlayer = Bukkit.getPlayer(in.readUTF());
if (targetPlayer == null)
return;

String lore = in.readUTF();
OfflinePlayer skullOwner = Bukkit.getOfflinePlayer(in.readUTF()); // todo fix depricated
String b64stringTexture = in.readUTF();

SkinSkull.giveSkull(this, targetPlayer, lore, skullOwner, b64stringTexture);
}
} catch (Exception e) {
e.printStackTrace();
Expand Down Expand Up @@ -413,9 +425,10 @@ private void initCommands() {

runRepeat(cooldownStorage::cleanup, 60, 60, TimeUnit.SECONDS);

manager.registerCommand(skinCommand);
manager.registerCommand(skinCommand); // fixme
manager.registerCommand(new SrCommand(this));
manager.registerCommand(new GUICommand(this));
manager.registerCommand(new SkullCommand(this, new SkinSkull(this, srLogger)));
}

private void checkProxyMode() {
Expand Down
Loading