Оч странная работа ITickableSound

Версия Minecraft
1.12.2
API
Forge
395
34
90
Дратути

Копался я в коде майна, нашёл такую вещь как ISound, ITickableSound.
Решил использовать её, пока писал опирался на ElytraSound ну, работает, звук постоянно воспроизводится.
Попробовал отключить mc.getSoundHandler().stopSound(sound);, передавал тот же объект что и в playSound
не работает, (mc.getSoundHandler().isSoundPlaying(sound) кстати тоже).
Подумал, прибегнул к костылям по типу sound.stop();, sound.start(); которые переключают donePlaying.
Работает, но только чючють звук полностью не воспроизводится, зато воспроизводится его кусок) в случайные моменты времени.
Хотя в ElytraSound сделано также, там таких проблем нет!
Подумал, решил еще переключать и repeat чтоб не повадно было!
Работает, звук останавливается, но обратно запускать его не получается.
Подумал, погоревал, в порыве отчаянья накалакодил всякого.
AncientPortalSound:
public class AncientPortalSound extends PositionedSound implements ITickableSound, ISoundTRA /[I]<- Мой бесполезный интерфейс[/I]/ {

    private final PlayerDistanceToPortalManager manager;
    private boolean donePlaying = false;
    private final float finalVolume;
    private final Minecraft mc;

    public AncientPortalSound(Type type, PlayerDistanceToPortalManager manager, Minecraft mc) {
        super(type == Type.IMPACT ? InitSounds.PORTAL_IMPACT.SOUND : InitSounds.PORTAL_HEARTBEAT.SOUND, SoundCategory.AMBIENT);
        this.finalVolume = type == Type.IMPACT ? 0.5F : 10.0F;
        this.repeatDelay = type == Type.IMPACT ? 0 : 4;
        this.volume = this.finalVolume;
        this.manager = manager;
        this.repeat = true;
        this.mc = mc;
    }

    @Override
    public boolean isDonePlaying() {
        return donePlaying;
    }

    @Override
    public void update() {
        final int minDistanceToPlaySound = 128;

        if (manager.distanceToPortal < minDistanceToPlaySound) {
            UltraMutableBlockPos blockPos = UltraMutableBlockPos.getBlockPosFromPoll();
            float scale = 1.0F - (manager.distanceToPortal + 16.0F) / minDistanceToPlaySound;
            scale = MathHelper.clamp(scale, 0.0F, 1.0F);

            blockPos.setPos(manager.nearestPortalPos);

            Vec3d vec3d = new Vec3d(blockPos.getX() - mc.player.posX, 0, blockPos.getZ() - mc.player.posZ).normalize();

            blockPos.setPos(mc.player);

            this.setPos(blockPos);
            this.addPos(vec3d.scale(2));

            volume = finalVolume * scale;

            UltraMutableBlockPos.returnBlockPosToPoll(blockPos);
        }
    }

    @Override
    public boolean isStopped() { // Метод моего интерфейса. Зачем? Я не знаю...
        return donePlaying;
    }

    @Override
    public void stop() { // Метод моего интерфейса.
        this.donePlaying = true;
        this.repeat = false;
    }

    private void setPos(UltraMutableBlockPos pos) {
        this.xPosF = pos.getX() + 0.5F;
        this.yPosF = pos.getY() + 0.5F;
        this.zPosF = pos.getZ() + 0.5F;
    }

    private void addPos(Vec3d vec3d) {
        this.xPosF += (float) vec3d.x;
        this.yPosF += (float) vec3d.y;
        this.zPosF += (float) vec3d.z;
    }

    public enum Type {
        HEARTBEAT, IMPACT
    }
}
PlayerDistanceToPortalManager:
public class PlayerDistanceToPortalManager {
    private final Sound portalHeartbeat = new Sound(AncientPortalSound.Type.HEARTBEAT, this);
    private final Sound portalImpact = new Sound(AncientPortalSound.Type.IMPACT, this);

    ...
 
    public void tickEventClientTickEvent(TickEvent.ClientTickEvent e) {
        EntityPlayer player = Minecraft.getMinecraft().player;
        Minecraft mc = Minecraft.getMinecraft();

        if (e.phase != TickEvent.Phase.START || player == null || e.side == Side.SERVER || mc.isGamePaused()) {
            return;
        }

        calculateDistanceToPortal(mc, player);
        updateServerRainTck(mc, player);
        addSound(mc, player);
        setRain(mc, player);
    }

    private void addSound(Minecraft mc, EntityPlayer player) {
        final int minDistanceToPlaySound = 128;

        if (distanceToPortal < minDistanceToPlaySound) {
            portalHeartbeat.init();
            portalImpact.init();
        } else {
            portalHeartbeat.stop();
            portalImpact.stop();
        }
    }

    ...
 
    private static class Sound {
        private final Minecraft mc = Minecraft.getMinecraft();
        private final PlayerDistanceToPortalManager manager;
        private final AncientPortalSound.Type type;
        private AncientPortalSound sound;


        private Sound(AncientPortalSound.Type type, PlayerDistanceToPortalManager manager) {
            this.manager = manager;
            this.sound = null;
            this.type = type;
        }

        public void init() {
            if (sound == null || sound.isStopped()) {
                sound = new AncientPortalSound(type, manager, mc);
                Minecraft.getMinecraft().getSoundHandler().playSound(sound);
            }
        }

        public void stop() {
            if (sound == null) {
                return;
            }
            mc.getSoundHandler().stopSound(sound);
            sound.stop();
            sound = null;
        }
    }
}
Сделал по принципу, если не выключено выключить всеми способами, если не включено создать новый объект и запустить.
Работает, но опять же через одно место, тот что Type.IMPACT выключается, работает потом выключается...
дебагом проверял даже метод update не вызывается хотя с Type.HEARTBEAT все нормально он работает как положено...

Как с этим работать(

Тут 2 варианта либо эту систему звуков писал Гарри Потер либо я тупой.
После всего этого я начинаю верить в первый вариант, слишком много магии на квадратный метр!
 
Последнее редактирование:
Назад
Сверху