All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.nukkit.entity.mob.EntityMob Maven / Gradle / Ivy

There is a newer version: 1.20.40-r1
Show newest version
package cn.nukkit.entity.mob;

import cn.nukkit.Player;
import cn.nukkit.api.PowerNukkitOnly;
import cn.nukkit.api.Since;
import cn.nukkit.block.BlockID;
import cn.nukkit.entity.Entity;
import cn.nukkit.entity.EntityCanAttack;
import cn.nukkit.entity.EntityIntelligent;
import cn.nukkit.event.entity.EntityDamageByEntityEvent;
import cn.nukkit.event.entity.EntityDamageEvent;
import cn.nukkit.inventory.EntityArmorInventory;
import cn.nukkit.inventory.EntityEquipmentInventory;
import cn.nukkit.inventory.EntityInventoryHolder;
import cn.nukkit.inventory.Inventory;
import cn.nukkit.item.Item;
import cn.nukkit.item.enchantment.Enchantment;
import cn.nukkit.level.Sound;
import cn.nukkit.level.format.FullChunk;
import cn.nukkit.math.NukkitMath;
import cn.nukkit.nbt.NBTIO;
import cn.nukkit.nbt.tag.CompoundTag;
import cn.nukkit.nbt.tag.FloatTag;
import cn.nukkit.nbt.tag.ListTag;
import cn.nukkit.utils.Utils;
import lombok.Getter;

import java.util.Collection;
import java.util.concurrent.ThreadLocalRandom;

/**
 * @author MagicDroidX (Nukkit Project)
 */

public abstract class EntityMob extends EntityIntelligent implements EntityInventoryHolder, EntityCanAttack {

    private static final String TAG_MAINHAND = "Mainhand";
    private static final String TAG_OFFHAND = "Offhand";
    private static final String TAG_ARMOR = "Armor";
    public static final String DIFFICULTY_HAND_DAMAGE = "diffHandDamage";

    @Getter
    private EntityEquipmentInventory equipmentInventory;

    @Getter
    private EntityArmorInventory armorInventory;

