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

package com.hypixel.hytale.server.core.universe.world;

import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.server.core.entity.Entity;
import com.hypixel.hytale.server.core.entity.EntityUtils;
import javax.annotation.Nullable;
import java.util.function.Predicate;
import it.unimi.dsi.fastutil.objects.ObjectListIterator;
import it.unimi.dsi.fastutil.objects.ObjectList;
import java.util.List;
import com.hypixel.hytale.server.core.modules.entity.EntityModule;
import com.hypixel.hytale.component.spatial.SpatialResource;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.protocol.packets.world.PlaySoundEvent3D;
import com.hypixel.hytale.protocol.Position;
import com.hypixel.hytale.server.core.asset.type.soundevent.config.SoundEvent;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.protocol.packets.world.PlaySoundEvent2D;
import com.hypixel.hytale.protocol.SoundCategory;
import com.hypixel.hytale.server.core.universe.PlayerRef;
import com.hypixel.hytale.protocol.Packet;
import com.hypixel.hytale.protocol.packets.world.PlaySoundEventEntity;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.ComponentAccessor;

public class SoundUtil
{
    public static void playSoundEventEntity(final int soundEventIndex, final int networkId, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        playSoundEventEntity(soundEventIndex, networkId, 1.0f, 1.0f, componentAccessor);
    }
    
    public static void playSoundEventEntity(final int soundEventIndex, final int networkId, final float volumeModifier, final float pitchModifier, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        if (soundEventIndex == 0) {
            return;
        }
        PlayerUtil.broadcastPacketToPlayers(componentAccessor, new PlaySoundEventEntity(soundEventIndex, networkId, volumeModifier, pitchModifier));
    }
    
    public static void playSoundEvent2dToPlayer(@Nonnull final PlayerRef playerRefComponent, final int soundEventIndex, @Nonnull final SoundCategory soundCategory) {
        playSoundEvent2dToPlayer(playerRefComponent, soundEventIndex, soundCategory, 1.0f, 1.0f);
    }
    
    public static void playSoundEvent2dToPlayer(@Nonnull final PlayerRef playerRefComponent, final int soundEventIndex, @Nonnull final SoundCategory soundCategory, final float volumeModifier, final float pitchModifier) {
        if (soundEventIndex == 0) {
            return;
        }
        playerRefComponent.getPacketHandler().write(new PlaySoundEvent2D(soundEventIndex, soundCategory, volumeModifier, pitchModifier));
    }
    
    public static void playSoundEvent2d(final int soundEventIndex, @Nonnull final SoundCategory soundCategory, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        playSoundEvent2d(soundEventIndex, soundCategory, 1.0f, 1.0f, componentAccessor);
    }
    
    public static void playSoundEvent2d(final int soundEventIndex, @Nonnull final SoundCategory soundCategory, final float volumeModifier, final float pitchModifier, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        if (soundEventIndex == 0) {
            return;
        }
        PlayerUtil.broadcastPacketToPlayers(componentAccessor, new PlaySoundEvent2D(soundEventIndex, soundCategory, volumeModifier, pitchModifier));
    }
    
    public static void playSoundEvent2d(@Nonnull final Ref<EntityStore> ref, final int soundEventIndex, @Nonnull final SoundCategory soundCategory, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        playSoundEvent2d(ref, soundEventIndex, soundCategory, 1.0f, 1.0f, componentAccessor);
    }
    
    public static void playSoundEvent2d(@Nonnull final Ref<EntityStore> ref, final int soundEventIndex, @Nonnull final SoundCategory soundCategory, final float volumeModifier, final float pitchModifier, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        if (soundEventIndex == 0) {
            return;
        }
        final PlayerRef playerRefComponent = componentAccessor.getComponent(ref, PlayerRef.getComponentType());
        if (playerRefComponent == null) {
            return;
        }
        playerRefComponent.getPacketHandler().write(new PlaySoundEvent2D(soundEventIndex, soundCategory, volumeModifier, pitchModifier));
    }
    
