Фоновая музыка в клиенте

Версия Minecraft
1.7.10
215
1
20
Создал кастомное измерение и хотел сделать так, чтобы там играл мой набор музыки.
После некоторых изысканий "сочинил" такой код:

Код:
@SubscribeEvent
 public void goMusic(ClientTickEvent e){
 Minecraft mc = Minecraft.getMinecraft();
 EntityClientPlayerMP p = mc.thePlayer;
 PositionedSoundRecord  Irdorath = PositionedSoundRecord.func_147673_a(new ResourceLocation("minecraft", "records.record_irdorath"));
 if(!(mc.currentScreen instanceof GuiWinGame) && p != null && p.worldObj.provider.dimensionId == RHCommon.hostilianworldID){
 mc.getSoundHandler().playSound(Irdorath);
 }
 }

[font=Monaco, Consolas, Courier, monospace]В целом, код запускает музыку. Только она сразу же многократно множится и превращается в гул, так как тут кое-чего не хватает.[/font]

[font=Monaco, Consolas, Courier, monospace]Вопросы:[/font]
[font=Monaco, Consolas, Courier, monospace]Как определить, играет ли уже музыка?[/font]
[font=Monaco, Consolas, Courier, monospace]Как определить, какая именно музыка играет?[/font]
[font=Monaco, Consolas, Courier, monospace]Как ее остановить?[/font]


[font=Monaco, Consolas, Courier, monospace]Конструкция типа:[/font]

Код:
if(!mc.getSoundHandler().isSoundPlaying(Irdorath)){
...
}
[font=Monaco, Consolas, Courier, monospace][size=small][font=Monaco, Consolas, Courier, monospace]не работает.[/font][/font][/size]
 
Рефлексией
 
У меня знакомый как то делал что-то навроде звукового движка какого то или контроллера, хз. У него набор возможностей крутецкий был. Если тема будет актуальна еще на днях, то дам знать чего там у него было такое
 
LaoTheLizard написал(а):
Как я понял, "private ISound field_147678_c;" - это как раз играющая музыка. И как мне её проверить, если она private?
Access transformers делают публичный доступ к полям и методам. Это получше, чем рефлексия
 
У меня уйдет немало времени, чтобы из данной вами информации извлечь для себя рациональные зерна и вырастить из них требуемый результат. Нет ли у кого готового элегантного и простого решения, которым этот кто-нибудь согласился бы поделиться с общественностью в моем лице?
 
Dahaka написал(а):
LaoTheLizard написал(а):
Как я понял, "private ISound field_147678_c;" - это как раз играющая музыка. И как мне её проверить, если она private?
Access transformers делают публичный доступ к полям и методам. Это получше, чем рефлексия
Поверхностно погуглил, интересная хрень. А как она компилятору говорит, что такое-то поле должно иметь такие-то модификаторы доступа?
 
Компилятор тут не при чем. Дело в том, что форж сам в рантайме на старте игры своими трансформерами пробегает по классам майна и меняет все модификаторы доступа на public. А вот проблему с невозможностью компиляции из-за обращения к приватному полю/методу нужно фиксить вручную. Есть минимум два варианта. Или самому декомпилировать майн и вручную заменить модификаторы доступа на public. Или использовать AT - форж сам соберется с public модификаторами для классов, которые указал в соответствующем конфиг файле.
 
Если второе: из среды то как тестить? На момент компиляции форж еще не обработал классы и не может их подсунуть компилю. Или может?
 
Во время применения fml и forge патчей, скорее всего. И собственно, таким же образом, наверное. Тем более, если они проводят это в рантайме, что мешает сделать это во время сборки.
 
Dahaka написал(а):
Во время применения fml и forge патчей, скорее всего. И собственно, таким же образом, наверное. Тем более, если они проводят это в рантайме, что мешает сделать это во время сборки.
спс
 
Покопавшись в гугле, я нашел исходники глобального французского мода MagicCrusade, откуда и взял готовое решение. Расскажу по порядку, что куда вставил и зачем.

ClientProxy.init():
Код:
    SoundEventRH soundHandler = new SoundEventRH();
     FMLCommonHandler.instance().bus().register(soundHandler);
     MinecraftForge.EVENT_BUS.register(soundHandler);