    /**
     * 不同难度下实体空手能造成的伤害.
     * 

* The damage that can be caused by the entity's empty hand at different difficulties. */ protected float[] diffHandDamage; public EntityMob(FullChunk chunk, CompoundTag nbt) { super(chunk, nbt); } @Override protected void initEntity() { super.initEntity(); this.equipmentInventory = new EntityEquipmentInventory(this); this.armorInventory = new EntityArmorInventory(this); if (this.namedTag.contains(TAG_MAINHAND)) { this.equipmentInventory.setItemInHand(NBTIO.getItemHelper(this.namedTag.getCompound(TAG_MAINHAND)), true); } if (this.namedTag.contains(TAG_OFFHAND)) { this.equipmentInventory.setItemInOffhand(NBTIO.getItemHelper(this.namedTag.getCompound(TAG_OFFHAND)), true); } if (this.namedTag.contains(TAG_ARMOR)) { ListTag armorList = this.namedTag.getList(TAG_ARMOR, CompoundTag.class); for (CompoundTag armorTag : armorList.getAll()) { this.armorInventory.setItem(armorTag.getByte("Slot"), NBTIO.getItemHelper(armorTag)); } } if (this.namedTag.contains(DIFFICULTY_HAND_DAMAGE)) { var damageList = this.namedTag.getList(DIFFICULTY_HAND_DAMAGE, FloatTag.class); this.diffHandDamage = new float[3]; this.diffHandDamage[0] = damageList.get(0).getData(); this.diffHandDamage[1] = damageList.get(1).getData(); this.diffHandDamage[2] = damageList.get(2).getData(); } } public void spawnToAll() { if (this.chunk != null && !this.closed) { Collection chunkPlayers = this.level.getChunkPlayers(this.chunk.getX(), this.chunk.getZ()).values(); for (Player chunkPlayer : chunkPlayers) { this.spawnTo(chunkPlayer); } } } @Override public void spawnTo(Player player) { super.spawnTo(player); this.equipmentInventory.sendContents(player); this.armorInventory.sendContents(player); } @Override public void saveNBT() { super.saveNBT(); this.namedTag.put(TAG_MAINHAND, NBTIO.putItemHelper(this.equipmentInventory.getItemInHand())); this.namedTag.put(TAG_OFFHAND, NBTIO.putItemHelper(this.equipmentInventory.getItemInOffhand())); if (this.armorInventory != null) { ListTag armorTag = new ListTag<>(TAG_ARMOR); for (int i = 0; i < 4; i++) { armorTag.add(NBTIO.putItemHelper(this.armorInventory.getItem(i), i)); } this.namedTag.putList(armorTag); } if (diffHandDamage != null) this.namedTag.putList(new ListTag(DIFFICULTY_HAND_DAMAGE).add(new FloatTag("", this.diffHandDamage[0])).add(new FloatTag("", this.diffHandDamage[1])).add(new FloatTag("", this.diffHandDamage[2]))); } @Override public boolean attack(EntityDamageEvent source) { if (this.isClosed() || !this.isAlive()) { return false; } if (source.getCause() != EntityDamageEvent.DamageCause.VOID && source.getCause() != EntityDamageEvent.DamageCause.CUSTOM && source.getCause() != EntityDamageEvent.DamageCause.MAGIC && source.getCause() != EntityDamageEvent.DamageCause.HUNGER) { int armorPoints = 0; int epf = 0; // int toughness = 0; var armorInventory = this.getArmorInventory(); for (Item armor : armorInventory.getContents().values()) { armorPoints += armor.getArmorPoints(); epf += calculateEnchantmentProtectionFactor(armor, source); //toughness += armor.getToughness(); } if (source.canBeReducedByArmor()) { source.setDamage(-source.getFinalDamage() * armorPoints * 0.04f, EntityDamageEvent.DamageModifier.ARMOR); } source.setDamage(-source.getFinalDamage() * Math.min(NukkitMath.ceilFloat(Math.min(epf, 25) * ((float) ThreadLocalRandom.current().nextInt(50, 100) / 100)), 20) * 0.04f, EntityDamageEvent.DamageModifier.ARMOR_ENCHANTMENTS); source.setDamage(-Math.min(this.getAbsorption(), source.getFinalDamage()), EntityDamageEvent.DamageModifier.ABSORPTION); } if (super.attack(source)) { Entity damager = null; if (source instanceof EntityDamageByEntityEvent) { damager = ((EntityDamageByEntityEvent) source).getDamager(); } for (int slot = 0; slot < 4; slot++) { Item armor = damageArmor(armorInventory.getItem(slot), damager); armorInventory.setItem(slot, armor, armor.getId() != BlockID.AIR); } return true; } else { return false; } } @Override public void setOnFire(int seconds) { int level = 0; for (Item armor : this.getArmorInventory().getContents().values()) { Enchantment fireProtection = armor.getEnchantment(Enchantment.ID_PROTECTION_FIRE); if (fireProtection != null && fireProtection.getLevel() > 0) { level = Math.max(level, fireProtection.getLevel()); } } seconds = (int) (seconds * (1 - level * 0.15)); super.setOnFire(seconds); } protected double calculateEnchantmentProtectionFactor(Item item, EntityDamageEvent source) { if (!item.hasEnchantments()) { return 0; } double epf = 0; if (item.applyEnchantments()) { for (Enchantment ench : item.getEnchantments()) { epf += ench.getProtectionFactor(source); } } return epf; } @PowerNukkitOnly @Since("1.4.0.0-PN") protected Item damageArmor(Item armor, Entity damager) { if (armor.hasEnchantments()) { if (damager != null) { if (armor.applyEnchantments()) { for (Enchantment enchantment : armor.getEnchantments()) { enchantment.doPostAttack(damager, this); } } } Enchantment durability = armor.getEnchantment(Enchantment.ID_DURABILITY); if (durability != null && durability.getLevel() > 0 && (100 / (durability.getLevel() + 1)) <= Utils.random.nextInt(100)) { return armor; } } if (armor.isUnbreakable() || armor.getMaxDurability() < 0) { return armor; } armor.setDamage(armor.getDamage() + 1); if (armor.getDamage() >= armor.getMaxDurability()) { getLevel().addSound(this, Sound.RANDOM_BREAK); return Item.get(BlockID.AIR, 0, 0); } return armor; } @Override public Inventory getInventory() { return this.armorInventory; } @Override public boolean canEquipByDispenser() { return true; } @Override public float[] getDiffHandDamage() { return this.diffHandDamage; } @Override public float getDiffHandDamage(int difficulty) { return this.diffHandDamage[difficulty - 1]; } @Override public void setDiffHandDamage(float[] damages) { this.diffHandDamage = damages; this.namedTag.putList(new ListTag(DIFFICULTY_HAND_DAMAGE).add(new FloatTag("", this.diffHandDamage[0])).add(new FloatTag("", this.diffHandDamage[1])).add(new FloatTag("", this.diffHandDamage[2]))); } @Override public void setDiffHandDamage(int difficulty, float damage) { this.diffHandDamage[difficulty - 1] = damage; this.namedTag.putList(new ListTag(DIFFICULTY_HAND_DAMAGE).add(new FloatTag("", this.diffHandDamage[0])).add(new FloatTag("", this.diffHandDamage[1])).add(new FloatTag("", this.diffHandDamage[2]))); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy