diff --git a/src/main/java/dev/micle/totemofreviving/item/TotemItem.java b/src/main/java/dev/micle/totemofreviving/item/TotemItem.java new file mode 100644 index 0000000..838f5a7 --- /dev/null +++ b/src/main/java/dev/micle/totemofreviving/item/TotemItem.java @@ -0,0 +1,227 @@ +package dev.micle.totemofreviving.item; + +import dev.micle.totemofreviving.TotemOfReviving; +import dev.micle.totemofreviving.config.Config; +import dev.micle.totemofreviving.network.ChangeTargetPacket; +import dev.micle.totemofreviving.network.ChargeTotemPacket; +import dev.micle.totemofreviving.network.Network; +import dev.micle.totemofreviving.network.ReviveTargetPacket; +import net.minecraft.client.Minecraft; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.client.util.InputMappings; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Rarity; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.StringTextComponent; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import org.lwjgl.glfw.GLFW; + +import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.List; +import java.util.UUID; + +public abstract class TotemItem extends Item { + private static final String TAG_TARGET_INDEX = "target_index"; + private static final String TAG_TARGET_UUID = "target_uuid"; + private static final String TAG_TARGET_NAME = "target_name"; + private static final String TAG_TARGET_COST = "target_cost"; + private static final String TAG_CHARGE = "charge"; + + public TotemItem(int durability) { + this(Rarity.COMMON, durability); + } + + public TotemItem(Rarity rarity, int durability) { + super(new Item.Properties().tab(TotemOfReviving.ITEM_GROUP).stacksTo(1).rarity(rarity).defaultDurability(durability)); + } + + public abstract boolean isCharge(ItemStack stack); + + public static int getTargetIndex(ItemStack stack) { + if (!isTotem(stack)) { return -1; } + return stack.getOrCreateTag().getInt(TAG_TARGET_INDEX); + } + public static void setTargetIndex(ItemStack stack, int targetIndex) { + if (!isTotem(stack)) { return; } + stack.getOrCreateTag().putInt(TAG_TARGET_INDEX, targetIndex); + } + + public static UUID getTargetUUID(ItemStack stack) { + if (!isTotem(stack)) { return null; } + try { + return UUID.fromString(stack.getOrCreateTag().getString(TAG_TARGET_UUID)); + } catch (IllegalArgumentException exception) { + return null; + } + } + public static void setTargetUUID(ItemStack stack, UUID targetUUID) { + if (!isTotem(stack)) { return; } + stack.getOrCreateTag().putString(TAG_TARGET_UUID, targetUUID.toString()); + } + + public static String getTargetName(ItemStack stack) { + if (!isTotem(stack)) { return null; } + return stack.getOrCreateTag().getString(TAG_TARGET_NAME); + } + public static void setTagTargetName(ItemStack stack, String targetName) { + if (!isTotem(stack)) { return; } + stack.getOrCreateTag().putString(TAG_TARGET_NAME, targetName); + } + + public static int getTargetCost(ItemStack stack) { + if (!isTotem(stack)) { return -1; } + return stack.getOrCreateTag().getInt(TAG_TARGET_COST); + } + public static void setTargetCost(ItemStack stack, int targetCost) { + if (!isTotem(stack)) { return; } + stack.getOrCreateTag().putInt(TAG_TARGET_COST, targetCost); + } + + public static int getCharge(ItemStack stack) { + if (!isTotem(stack)) { return -1; } + int charge = stack.getOrCreateTag().getInt(TAG_CHARGE); + int maxCharge = getMaxCharge(stack); + if (charge > maxCharge) { + charge = maxCharge; + setCharge(stack, charge); + } + return charge; + } + public static void setCharge(ItemStack stack, int charge) { + if (!isTotem(stack)) { return; } + stack.getOrCreateTag().putInt(TAG_CHARGE, charge); + } + + public static int getMaxCharge(ItemStack stack) { + Config.TotemConfig config = getConfig(stack); + if (config == null) { return -1; } + + if (config.getChargeCost() == -1) { + return config.getChargeCostLimit(); + } + return config.getChargeCost(); + } + + public static boolean isCostDynamic(ItemStack stack) { + if (!isTotem(stack)) { return false; } + return getConfig(stack).getChargeCost() == -1; + } + + public static boolean canReviveAcrossDimensions(ItemStack stack) { + if (!isTotem(stack)) { return false; } + return getConfig(stack).getCanReviveAcrossDimensions(); + } + + public static boolean canReviveMoreExpensiveTargets(ItemStack stack) { + if (!isTotem(stack)) { return false; } + return getConfig(stack).getCanReviveMoreExpensiveTargets(); + } + + public static boolean isEnabled(ItemStack stack) { + if (!isTotem(stack)) { return false; } + return getConfig(stack).getIsEnabled(); + } + + @Override + @OnlyIn(Dist.CLIENT) + @ParametersAreNonnullByDefault + public void appendHoverText(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag tooltipFlag) { + if (world == null) { return; } + + UUID targetUUID = getTargetUUID(stack); + String targetName = getTargetName(stack); + int targetCost = getTargetCost(stack); + int charge = getCharge(stack); + int maxCharge = getMaxCharge(stack); + + if (getConfig(stack).getIsEnabled()) { + if (targetUUID == null) { + tooltip.add(new StringTextComponent(TextFormatting.RED + "Target: " + TextFormatting.DARK_RED + "NONE")); + } else { + tooltip.add(new StringTextComponent(TextFormatting.WHITE + "Target: " + TextFormatting.GRAY + targetName)); + } + tooltip.add(new StringTextComponent("")); + if (charge < targetCost && !canReviveMoreExpensiveTargets(stack)) { + tooltip.add(new StringTextComponent(TextFormatting.RED + "Charges: " + TextFormatting.DARK_RED + "(" + charge + "/" + targetCost + ") " + + TextFormatting.RED + "[Max: " + TextFormatting.DARK_RED + maxCharge + TextFormatting.RED + "]")); + } else { + tooltip.add(new StringTextComponent(TextFormatting.WHITE + "Charges: " + TextFormatting.GRAY + "(" + charge + "/" + targetCost + ") " + + TextFormatting.WHITE + "[Max: " + TextFormatting.GRAY + maxCharge + TextFormatting.WHITE + "]")); + } + tooltip.add(new StringTextComponent("")); + if (InputMappings.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), GLFW.GLFW_KEY_LEFT_SHIFT)) { + tooltip.add(new StringTextComponent(TextFormatting.GRAY + "Showing advanced tooltip.")); + tooltip.add(new StringTextComponent(TextFormatting.WHITE + "[" + TextFormatting.GRAY + "R-CLICK" + TextFormatting.WHITE + "]")); + tooltip.add(new StringTextComponent(TextFormatting.WHITE + "When second hand is empty: revive target.")); + tooltip.add(new StringTextComponent(TextFormatting.WHITE + "When second hand is holding a reviving charge: charge totem.")); + tooltip.add(new StringTextComponent("")); + tooltip.add(new StringTextComponent(TextFormatting.WHITE + "[" + TextFormatting.GRAY + "L-SHIFT + R-CLICK" + TextFormatting.WHITE + "]")); + tooltip.add(new StringTextComponent(TextFormatting.WHITE + "Change target.")); + } else { + tooltip.add(new StringTextComponent(TextFormatting.GRAY + "Hold [" + TextFormatting.DARK_GRAY + "L-SHIFT" + TextFormatting.GRAY + "] for advanced tooltip.")); + } + } else { + tooltip.add(new StringTextComponent(TextFormatting.RED + "Totem is disabled!")); + } + super.appendHoverText(stack, world, tooltip, tooltipFlag); + } + + @Override + @OnlyIn(Dist.CLIENT) + @ParametersAreNonnullByDefault + public ActionResult use(World world, PlayerEntity player, Hand hand) { + if (!getConfig(player.getItemInHand(hand)).getIsEnabled() || !world.isClientSide) { + return super.use(world, player, hand); + } + + ItemStack chargeItem = (hand.equals(Hand.MAIN_HAND)) ? player.getOffhandItem() : player.getMainHandItem(); + + if (player.isCrouching()) { + Network.channel.sendToServer(new ChangeTargetPacket(hand)); + } else { + if (isCharge(chargeItem)) { + Network.channel.sendToServer(new ChargeTotemPacket(hand)); + } else { + Network.channel.sendToServer(new ReviveTargetPacket(hand)); + } + } + return super.use(world, player, hand); + } + + @Override + public int getMaxDamage(ItemStack stack) { + return getConfig(stack).getDurability(); + } + + @Override + public boolean isDamageable(ItemStack stack) { + return (getConfig(stack).getDurability() != 0); + } + + @Override + public int getDamage(ItemStack stack) { + if (isDamageable(stack) && super.getDamage(stack) >= getMaxDamage(stack)) { + stack.setCount(0); + return getMaxDamage(stack); + } + return (isDamageable(stack)) ? super.getDamage(stack) : 0; + } + + private static boolean isTotem(ItemStack stack) { + return (stack.getItem() instanceof TotemItem); + } + + private static Config.TotemConfig getConfig(ItemStack stack) { + Item item = stack.getItem(); + if (item instanceof StrawTotemItem) { return Config.Server.getStrawTotemConfig(); } + return null; + } +}