FMLevents.onPlayerTick(PlayerTickEvent e):
Код:
if (e.player.worldObj.isRemote && e.player.dimension == RHCommon.hostilianworldID){SoundEventRH.update_sound(e.player.worldObj.isDaytime(), e.player.worldObj.rand);}

и, конечно же, SoundEventRH:
Код:
package ru.lao.rha.eventhandlers;


import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import net.minecraft.client.Minecraft;
import net.minecraft.client.audio.ISound;
import net.minecraft.client.audio.PositionedSoundRecord;
import net.minecraft.client.audio.SoundCategory;
import net.minecraft.client.audio.SoundHandler;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.event.sound.PlaySoundEvent17;
import ru.lao.rha.proxies.RHCommon;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;

public class SoundEventRH {
 
 static Minecraft mc = Minecraft.getMinecraft();

 public static final ISound  Irdorath = PositionedSoundRecord.func_147673_a(new ResourceLocation("minecraft", "music.game.hostilian.irdorath"));
 public static final ISound  Lobardshof = PositionedSoundRecord.func_147673_a(new ResourceLocation("minecraft", "music.game.hostilian.lobardshof"));
 public static final ISound  Minental = PositionedSoundRecord.func_147673_a(new ResourceLocation("minecraft", "music.game.hostilian.minental"));
 public static final ISound  Minental2 = PositionedSoundRecord.func_147673_a(new ResourceLocation("minecraft", "music.game.hostilian.minental2"));
 public static final ISound  Neueinselwelt = PositionedSoundRecord.func_147673_a(new ResourceLocation("minecraft", "music.game.hostilian.neueinselwelt"));

 @SubscribeEvent
 @SideOnly(Side.CLIENT)
 public void onSoundPlay(PlaySoundEvent17 event)
 {
 if (mc.thePlayer != null && mc.thePlayer.dimension == RHCommon.hostilianworldID && event.category == SoundCategory.MUSIC)
 if(!event.result.equals(Irdorath) &&
 !event.result.equals(Lobardshof) &&
 !event.result.equals(Minental) &&
 !event.result.equals(Minental2) &&
 !event.result.equals(Neueinselwelt)){
 //System.out.println("Canceling non-hostilian music...");
 event.result = null;
 
 }
 }
 
 @SideOnly(Side.CLIENT)
 public static void update_sound(boolean is_day, Random rand)
 {

 if (System.currentTimeMillis() % (1000 * 60 * 15) < 5000){ // once in 15 minutes
 SoundHandler snd = mc.getSoundHandler();

 if(!snd.isSoundPlaying(Irdorath) && !snd.isSoundPlaying(Lobardshof) &&
 !snd.isSoundPlaying(Minental) && !snd.isSoundPlaying(Minental2) && !snd.isSoundPlaying(Neueinselwelt)
 ){
 //System.out.println("No music in hostilian world. Trying to play some...");
 snd.stopSounds();
 
 int number = rand.nextInt(tracks.size());
 if(number >= tracks.size())number = tracks.size() - 1;
 snd.playSound(tracks.get(number));
 System.out.println("Playing music #" + (number + 1));
 }
 }

 }
}

В оригинале были ошибки, я их вроде исправил, но все баги устранить пока не удалось. Музыка начинает играть раз в 15 минут (если быть точным - она включается в 0, 15, 30 и 45 минут каждого часа). Единственный баг - время от времени включается одновременно две композиции. Код почему-то считает, что музыка еще не играет. Сейчас разбираюсь, почему.
 
Можно было не писать об этом, но мало ли - вдруг кому пригодится: вопрос я таки решил, достаточно слушать эвент PlaySoundEvent17 и вместо стандартной музыки подставлять свою. Двоиться начинает, потому что саундхендлер не определяет, что музыка уже играет. Тут есть два варианта: либо поставить счетчик попыток и разрешать не каждый раз, а можно переписать длительности всех композиций и контролировать, когда они были запущены и когда должны бы кончиться. Последний вариант я и применил, но он имеет слабое место: в одиночном режиме, если поставить на паузу игру, то контроль уже нельзя осуществить через системное время, но лично я на этот баг забил, так как мод ориентирую больше на сетевой режим.
 
Назад
Сверху