Files
ToolStats/src/main/java/lol/hyper/toolstats/tools/TokenData.java
hyperdefined 6a994e4a82 move keys to own class
this took forever
2026-01-20 17:39:08 -05:00

258 lines
12 KiB
Java

/*
* This file is part of ToolStats.
*
* ToolStats 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.
*
* ToolStats 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 ToolStats. If not, see <https://www.gnu.org/licenses/>.
*/
package lol.hyper.toolstats.tools;
import io.papermc.paper.datacomponent.DataComponentTypes;
import io.papermc.paper.datacomponent.item.CustomModelData;
import lol.hyper.toolstats.ToolStats;
import net.kyori.adventure.text.Component;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.ShapedRecipe;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import java.util.*;
public class TokenData {
private final ToolStats toolStats;
private final Set<ShapedRecipe> recipes = new HashSet<>();
private final ArrayList<String> tokenTypes = new ArrayList<>();
public TokenData(ToolStats toolStats) {
this.toolStats = toolStats;
}
public void setup() {
NamespacedKey playerKillsKey = new NamespacedKey(toolStats, "player-kills-token");
ShapedRecipe playerKillRecipe = new ShapedRecipe(playerKillsKey, createToken("player-kills"));
playerKillRecipe.shape(" P ", "PSP", " P ");
playerKillRecipe.setIngredient('P', Material.PAPER);
playerKillRecipe.setIngredient('S', Material.WOODEN_SWORD);
recipes.add(playerKillRecipe);
NamespacedKey mobKillsKey = new NamespacedKey(toolStats, "mob-kills-token");
ShapedRecipe mobKillsRecipe = new ShapedRecipe(mobKillsKey, createToken("mob-kills"));
mobKillsRecipe.shape(" P ", "PRP", " P ");
mobKillsRecipe.setIngredient('P', Material.PAPER);
mobKillsRecipe.setIngredient('R', Material.ROTTEN_FLESH);
recipes.add(mobKillsRecipe);
NamespacedKey blocksMinedKey = new NamespacedKey(toolStats, "blocks-mined-token");
ShapedRecipe blocksMinedRecipe = new ShapedRecipe(blocksMinedKey, createToken("blocks-mined"));
blocksMinedRecipe.shape(" P ", "PSP", " P ");
blocksMinedRecipe.setIngredient('P', Material.PAPER);
blocksMinedRecipe.setIngredient('S', Material.WOODEN_PICKAXE);
recipes.add(blocksMinedRecipe);
NamespacedKey cropsMinedKey = new NamespacedKey(toolStats, "crops-mined-token");
ShapedRecipe cropsMinedRecipe = new ShapedRecipe(cropsMinedKey, createToken("crops-mined"));
cropsMinedRecipe.shape(" P ", "PHP", " P ");
cropsMinedRecipe.setIngredient('P', Material.PAPER);
cropsMinedRecipe.setIngredient('H', Material.WOODEN_HOE);
recipes.add(cropsMinedRecipe);
NamespacedKey fishCaughtKey = new NamespacedKey(toolStats, "fish-caught-token");
ShapedRecipe fishCaughtRecipe = new ShapedRecipe(fishCaughtKey, createToken("fish-caught"));
fishCaughtRecipe.shape(" P ", "PCP", " P ");
fishCaughtRecipe.setIngredient('P', Material.PAPER);
fishCaughtRecipe.setIngredient('C', Material.COD);
recipes.add(fishCaughtRecipe);
NamespacedKey sheepShearedKey = new NamespacedKey(toolStats, "sheep-sheared-token");
ShapedRecipe sheepShearedRecipe = new ShapedRecipe(sheepShearedKey, createToken("sheep-sheared"));
sheepShearedRecipe.shape(" P ", "PWP", " P ");
sheepShearedRecipe.setIngredient('P', Material.PAPER);
sheepShearedRecipe.setIngredient('W', Material.WHITE_WOOL);
recipes.add(sheepShearedRecipe);
NamespacedKey armorDamageKey = new NamespacedKey(toolStats, "damage-taken-token");
ShapedRecipe armorDamageRecipe = new ShapedRecipe(armorDamageKey, createToken("damage-taken"));
armorDamageRecipe.shape(" P ", "PCP", " P ");
armorDamageRecipe.setIngredient('P', Material.PAPER);
armorDamageRecipe.setIngredient('C', Material.LEATHER_CHESTPLATE);
recipes.add(armorDamageRecipe);
NamespacedKey damageDoneKey = new NamespacedKey(toolStats, "damage-done-token");
ShapedRecipe damageDoneRecipe = new ShapedRecipe(damageDoneKey, createToken("damage-done"));
damageDoneRecipe.shape(" P ", "PSP", " P ");
damageDoneRecipe.setIngredient('P', Material.PAPER);
damageDoneRecipe.setIngredient('S', Material.SHIELD);
recipes.add(damageDoneRecipe);
NamespacedKey arrowsShotKey = new NamespacedKey(toolStats, "arrows-shot-token");
ShapedRecipe arrowsShotRecipe = new ShapedRecipe(arrowsShotKey, createToken("arrows-shot"));
arrowsShotRecipe.shape(" P ", "PAP", " P ");
arrowsShotRecipe.setIngredient('P', Material.PAPER);
arrowsShotRecipe.setIngredient('A', Material.ARROW);
recipes.add(arrowsShotRecipe);
NamespacedKey flightTimeKey = new NamespacedKey(toolStats, "flight-time-token");
ShapedRecipe flightTimeRecipe = new ShapedRecipe(flightTimeKey, createToken("flight-time"));
flightTimeRecipe.shape(" P ", "PFP", " P ");
flightTimeRecipe.setIngredient('P', Material.PAPER);
flightTimeRecipe.setIngredient('F', Material.FEATHER);
recipes.add(flightTimeRecipe);
NamespacedKey resetKey = new NamespacedKey(toolStats, "reset-token");
ShapedRecipe resetRecipe = new ShapedRecipe(resetKey, createToken("reset"));
resetRecipe.shape(" P ", "PPP", " P ");
resetRecipe.setIngredient('P', Material.PAPER);
recipes.add(resetRecipe);
NamespacedKey removeKey = new NamespacedKey(toolStats, "remove-token");
ShapedRecipe removeRecipe = new ShapedRecipe(removeKey, createToken("remove"));
removeRecipe.shape(" P ", "P P", " P ");
removeRecipe.setIngredient('P', Material.PAPER);
recipes.add(removeRecipe);
NamespacedKey witherKillsKey = new NamespacedKey(toolStats, "wither-kills-token");
ShapedRecipe witherKillsRecipe = new ShapedRecipe(witherKillsKey, createToken("wither-kills"));
witherKillsRecipe.shape(" P ", "PWP", " P ");
witherKillsRecipe.setIngredient('P', Material.PAPER);
witherKillsRecipe.setIngredient('W', Material.WITHER_ROSE);
recipes.add(witherKillsRecipe);
NamespacedKey enderDragonKillsKey = new NamespacedKey(toolStats, "enderdragon-kills-token");
ShapedRecipe enderDragonKillsRecipe = new ShapedRecipe(enderDragonKillsKey, createToken("enderdragon-kills"));
enderDragonKillsRecipe.shape(" P ", "PEP", " P ");
enderDragonKillsRecipe.setIngredient('P', Material.PAPER);
enderDragonKillsRecipe.setIngredient('E', Material.ENDER_PEARL);
recipes.add(enderDragonKillsRecipe);
NamespacedKey criticalStrikesKey = new NamespacedKey(toolStats, "critical-strikes-token");
ShapedRecipe criticalStrikesRecipe = new ShapedRecipe(criticalStrikesKey, createToken("critical-strikes"));
criticalStrikesRecipe.shape(" P ", "PSP", " P ");
criticalStrikesRecipe.setIngredient('P', Material.PAPER);
criticalStrikesRecipe.setIngredient('S', Material.GOLDEN_SWORD);
recipes.add(criticalStrikesRecipe);
NamespacedKey tridentThrowsKey = new NamespacedKey(toolStats, "trident-throws-token");
ShapedRecipe tridentThrowsRecipe = new ShapedRecipe(tridentThrowsKey, createToken("trident-throws"));
tridentThrowsRecipe.shape(" P ", "PSP", " P ");
tridentThrowsRecipe.setIngredient('P', Material.PAPER);
tridentThrowsRecipe.setIngredient('S', Material.PRISMARINE_SHARD);
recipes.add(tridentThrowsRecipe);
tokenTypes.add("crops-mined");
tokenTypes.add("blocks-mined");
tokenTypes.add("damage-taken");
tokenTypes.add("damage-done");
tokenTypes.add("mob-kills");
tokenTypes.add("player-kills");
tokenTypes.add("arrows-shot");
tokenTypes.add("sheep-sheared");
tokenTypes.add("flight-time");
tokenTypes.add("fish-caught");
tokenTypes.add("reset");
tokenTypes.add("remove");
tokenTypes.add("wither-kills");
tokenTypes.add("enderdragon-kills");
tokenTypes.add("critical-strikes");
tokenTypes.add("trident-throws");
}
public Set<ShapedRecipe> getRecipes() {
return recipes;
}
public ArrayList<String> getTokenTypes() {
return tokenTypes;
}
public ItemStack createToken(String tokenType) {
// we don't have to check if the token exists
// we do that prior
ConfigurationSection tokenConfig = toolStats.config.getConfigurationSection("tokens.data." + tokenType);
String materialFromConfig = tokenConfig.getString("material");
if (materialFromConfig == null) {
toolStats.logger.warn("Could not find material config for token {}", tokenType);
toolStats.logger.warn("Using PAPER as default.");
materialFromConfig = "PAPER";
}
Material material = Material.getMaterial(materialFromConfig);
if (material == null) {
toolStats.logger.warn("Material {} is not a valid Minecraft material.", materialFromConfig);
toolStats.logger.warn("Using PAPER as default.");
material = Material.PAPER;
}
ItemStack token = new ItemStack(material);
ItemMeta tokenMeta = token.getItemMeta();
PersistentDataContainer tokenData = tokenMeta.getPersistentDataContainer();
// set the title and lore
String titleFromConfig = toolStats.config.getString("tokens.data." + tokenType + ".title");
Component title = toolStats.textUtils.format(titleFromConfig);
List<Component> lore = toolStats.configTools.getTokenLore(tokenType);
tokenMeta.displayName(title);
tokenMeta.lore(lore);
// set the PDC
tokenData.set(toolStats.toolStatsKeys.getTokenType(), PersistentDataType.STRING, tokenType);
token.setItemMeta(tokenMeta);
// set the custom model data
if (tokenConfig.getBoolean("custom-model-data.enabled")) {
String type = tokenConfig.getString("custom-model-data.type");
Object value = tokenConfig.get("custom-model-data.value");
if (type == null || value == null) {
toolStats.logger.info("Could not find custom model data for token {}", tokenType);
toolStats.logger.info("Type: {}", type);
toolStats.logger.info("Value: {}", value);
return null;
}
CustomModelData data = setData(type, value);
if (data != null) {
token.setData(DataComponentTypes.CUSTOM_MODEL_DATA, data);
} else {
return null;
}
}
return token;
}
private CustomModelData setData(String type, Object data) {
switch (type.toLowerCase(Locale.ROOT)) {
case "float": {
float f;
try {
f = Float.parseFloat(data.toString());
} catch (NumberFormatException e) {
toolStats.logger.info("{} is not a valid float!", data);
return null;
}
return CustomModelData.customModelData().addFloat(f).build();
}
case "string": {
return CustomModelData.customModelData().addString(data.toString()).build();
}
default: {
toolStats.logger.info("{} is not a valid data type!", data);
return null;
}
}
}
}