package com.thebrokenrail.reliccraft.item; import com.squareup.moshi.JsonAdapter; import com.squareup.moshi.Moshi; import com.thebrokenrail.reliccraft.RelicCraft; import com.thebrokenrail.reliccraft.data.Action; import com.thebrokenrail.reliccraft.data.Actions; import com.thebrokenrail.reliccraft.data.RelicData; import com.thebrokenrail.reliccraft.entity.RelicEntity; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.block.BlockState; import net.minecraft.client.item.TooltipContext; import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Item; import net.minecraft.item.ItemGroup; import net.minecraft.item.ItemStack; import net.minecraft.item.ItemUsageContext; import net.minecraft.item.Items; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; import net.minecraft.text.TranslatableText; import net.minecraft.util.ActionResult; import net.minecraft.util.Formatting; import net.minecraft.util.Hand; import net.minecraft.util.Rarity; import net.minecraft.util.TypedActionResult; import net.minecraft.util.collection.DefaultedList; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import java.util.List; public class RelicItem extends Item { public RelicItem() { super(new Settings().group(RelicCraft.ITEM_GROUP).rarity(Rarity.UNCOMMON).maxDamage(1)); } @Override public void appendStacks(ItemGroup group, DefaultedList stacks) { } @Override public Text getName(ItemStack stack) { RelicData data = getData(stack); return new TranslatableText("text." + RelicCraft.NAMESPACE + ".relic.title_variant." + data.name.variant, super.getName(stack), new TranslatableText("text." + RelicCraft.NAMESPACE + ".relic.magic_word." + data.name.magicWord)); } public static RelicData getData(ItemStack stack) { CompoundTag tag = stack.getTag(); if (tag == null) { return new RelicData(); } Moshi moshi = new Moshi.Builder().build(); JsonAdapter jsonAdapter = moshi.adapter(RelicData.class); try { return jsonAdapter.fromJson(tag.getString("RelicData")); } catch (Throwable e) { return new RelicData(); } } public int getMaxDamage(ItemStack stack) { return getData(stack).maxDurability; } @Override public boolean hasGlint(ItemStack stack) { RelicData data = getData(stack); return super.hasGlint(stack) || data.enchantmentGlint; } @Override public boolean postHit(ItemStack stack, LivingEntity target, LivingEntity attacker) { if (attacker instanceof PlayerEntity) { RelicData data = getData(stack); if (!attacker.getEntityWorld().isClient()) { String id = data.attack[RANDOM.nextInt(data.attack.length)]; Action action = Actions.get(id); action.execute(attacker.getEntityWorld(), attacker, target); } damage(stack, (PlayerEntity) attacker, Hand.MAIN_HAND); return true; } else { return false; } } @Override public boolean canMine(BlockState state, World world, BlockPos pos, PlayerEntity miner) { RelicData data = getData(miner.getMainHandStack()); if (!world.isClient()) { String id = data.attack[RANDOM.nextInt(data.attack.length)]; Action action = Actions.get(id); action.execute(miner.getEntityWorld(), miner, pos); } damage(miner.getMainHandStack(), miner, Hand.MAIN_HAND); return false; } @Override public TypedActionResult use(World world, PlayerEntity user, Hand hand) { ItemStack stack = user.getStackInHand(hand); RelicData data = getData(stack); if (data.use.mode == RelicData.UseData.Mode.PROJECTILE) { if (!world.isClient()) { RelicEntity entity = new RelicEntity(world, user); entity.setItem(stack); entity.setProperties(user, user.pitch, user.yaw, 0.0f, 1.5f, 1.0f); world.spawnEntity(entity); } damage(stack, user, hand); return new TypedActionResult<>(ActionResult.SUCCESS, stack); } else if (data.use.mode == RelicData.UseData.Mode.SELF) { if (!world.isClient()) { String id = data.use.actions[RANDOM.nextInt(data.use.actions.length)]; Action action = Actions.get(id); action.execute(user.getEntityWorld(), user, user); } damage(stack, user, hand); return new TypedActionResult<>(ActionResult.SUCCESS, stack); } else { return new TypedActionResult<>(ActionResult.PASS, stack); } } @Override public ActionResult useOnEntity(ItemStack stack, PlayerEntity user, LivingEntity entity, Hand hand) { RelicData data = getData(stack); if (data.use.mode == RelicData.UseData.Mode.TARGET) { if (!user.getEntityWorld().isClient()) { String id = data.use.actions[RANDOM.nextInt(data.use.actions.length)]; Action action = Actions.get(id); action.execute(user.getEntityWorld(), user, entity); } damage(stack, user, hand); return ActionResult.SUCCESS; } else { return ActionResult.PASS; } } @Override public ActionResult useOnBlock(ItemUsageContext context) { assert context.getPlayer() != null; RelicData data = getData(context.getStack()); if (data.use.mode == RelicData.UseData.Mode.TARGET) { if (!context.getWorld().isClient()) { String id = data.use.actions[RANDOM.nextInt(data.use.actions.length)]; Action action = Actions.get(id); action.execute(context.getPlayer().getEntityWorld(), context.getPlayer(), context.getBlockPos()); } damage(context.getStack(), context.getPlayer(), context.getHand()); return ActionResult.SUCCESS; } else { return ActionResult.PASS; } } @Override public boolean canRepair(ItemStack stack, ItemStack ingredient) { return ingredient.getItem() == Items.BLAZE_POWDER; } public static final String RELIC_REVEALED_KEY = "RelicRevealed"; @Environment(EnvType.CLIENT) @Override public void appendTooltip(ItemStack stack, World world, List tooltip, TooltipContext context) { super.appendTooltip(stack, world, tooltip, context); CompoundTag tag = stack.getTag(); if (tag == null) { tag = new CompoundTag(); } byte revealed = tag.getByte(RELIC_REVEALED_KEY); if (revealed >= 2) { RelicData data = getData(stack); tooltip.add(new TranslatableText("item." + RelicCraft.NAMESPACE + ".tooltip.relic.on_attack").formatted(Formatting.WHITE)); for (String action : data.attack) { tooltip.add(new TranslatableText("item." + RelicCraft.NAMESPACE + ".tooltip.relic.on_attack.action", new TranslatableText("text." + RelicCraft.NAMESPACE + ".relic.action." + action).formatted(Formatting.GRAY))); } tooltip.add(new TranslatableText("item." + RelicCraft.NAMESPACE + ".tooltip.relic.on_use").formatted(Formatting.WHITE)); tooltip.add(new TranslatableText("item." + RelicCraft.NAMESPACE + ".tooltip.relic.on_use.mode", new TranslatableText("item." + RelicCraft.NAMESPACE + ".tooltip.relic.on_use.mode." + data.use.mode.name().toLowerCase()).formatted(Formatting.GRAY)).formatted(Formatting.WHITE)); tooltip.add(new TranslatableText("item." + RelicCraft.NAMESPACE + ".tooltip.relic.on_use.actions").formatted(Formatting.WHITE)); for (String action : data.use.actions) { tooltip.add(new TranslatableText("item." + RelicCraft.NAMESPACE + ".tooltip.relic.on_use.actions.action", new TranslatableText("text." + RelicCraft.NAMESPACE + ".relic.action." + action).formatted(Formatting.GRAY))); } } else if (revealed == 1) { tooltip.add(new TranslatableText("item." + RelicCraft.NAMESPACE + ".tooltip.relic.not_crafted").formatted(Formatting.WHITE)); } } @Override public void inventoryTick(ItemStack stack, World world, Entity entity, int slot, boolean selected) { CompoundTag tag = stack.getTag(); if (tag == null) { tag = new CompoundTag(); } byte revealed = tag.getByte(RELIC_REVEALED_KEY); if (revealed == 1) { if (entity instanceof ServerPlayerEntity) { RelicCraft.REVEAL_RELIC_CRITERION.trigger((ServerPlayerEntity) entity); } tag.putByte(RELIC_REVEALED_KEY, (byte) 2); } stack.setTag(tag); } private void damage(ItemStack stack, PlayerEntity player, Hand hand) { stack.damage(RANDOM.nextInt(4) + 1, player, e -> e.sendToolBreakStatus(hand)); player.getItemCooldownManager().set(this, 10); RelicCraft.playRelicSound(player); } }