    public static void playSoundEvent3d(final int soundEventIndex, @Nonnull final SoundCategory soundCategory, final double x, final double y, final double z, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        playSoundEvent3d(soundEventIndex, soundCategory, x, y, z, 1.0f, 1.0f, componentAccessor);
    }
    
    public static void playSoundEvent3d(final int soundEventIndex, @Nonnull final SoundCategory soundCategory, final double x, final double y, final double z, final float volumeModifier, final float pitchModifier, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        if (soundEventIndex == 0) {
            return;
        }
        final SoundEvent soundEvent = SoundEvent.getAssetMap().getAsset(soundEventIndex);
        if (soundEvent == null) {
            return;
        }
        final PlaySoundEvent3D packet = new PlaySoundEvent3D(soundEventIndex, soundCategory, new Position(x, y, z), volumeModifier, pitchModifier);
        final Vector3d position = new Vector3d(x, y, z);
        final SpatialResource<Ref<EntityStore>, EntityStore> playerSpatialResource = componentAccessor.getResource(EntityModule.get().getPlayerSpatialResourceType());
        final ObjectList<Ref<EntityStore>> results = SpatialResource.getThreadLocalReferenceList();
        playerSpatialResource.getSpatialStructure().collect(position, soundEvent.getMaxDistance(), results);
        for (final Ref<EntityStore> playerRef : results) {
            if (playerRef != null) {
                if (!playerRef.isValid()) {
                    continue;
                }
                final PlayerRef playerRefComponent = componentAccessor.getComponent(playerRef, PlayerRef.getComponentType());
                assert playerRefComponent != null;
                playerRefComponent.getPacketHandler().write(packet);
            }
        }
    }
    
    public static void playSoundEvent3d(final int soundEventIndex, @Nonnull final SoundCategory soundCategory, @Nonnull final Vector3d position, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        playSoundEvent3d(soundEventIndex, soundCategory, position.getX(), position.getY(), position.getZ(), componentAccessor);
    }
    
    public static void playSoundEvent3d(final int soundEventIndex, @Nonnull final SoundCategory soundCategory, final double x, final double y, final double z, @Nonnull final Predicate<Ref<EntityStore>> shouldHear, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        playSoundEvent3d(soundEventIndex, soundCategory, x, y, z, 1.0f, 1.0f, shouldHear, componentAccessor);
    }
    
    public static void playSoundEvent3d(final int soundEventIndex, @Nonnull final SoundCategory soundCategory, final double x, final double y, final double z, final float volumeModifier, final float pitchModifier, @Nonnull final Predicate<Ref<EntityStore>> shouldHear, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        if (soundEventIndex == 0) {
            return;
        }
        final SoundEvent soundEvent = SoundEvent.getAssetMap().getAsset(soundEventIndex);
        if (soundEvent == null) {
            return;
        }
        final PlaySoundEvent3D packet = new PlaySoundEvent3D(soundEventIndex, soundCategory, new Position(x, y, z), volumeModifier, pitchModifier);
        final SpatialResource<Ref<EntityStore>, EntityStore> playerSpatialResource = componentAccessor.getResource(EntityModule.get().getPlayerSpatialResourceType());
        final ObjectList<Ref<EntityStore>> results = SpatialResource.getThreadLocalReferenceList();
        playerSpatialResource.getSpatialStructure().collect(new Vector3d(x, y, z), soundEvent.getMaxDistance(), results);
        for (final Ref<EntityStore> playerRef : results) {
            if (playerRef != null) {
                if (!playerRef.isValid()) {
                    continue;
                }
                if (!shouldHear.test(playerRef)) {
                    continue;
                }
                final PlayerRef playerRefComponent = componentAccessor.getComponent(playerRef, PlayerRef.getComponentType());
                assert playerRefComponent != null;
                playerRefComponent.getPacketHandler().write(packet);
            }
        }
    }
    
