mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-12-01 00:37:59 +01:00
230 lines
9.5 KiB
Java
230 lines
9.5 KiB
Java
package com.minelittlepony.unicopia.item;
|
|
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.stream.Stream;
|
|
|
|
import javax.annotation.Nullable;
|
|
|
|
import com.minelittlepony.unicopia.USounds;
|
|
import com.minelittlepony.unicopia.ability.magic.Caster;
|
|
import com.minelittlepony.unicopia.ability.magic.SpellPredicate;
|
|
import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod;
|
|
import com.minelittlepony.unicopia.ability.magic.spell.Spell;
|
|
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
|
import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation;
|
|
import com.minelittlepony.unicopia.entity.mob.CastSpellEntity;
|
|
import com.minelittlepony.unicopia.entity.mob.UEntities;
|
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
|
import com.minelittlepony.unicopia.item.group.MultiItem;
|
|
|
|
import net.minecraft.client.item.TooltipContext;
|
|
import net.minecraft.entity.Entity;
|
|
import net.minecraft.entity.EntityType;
|
|
import net.minecraft.entity.EquipmentSlot;
|
|
import net.minecraft.entity.LivingEntity;
|
|
import net.minecraft.entity.player.PlayerEntity;
|
|
import net.minecraft.item.ItemStack;
|
|
import net.minecraft.particle.ParticleTypes;
|
|
import net.minecraft.predicate.entity.EntityPredicates;
|
|
import net.minecraft.sound.SoundCategory;
|
|
import net.minecraft.text.Text;
|
|
import net.minecraft.util.ActionResult;
|
|
import net.minecraft.util.Hand;
|
|
import net.minecraft.util.TypedActionResult;
|
|
import net.minecraft.util.math.Vec3d;
|
|
import net.minecraft.world.World;
|
|
|
|
public class EnchantedStaffItem extends StaffItem implements EnchantableItem, ChargeableItem, MultiItem {
|
|
|
|
private static final Map<EntityType<?>, SpellType<?>> ENTITY_TYPE_TO_SPELL = new HashMap<>();
|
|
public static <T extends Spell> SpellType<T> register(EntityType<?> entityType, SpellType<T> spellType) {
|
|
ENTITY_TYPE_TO_SPELL.put(entityType, spellType);
|
|
return spellType;
|
|
}
|
|
|
|
public static SpellType<?> getSpellType(Entity entity, boolean remove) {
|
|
if (entity instanceof CastSpellEntity cast) {
|
|
return cast.getSpellSlot().get(c -> !SpellPredicate.IS_PLACED.test(c), true).map(Spell::getType).orElse(SpellType.empty());
|
|
}
|
|
if (entity instanceof PlayerEntity player) {
|
|
if (remove) {
|
|
return Pony.of(player).getCharms().equipSpell(Hand.MAIN_HAND, SpellType.EMPTY_KEY.withTraits()).type();
|
|
}
|
|
return Pony.of(player).getCharms().getEquippedSpell(Hand.MAIN_HAND).type();
|
|
}
|
|
return ENTITY_TYPE_TO_SPELL.getOrDefault(entity.getType(), SpellType.empty());
|
|
}
|
|
|
|
static {
|
|
register(EntityType.DROWNED, SpellType.BUBBLE);
|
|
register(EntityType.DOLPHIN, SpellType.BUBBLE);
|
|
register(EntityType.BLAZE, SpellType.FIRE_BOLT);
|
|
register(EntityType.CHICKEN, SpellType.FEATHER_FALL);
|
|
register(EntityType.CREEPER, SpellType.CATAPULT);
|
|
register(EntityType.HUSK, SpellType.HYDROPHOBIC);
|
|
register(EntityType.SNOW_GOLEM, SpellType.FROST);
|
|
register(EntityType.POLAR_BEAR, SpellType.FROST);
|
|
register(EntityType.FIREBALL, SpellType.FLAME);
|
|
register(EntityType.SMALL_FIREBALL, SpellType.FLAME);
|
|
register(EntityType.ENDER_DRAGON, SpellType.DISPLACEMENT);
|
|
register(EntityType.GUARDIAN, SpellType.AWKWARD);
|
|
register(EntityType.ELDER_GUARDIAN, SpellType.AWKWARD);
|
|
register(EntityType.DRAGON_FIREBALL, SpellType.INFERNAL);
|
|
register(EntityType.CAVE_SPIDER, SpellType.REVEALING);
|
|
register(EntityType.ZOMBIE, SpellType.NECROMANCY);
|
|
register(EntityType.VEX, SpellType.NECROMANCY);
|
|
register(EntityType.SKELETON, SpellType.CATAPULT);
|
|
register(EntityType.WITHER_SKELETON, SpellType.CATAPULT);
|
|
register(EntityType.SKELETON_HORSE, SpellType.CATAPULT);
|
|
register(UEntities.TWITTERMITE, SpellType.LIGHT);
|
|
}
|
|
|
|
public EnchantedStaffItem(Settings settings) {
|
|
super(settings.maxDamage(500));
|
|
}
|
|
|
|
@Override
|
|
public List<ItemStack> getDefaultStacks() {
|
|
return Stream.concat(
|
|
Stream.of(getDefaultStack()),
|
|
ENTITY_TYPE_TO_SPELL.values().stream().distinct().map(type -> EnchantableItem.enchant(getDefaultStack(), type))
|
|
).toList();
|
|
}
|
|
|
|
@Override
|
|
public void appendTooltip(ItemStack stack, @Nullable World world, List<Text> lines, TooltipContext context) {
|
|
|
|
if (EnchantableItem.isEnchanted(stack)) {
|
|
SpellType<?> key = EnchantableItem.getSpellKey(stack);
|
|
lines.add(Text.translatable(key.getTranslationKey()).formatted(key.getAffinity().getColor()));
|
|
lines.add(Text.translatable(getTranslationKey(stack) + ".charges", (int)Math.floor(ChargeableItem.getEnergy(stack)), getMaxCharge()));
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public ActionResult useOnEntity(ItemStack stack, PlayerEntity player, LivingEntity target, Hand hand) {
|
|
if (EnchantableItem.isEnchanted(stack)) {
|
|
return ActionResult.PASS;
|
|
}
|
|
|
|
super.useOnEntity(stack, player, target, hand);
|
|
|
|
boolean remove = EntityPredicates.EXCEPT_CREATIVE_OR_SPECTATOR.test(target);
|
|
SpellType<?> type = getSpellType(target, remove);
|
|
if (!type.isEmpty()) {
|
|
if (remove) {
|
|
target.setHealth(1);
|
|
target.setFrozenTicks(9000);
|
|
}
|
|
player.setStackInHand(hand, recharge(EnchantableItem.enchant(stack, type)));
|
|
}
|
|
return ActionResult.SUCCESS;
|
|
}
|
|
|
|
@Override
|
|
public TypedActionResult<ItemStack> use(World world, PlayerEntity player, Hand hand) {
|
|
ItemStack itemstack = player.getStackInHand(hand);
|
|
player.setCurrentHand(hand);
|
|
return TypedActionResult.consume(itemstack);
|
|
}
|
|
|
|
@Override
|
|
public void onStoppedUsing(ItemStack stack, World world, LivingEntity entity, int timeLeft) {
|
|
int i = getMaxUseTime(stack) - timeLeft;
|
|
|
|
if (EnchantableItem.isEnchanted(stack) && hasCharge(stack)) {
|
|
if (i > 20) {
|
|
Pony.of(entity).ifPresent(pony -> {
|
|
pony.subtractEnergyCost(4);
|
|
stack.damage(1, pony.asEntity(), p -> p.sendEquipmentBreakStatus(EquipmentSlot.MAINHAND));
|
|
getSpellEffect(stack).create().toThrowable().throwProjectile(pony);
|
|
pony.setAnimation(Animation.ARMS_UP, Animation.Recipient.ANYONE, 10);
|
|
});
|
|
ChargeableItem.consumeEnergy(stack, 1);
|
|
} else if (i > 5) {
|
|
Pony.of(entity).ifPresent(pony -> {
|
|
pony.subtractEnergyCost(4);
|
|
stack.damage(1, pony.asEntity(), p -> p.sendEquipmentBreakStatus(EquipmentSlot.MAINHAND));
|
|
getSpellEffect(stack).create().toThrowable().throwProjectile(pony);
|
|
pony.setAnimation(Animation.ARMS_UP, Animation.Recipient.ANYONE, 10);
|
|
});
|
|
ChargeableItem.consumeEnergy(stack, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected boolean castContainedEffect(ItemStack stack, LivingEntity target, LivingEntity attacker) {
|
|
if (attacker.isSneaking() && hasCharge(stack)) {
|
|
stack.damage(50, attacker, p -> p.sendEquipmentBreakStatus(EquipmentSlot.MAINHAND));
|
|
Caster.of(attacker).ifPresent(c -> c.subtractEnergyCost(4));
|
|
Caster.of(target).ifPresent(c -> getSpellEffect(stack).apply(c, CastingMethod.STAFF));
|
|
ChargeableItem.consumeEnergy(stack, 1);
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public void usageTick(World world, LivingEntity entity, ItemStack stack, int ticksRemaining) {
|
|
if (entity instanceof LivingEntity) {
|
|
LivingEntity living = entity;
|
|
|
|
if (living.getActiveItem().getItem() == this) {
|
|
Vec3d eyes = entity.getCameraPosVec(1);
|
|
|
|
float i = getMaxUseTime(stack) - ticksRemaining;
|
|
|
|
world.addParticle(i > 150 ? ParticleTypes.LARGE_SMOKE : ParticleTypes.CLOUD, eyes.x, eyes.y, eyes.z,
|
|
(world.random.nextGaussian() - 0.5) / 10,
|
|
(world.random.nextGaussian() - 0.5) / 10,
|
|
(world.random.nextGaussian() - 0.5) / 10
|
|
);
|
|
world.playSound(null, entity.getBlockPos(), USounds.ITEM_MAGIC_STAFF_CHARGE, SoundCategory.PLAYERS, 1, i / 20);
|
|
|
|
if (i > 200) {
|
|
living.clearActiveItem();
|
|
living.damage(entity.getDamageSources().magic(), 1);
|
|
if (EnchantableItem.isEnchanted(stack) && hasCharge(stack)) {
|
|
Caster.of(entity).ifPresent(c -> getSpellEffect(stack).apply(c, CastingMethod.STAFF));
|
|
ChargeableItem.consumeEnergy(stack, 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public int getMaxUseTime(ItemStack stack) {
|
|
return 72000;
|
|
}
|
|
|
|
@Override
|
|
public int getMaxCharge() {
|
|
return 3;
|
|
}
|
|
|
|
@Override
|
|
public int getDefaultCharge() {
|
|
return 3;
|
|
}
|
|
|
|
@Override
|
|
public Text getName(ItemStack stack) {
|
|
if (EnchantableItem.isEnchanted(stack) && hasCharge(stack)) {
|
|
return Text.translatable(this.getTranslationKey(stack) + ".enchanted", super.getName(stack), EnchantableItem.getSpellKey(stack).getName());
|
|
}
|
|
return super.getName(stack);
|
|
}
|
|
|
|
@Override
|
|
public void onDischarge(ItemStack stack) {
|
|
if ((stack.hasNbt() && stack.getNbt().contains("energy") ? stack.getNbt().getFloat("energy") : 0) == 0) {
|
|
EnchantableItem.unenchant(stack);
|
|
}
|
|
}
|
|
}
|