// 
// Decompiled by Procyon v0.6.0
// 

package com.hypixel.hytale.server.npc.systems;

import com.hypixel.hytale.component.Component;
import com.hypixel.hytale.component.Holder;
import com.hypixel.hytale.math.vector.Vector3f;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.server.core.inventory.Inventory;
import java.util.List;
import com.hypixel.hytale.server.npc.role.Role;
import com.hypixel.hytale.component.AddReason;
import com.hypixel.hytale.server.core.modules.entity.item.ItemComponent;
import com.hypixel.hytale.server.core.modules.entity.component.HeadRotation;
import com.hypixel.hytale.server.core.modules.item.ItemModule;
import java.util.Collection;
import com.hypixel.hytale.server.core.inventory.ItemStack;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import com.hypixel.hytale.server.core.asset.type.gameplay.DeathConfig;
import com.hypixel.hytale.server.core.modules.entity.damage.DeathComponent;
import com.hypixel.hytale.server.core.modules.entity.damage.DeathSystems;
import com.hypixel.hytale.server.npc.blackboard.view.event.entity.EntityEventType;
import com.hypixel.hytale.server.core.modules.entity.player.PlayerSettings;
import com.hypixel.hytale.protocol.GameMode;
import com.hypixel.hytale.math.util.ChunkUtil;
import com.hypixel.hytale.server.npc.blackboard.view.event.entity.EntityEventView;
import com.hypixel.hytale.server.npc.blackboard.Blackboard;
import com.hypixel.hytale.component.ResourceType;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.server.core.entity.entities.Player;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.component.Archetype;
import com.hypixel.hytale.server.npc.util.DamageData;
import com.hypixel.hytale.component.system.EcsEvent;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.server.core.modules.entity.damage.Damage;
import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.component.ArchetypeChunk;
import javax.annotation.Nullable;
import com.hypixel.hytale.server.core.modules.entity.damage.DamageModule;
import com.hypixel.hytale.component.SystemGroup;
import com.hypixel.hytale.server.npc.entities.NPCEntity;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.query.Query;
import com.hypixel.hytale.server.core.modules.entity.damage.DamageEventSystem;

public class NPCDamageSystems
{
    public static class FilterDamageSystem extends DamageEventSystem
    {
        @Nonnull
        private final Query<EntityStore> query;
        
        public FilterDamageSystem() {
            this.query = NPCEntity.getComponentType();
        }
        
        @Nullable
        @Override
        public SystemGroup<EntityStore> getGroup() {
            return DamageModule.get().getFilterDamageGroup();
        }
        
        @Nonnull
        @Override
        public Query<EntityStore> getQuery() {
            return this.query;
        }
        
        @Override
        public void handle(final int index, @Nonnull final ArchetypeChunk<EntityStore> archetypeChunk, @Nonnull final Store<EntityStore> store, @Nonnull final CommandBuffer<EntityStore> commandBuffer, @Nonnull final Damage damage) {
            final NPCEntity npcComponent = archetypeChunk.getComponent(index, NPCEntity.getComponentType());
            assert npcComponent != null;
            final Damage.Source source = damage.getSource();
            if (!(source instanceof Damage.EntitySource)) {
                return;
            }
            final Damage.EntitySource entitySource = (Damage.EntitySource)source;
            final Ref<EntityStore> sourceRef = entitySource.getRef();
            if (!sourceRef.isValid()) {
                return;
            }
            if (!npcComponent.getCanCauseDamage(sourceRef, commandBuffer)) {
                damage.setCancelled(true);
            }
        }
    }
    
    public static class DamageReceivedSystem extends DamageEventSystem
    {
        @Nonnull
        private final Query<EntityStore> query;
        
        public DamageReceivedSystem() {
            this.query = NPCEntity.getComponentType();
        }
        
        @Nullable
        @Override
        public SystemGroup<EntityStore> getGroup() {
            return DamageModule.get().getInspectDamageGroup();
        }
        
        @Nonnull
        @Override
        public Query<EntityStore> getQuery() {
            return this.query;
        }
        
        @Override
        public void handle(final int index, @Nonnull final ArchetypeChunk<EntityStore> archetypeChunk, @Nonnull final Store<EntityStore> store, @Nonnull final CommandBuffer<EntityStore> commandBuffer, @Nonnull final Damage damage) {
            final NPCEntity npcComponent = archetypeChunk.getComponent(index, NPCEntity.getComponentType());
            assert npcComponent != null;
            final DamageData damageData = npcComponent.getDamageData();
            damageData.onSufferedDamage(commandBuffer, damage);
        }
    }
    
    public static class DamageDealtSystem extends DamageEventSystem
    {
        @Nullable
        @Override
        public SystemGroup<EntityStore> getGroup() {
            return DamageModule.get().getInspectDamageGroup();
        }
        
        @Nonnull
        @Override
        public Query<EntityStore> getQuery() {
            return (Query<EntityStore>)Archetype.empty();
        }
        
        @Override
        public void handle(final int index, @Nonnull final ArchetypeChunk<EntityStore> archetypeChunk, @Nonnull final Store<EntityStore> store, @Nonnull final CommandBuffer<EntityStore> commandBuffer, @Nonnull final Damage damage) {
            final Damage.Source source = damage.getSource();
            if (!(source instanceof Damage.EntitySource)) {
                return;
            }
            final Damage.EntitySource entitySource = (Damage.EntitySource)source;
            final Ref<EntityStore> sourceRef = entitySource.getRef();
            if (!sourceRef.isValid()) {
                return;
            }
            final NPCEntity sourceNpcComponent = commandBuffer.getComponent(sourceRef, NPCEntity.getComponentType());
            if (sourceNpcComponent != null) {
                sourceNpcComponent.getDamageData().onInflictedDamage(archetypeChunk.getReferenceTo(index), damage.getAmount());
            }
        }
    }
    