    public static void playSoundEvent3d(@Nullable final Ref<EntityStore> sourceRef, final int soundEventIndex, @Nonnull final Vector3d pos, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        playSoundEvent3d(sourceRef, soundEventIndex, pos.getX(), pos.getY(), pos.getZ(), componentAccessor);
    }
    
    public static void playSoundEvent3d(@Nullable final Ref<EntityStore> sourceRef, final int soundEventIndex, final double x, final double y, final double z, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        playSoundEvent3d(sourceRef, soundEventIndex, x, y, z, false, componentAccessor);
    }
    
    public static void playSoundEvent3d(@Nullable final Ref<EntityStore> sourceRef, final int soundEventIndex, @Nonnull final Vector3d position, final boolean ignoreSource, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        playSoundEvent3d(sourceRef, soundEventIndex, position.getX(), position.getY(), position.getZ(), ignoreSource, componentAccessor);
    }
    
    public static void playSoundEvent3d(@Nullable final Ref<EntityStore> sourceRef, final int soundEventIndex, final double x, final double y, final double z, final boolean ignoreSource, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        final Entity sourceEntity = (sourceRef != null) ? EntityUtils.getEntity(sourceRef, componentAccessor) : null;
        playSoundEvent3d(soundEventIndex, x, y, z, playerRef -> {
            if (sourceEntity == null) {
                return true;
            }
            else if (ignoreSource && sourceRef.equals(playerRef)) {
                return false;
            }
            else {
                return !sourceEntity.isHiddenFromLivingEntity(sourceRef, playerRef, componentAccessor);
            }
        }, componentAccessor);
    }
    
    public static void playSoundEvent3d(final int soundEventIndex, final double x, final double y, final double z, @Nonnull final Predicate<Ref<EntityStore>> shouldHear, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        playSoundEvent3d(soundEventIndex, SoundCategory.SFX, x, y, z, shouldHear, componentAccessor);
    }
    
    public static void playSoundEvent3dToPlayer(@Nullable final Ref<EntityStore> playerRef, final int soundEventIndex, @Nonnull final SoundCategory soundCategory, final double x, final double y, final double z, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        playSoundEvent3dToPlayer(playerRef, soundEventIndex, soundCategory, x, y, z, 1.0f, 1.0f, componentAccessor);
    }
    
    public static void playSoundEvent3dToPlayer(@Nullable final Ref<EntityStore> playerRef, final int soundEventIndex, @Nonnull final SoundCategory soundCategory, final double x, final double y, final double z, final float volumeModifier, final float pitchModifier, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        if (playerRef == null || soundEventIndex == 0) {
            return;
        }
        final SoundEvent soundEventAsset = SoundEvent.getAssetMap().getAsset(soundEventIndex);
        if (soundEventAsset == null) {
            return;
        }
        final float maxDistance = soundEventAsset.getMaxDistance();
        final TransformComponent transformComponent = componentAccessor.getComponent(playerRef, TransformComponent.getComponentType());
        assert transformComponent != null;
        if (transformComponent.getPosition().distanceSquaredTo(x, y, z) <= maxDistance * maxDistance) {
            final PlayerRef playerRefComponent = componentAccessor.getComponent(playerRef, PlayerRef.getComponentType());
            assert playerRefComponent != null;
            playerRefComponent.getPacketHandler().write(new PlaySoundEvent3D(soundEventIndex, soundCategory, new Position(x, y, z), volumeModifier, pitchModifier));
        }
    }
    
    public static void playSoundEvent3dToPlayer(@Nullable final Ref<EntityStore> playerRef, final int soundEventIndex, @Nonnull final SoundCategory soundCategory, @Nonnull final Vector3d position, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        playSoundEvent3dToPlayer(playerRef, soundEventIndex, soundCategory, position.x, position.y, position.z, componentAccessor);
    }
}
