MusicManager.java

net.minecraft.client.sounds.MusicManager

信息

  • 全限定名:net.minecraft.client.sounds.MusicManager
  • 类型:public class
  • 包:net.minecraft.client.sounds
  • 源码路径:src/main/java/net/minecraft/client/sounds/MusicManager.java
  • 起始行号:L20
  • 职责:

    TODO

字段/常量

  • STARTING_DELAY

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L21
    • 说明:

      TODO

  • random

    • 类型: RandomSource
    • 修饰符: private final
    • 源码定位: L22
    • 说明:

      TODO

  • minecraft

    • 类型: Minecraft
    • 修饰符: private final
    • 源码定位: L23
    • 说明:

      TODO

  • currentMusic

    • 类型: SoundInstance
    • 修饰符: private
    • 源码定位: L24
    • 说明:

      TODO

  • gameMusicFrequency

    • 类型: MusicManager.MusicFrequency
    • 修饰符: private
    • 源码定位: L25
    • 说明:

      TODO

  • currentGain

    • 类型: float
    • 修饰符: private
    • 源码定位: L26
    • 说明:

      TODO

  • nextSongDelay

    • 类型: int
    • 修饰符: private
    • 源码定位: L27
    • 说明:

      TODO

  • toastShown

    • 类型: boolean
    • 修饰符: private
    • 源码定位: L28
    • 说明:

      TODO

内部类/嵌套类型

  • net.minecraft.client.sounds.MusicManager.MusicFrequency
    • 类型: enum
    • 修饰符: public static
    • 源码定位: L159
    • 说明:

      TODO

构造器

public MusicManager(Minecraft minecraft) @ L30

  • 构造器名:MusicManager
  • 源码定位:L30
  • 修饰符:public

参数:

  • minecraft: Minecraft

说明:

TODO

方法

下面的方法块按源码顺序生成。

public void tick() @ L35

  • 方法名:tick
  • 源码定位:L35
  • 返回类型:void
  • 修饰符:public

参数:

说明:

TODO

private static boolean canReplace(Music music, SoundInstance currentMusic) @ L67

  • 方法名:canReplace
  • 源码定位:L67
  • 返回类型:boolean
  • 修饰符:private static

参数:

  • music: Music
  • currentMusic: SoundInstance

说明:

TODO

public void startPlaying(Music music) @ L71

  • 方法名:startPlaying
  • 源码定位:L71
  • 返回类型:void
  • 修饰符:public

参数:

  • music: Music

说明:

TODO

public void showNowPlayingToastIfNeeded() @ L86

  • 方法名:showNowPlayingToastIfNeeded
  • 源码定位:L86
  • 返回类型:void
  • 修饰符:public

参数:

说明:

TODO

public void stopPlaying(Music music) @ L93

  • 方法名:stopPlaying
  • 源码定位:L93
  • 返回类型:void
  • 修饰符:public

参数:

  • music: Music

说明:

TODO

public void stopPlaying() @ L99

  • 方法名:stopPlaying
  • 源码定位:L99
  • 返回类型:void
  • 修饰符:public

参数:

说明:

TODO

private boolean fadePlaying(float volume) @ L109

  • 方法名:fadePlaying
  • 源码定位:L109
  • 返回类型:boolean
  • 修饰符:private

参数:

  • volume: float

说明:

TODO

public boolean isPlayingMusic(Music music) @ L138

  • 方法名:isPlayingMusic
  • 源码定位:L138
  • 返回类型:boolean
  • 修饰符:public

参数:

  • music: Music

说明:

TODO

public String getCurrentMusicTranslationKey() @ L142

  • 方法名:getCurrentMusicTranslationKey
  • 源码定位:L142
  • 返回类型:String
  • 修饰符:public

参数:

说明:

TODO

public void setMinutesBetweenSongs(MusicManager.MusicFrequency musicFrequency) @ L153

  • 方法名:setMinutesBetweenSongs
  • 源码定位:L153
  • 返回类型:void
  • 修饰符:public

参数:

  • musicFrequency: MusicManager.MusicFrequency

说明:

TODO

代码

@OnlyIn(Dist.CLIENT)
public class MusicManager {
    private static final int STARTING_DELAY = 100;
    private final RandomSource random = RandomSource.create();
    private final Minecraft minecraft;
    private @Nullable SoundInstance currentMusic;
    private MusicManager.MusicFrequency gameMusicFrequency;
    private float currentGain = 1.0F;
    private int nextSongDelay = 100;
    private boolean toastShown = false;
 
    public MusicManager(Minecraft minecraft) {
        this.minecraft = minecraft;
        this.gameMusicFrequency = minecraft.options.musicFrequency().get();
    }
 
    public void tick() {
        float volume = this.minecraft.getMusicVolume();
        if (this.currentMusic != null && this.currentGain != volume) {
            boolean stillPlaying = this.fadePlaying(volume);
            if (!stillPlaying) {
                return;
            }
        }
 
        Music music = this.minecraft.getSituationalMusic();
        if (music == null) {
            this.nextSongDelay = Math.max(this.nextSongDelay, 100);
        } else {
            if (this.currentMusic != null) {
                if (canReplace(music, this.currentMusic)) {
                    this.minecraft.getSoundManager().stop(this.currentMusic);
                    this.nextSongDelay = Mth.nextInt(this.random, 0, music.minDelay() / 2);
                }
 
                if (!this.minecraft.getSoundManager().isActive(this.currentMusic)) {
                    this.currentMusic = null;
                    this.nextSongDelay = Math.min(this.nextSongDelay, this.gameMusicFrequency.getNextSongDelay(music, this.random));
                }
            }
 
            this.nextSongDelay = Math.min(this.nextSongDelay, this.gameMusicFrequency.getNextSongDelay(music, this.random));
            if (this.currentMusic == null && this.nextSongDelay-- <= 0) {
                this.startPlaying(music);
            }
        }
    }
 