    public static class DamageReceivedEventViewSystem extends DamageEventSystem
    {
        @Nonnull
        private final ComponentType<EntityStore, Player> playerComponentType;
        @Nonnull
        private final ComponentType<EntityStore, TransformComponent> transformComponentType;
        @Nonnull
        private final ResourceType<EntityStore, Blackboard> blackboardResourceType;
        @Nonnull
        private final Query<EntityStore> query;
        
        public DamageReceivedEventViewSystem() {
            this.playerComponentType = Player.getComponentType();
            this.transformComponentType = TransformComponent.getComponentType();
            this.blackboardResourceType = Blackboard.getResourceType();
            this.query = (Query<EntityStore>)Query.and(Query.or(NPCEntity.getComponentType(), this.playerComponentType), this.transformComponentType);
        }
        
        @Nullable
        @Override
        public SystemGroup<EntityStore> getGroup() {
            return DamageModule.get().getInspectDamageGroup();
        }
        
        @Nonnull
        @Override
        public Query<EntityStore> getQuery() {
            return this.query;
        }
        
        @Override
        public void handle(final int index, @Nonnull final ArchetypeChunk<EntityStore> archetypeChunk, @Nonnull final Store<EntityStore> store, @Nonnull final CommandBuffer<EntityStore> commandBuffer, @Nonnull final Damage damage) {
            final TransformComponent transformComponent = archetypeChunk.getComponent(index, this.transformComponentType);
            assert transformComponent != null;
            final Blackboard blackboard = commandBuffer.getResource(this.blackboardResourceType);
            final EntityEventView view = blackboard.getView(EntityEventView.class, ChunkUtil.chunkCoordinate(transformComponent.getPosition().x), ChunkUtil.chunkCoordinate(transformComponent.getPosition().z));
            final Damage.Source source = damage.getSource();
            if (!(source instanceof Damage.EntitySource)) {
                return;
            }
            final Damage.EntitySource entitySource = (Damage.EntitySource)source;
            final Ref<EntityStore> sourceRef = entitySource.getRef();
            if (!sourceRef.isValid()) {
                return;
            }
            final Player sourcePlayerComponent = commandBuffer.getComponent(sourceRef, Player.getComponentType());
            if (sourcePlayerComponent != null && sourcePlayerComponent.getGameMode() == GameMode.Creative) {
                final PlayerSettings playerSettingsComponent = commandBuffer.getComponent(sourceRef, PlayerSettings.getComponentType());
                if (playerSettingsComponent == null || !playerSettingsComponent.creativeSettings().allowNPCDetection()) {
                    return;
                }
            }
            view.processAttackedEvent(archetypeChunk.getReferenceTo(index), sourceRef, commandBuffer, EntityEventType.DAMAGE);
        }
    }
    
    public static class DropDeathItems extends DeathSystems.OnDeathSystem
    {
        @Nonnull
        private static final Query<EntityStore> QUERY;
        
        @Nonnull
        @Override
        public Query<EntityStore> getQuery() {
            return DropDeathItems.QUERY;
        }
        
        @Override
        public void onComponentAdded(@Nonnull final Ref<EntityStore> ref, @Nonnull final DeathComponent component, @Nonnull final Store<EntityStore> store, @Nonnull final CommandBuffer<EntityStore> commandBuffer) {
            if (component.getItemsLossMode() != DeathConfig.ItemsLossMode.ALL) {
                return;
            }
            final NPCEntity npcComponent = commandBuffer.getComponent(ref, NPCEntity.getComponentType());
            assert npcComponent != null;
            final Role role = npcComponent.getRole();
            if (role == null) {
                return;
            }
            final List<ItemStack> itemsToDrop = new ObjectArrayList<ItemStack>();
            if (role.isPickupDropOnDeath()) {
                final Inventory inventory = npcComponent.getInventory();
                itemsToDrop.addAll(inventory.getStorage().dropAllItemStacks());
            }
            final String dropListId = role.getDropListId();
            if (dropListId != null) {
                final ItemModule itemModule = ItemModule.get();
                if (itemModule.isEnabled()) {
                    final List<ItemStack> randomItemsToDrop = itemModule.getRandomItemDrops(dropListId);
                    itemsToDrop.addAll(randomItemsToDrop);
                }
            }
            if (!itemsToDrop.isEmpty()) {
                final TransformComponent transformComponent = store.getComponent(ref, TransformComponent.getComponentType());
                assert transformComponent != null;
                final Vector3d position = transformComponent.getPosition();
                final HeadRotation headRotationComponent = store.getComponent(ref, HeadRotation.getComponentType());
                assert headRotationComponent != null;
                final Vector3f headRotation = headRotationComponent.getRotation();
                final Vector3d dropPosition = position.clone().add(0.0, 1.0, 0.0);
                final Holder<EntityStore>[] drops = ItemComponent.generateItemDrops(store, itemsToDrop, dropPosition, headRotation.clone());
                commandBuffer.addEntities(drops, AddReason.SPAWN);
            }
        }
        
        static {
            QUERY = Query.and(NPCEntity.getComponentType(), TransformComponent.getComponentType(), HeadRotation.getComponentType(), Query.not((Query<Object>)Player.getComponentType()));
        }
    }
}