    private static boolean canReplace(Music music, SoundInstance currentMusic) {
        return music.replaceCurrentMusic() && !music.sound().value().location().equals(currentMusic.getIdentifier());
    }
 
    public void startPlaying(Music music) {
        SoundEvent soundEvent = music.sound().value();
        this.currentMusic = SimpleSoundInstance.forMusic(soundEvent);
        switch (this.minecraft.getSoundManager().play(this.currentMusic)) {
            case STARTED:
                this.minecraft.getToastManager().showNowPlayingToast();
                this.toastShown = true;
                break;
            case STARTED_SILENTLY:
                this.toastShown = false;
        }
 
        this.nextSongDelay = Integer.MAX_VALUE;
    }
 
    public void showNowPlayingToastIfNeeded() {
        if (!this.toastShown) {
            this.minecraft.getToastManager().showNowPlayingToast();
            this.toastShown = true;
        }
    }
 
    public void stopPlaying(Music music) {
        if (this.isPlayingMusic(music)) {
            this.stopPlaying();
        }
    }
 
    public void stopPlaying() {
        if (this.currentMusic != null) {
            this.minecraft.getSoundManager().stop(this.currentMusic);
            this.currentMusic = null;
            this.minecraft.getToastManager().hideNowPlayingToast();
        }
 
        this.nextSongDelay += 100;
    }
 
    private boolean fadePlaying(float volume) {
        if (this.currentMusic == null) {
            return false;
        } else if (this.currentGain == volume) {
            return true;
        } else {
            if (this.currentGain < volume) {
                this.currentGain = this.currentGain + Mth.clamp(this.currentGain, 5.0E-4F, 0.005F);
                if (this.currentGain > volume) {
                    this.currentGain = volume;
                }
            } else {
                this.currentGain = 0.03F * volume + 0.97F * this.currentGain;
                if (Math.abs(this.currentGain - volume) < 1.0E-4F || this.currentGain < volume) {
                    this.currentGain = volume;
                }
            }
 
            this.currentGain = Mth.clamp(this.currentGain, 0.0F, 1.0F);
            if (this.currentGain <= 1.0E-4F) {
                this.stopPlaying();
                return false;
            } else {
                this.minecraft.getSoundManager().updateCategoryVolume(SoundSource.MUSIC, this.currentGain);
                return true;
            }
        }
    }
 
    public boolean isPlayingMusic(Music music) {
        return this.currentMusic == null ? false : music.sound().value().location().equals(this.currentMusic.getIdentifier());
    }
 
    public @Nullable String getCurrentMusicTranslationKey() {
        if (this.currentMusic != null) {
            Sound sound = this.currentMusic.getSound();
            if (sound != null) {
                return sound.getLocation().toShortLanguageKey();
            }
        }
 
        return null;
    }
 
    public void setMinutesBetweenSongs(MusicManager.MusicFrequency musicFrequency) {
        this.gameMusicFrequency = musicFrequency;
        this.nextSongDelay = this.gameMusicFrequency.getNextSongDelay(this.minecraft.getSituationalMusic(), this.random);
    }
 
    @OnlyIn(Dist.CLIENT)
    public static enum MusicFrequency implements StringRepresentable {
        DEFAULT("DEFAULT", "options.music_frequency.default", 20),
        FREQUENT("FREQUENT", "options.music_frequency.frequent", 10),
        CONSTANT("CONSTANT", "options.music_frequency.constant", 0);
 
        public static final Codec<MusicManager.MusicFrequency> CODEC = StringRepresentable.fromEnum(MusicManager.MusicFrequency::values);
        private final String name;
        private final int maxFrequency;
        private final Component caption;
 
        private MusicFrequency(String name, String translationKey, int maxFrequencyMinutes) {
            this.name = name;
            this.maxFrequency = maxFrequencyMinutes * 1200;
            this.caption = Component.translatable(translationKey);
        }
 
        private int getNextSongDelay(@Nullable Music music, RandomSource random) {
            if (music == null) {
                return this.maxFrequency;
            } else if (this == CONSTANT) {
                return 100;
            } else {
                int minFrequency = Math.min(music.minDelay(), this.maxFrequency);
                int maxFrequency = Math.min(music.maxDelay(), this.maxFrequency);
                return Mth.nextInt(random, minFrequency, maxFrequency);
            }
        }
 
        public Component caption() {
            return this.caption;
        }
 
        @Override
        public String getSerializedName() {
            return this.name;
        }
    }
}

引用的其他类

  • Minecraft

    • 引用位置: 参数/字段
  • SimpleSoundInstance

    • 引用位置: 方法调用
    • 关联成员: SimpleSoundInstance.forMusic()
  • SoundInstance

    • 引用位置: 参数/字段
  • Component

    • 引用位置: 方法调用
    • 关联成员: Component.translatable()
  • Music

    • 引用位置: 参数
  • Mth

    • 引用位置: 方法调用
    • 关联成员: Mth.clamp(), Mth.nextInt()
  • RandomSource

    • 引用位置: 字段/方法调用
    • 关联成员: RandomSource.create()
  • StringRepresentable

    • 引用位置: 方法调用
    • 关联成员: StringRepresentable.fromEnum()