Implement battle music

Can play mid and wav files in the generated config directory
This commit is contained in:
Stephen Seo 2018-09-14 14:14:10 +09:00
parent 5f70253955
commit b1a3eb9880
8 changed files with 448 additions and 4 deletions

View file

@ -0,0 +1,246 @@
package com.seodisparate.TurnBasedMinecraft.client;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.util.ArrayList;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.Sequencer;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import org.apache.logging.log4j.Logger;
import com.seodisparate.TurnBasedMinecraft.common.TurnBasedMinecraftMod;
import net.minecraft.client.Minecraft;
public class BattleMusic
{
private Logger logger;
private ArrayList<File> battleMusic;
private ArrayList<File> sillyMusic;
private boolean initialized;
private File nextBattle;
private File nextSilly;
private Sequencer sequencer;
private Clip clip;
private boolean playingIsSilly;
public BattleMusic(Logger logger)
{
initialized = false;
this.logger = logger;
battleMusic = new ArrayList<File>();
sillyMusic = new ArrayList<File>();
try {
sequencer = MidiSystem.getSequencer();
sequencer.open();
} catch (Exception e)
{
logger.error("Failed to load midi sequencer");
return;
}
try
{
clip = AudioSystem.getClip();
} catch(LineUnavailableException e)
{
logger.error("Failed to load clip (for wav)");
return;
}
File battleMusicFolder = new File(TurnBasedMinecraftMod.MUSIC_BATTLE);
File sillyMusicFolder = new File(TurnBasedMinecraftMod.MUSIC_SILLY);
if(!battleMusicFolder.exists())
{
if(!battleMusicFolder.mkdirs())
{
logger.error("Failed to create " + TurnBasedMinecraftMod.MUSIC_BATTLE);
return;
}
}
if(!sillyMusicFolder.exists())
{
if(!sillyMusicFolder.mkdirs())
{
logger.error("Failed to create " + TurnBasedMinecraftMod.MUSIC_SILLY);
return;
}
}
File[] battleFiles = battleMusicFolder.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name)
{
int extIndex = name.lastIndexOf(".");
if(extIndex == -1)
{
return false;
}
String ext = name.substring(extIndex + 1).toLowerCase();
if(ext.equals("mid") || ext.equals("wav"))
{
return true;
}
return false;
}
});
for(File f : battleFiles)
{
battleMusic.add(f);
}
File[] sillyFiles = sillyMusicFolder.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name)
{
int extIndex = name.lastIndexOf(".");
if(extIndex == -1)
{
return false;
}
String ext = name.substring(extIndex + 1).toLowerCase();
if(ext.equals("mid") || ext.equals("wav"))
{
return true;
}
return false;
}
});
for(File f : sillyFiles)
{
sillyMusic.add(f);
}
pickNextBattle();
pickNextSilly();
initialized = true;
}
private void pickNextBattle()
{
if(!initialized || battleMusic.isEmpty())
{
nextBattle = null;
return;
}
nextBattle = battleMusic.get((int)(Math.random() * battleMusic.size()));
}
private void pickNextSilly()
{
if(!initialized || sillyMusic.isEmpty())
{
nextSilly = null;
return;
}
nextSilly = sillyMusic.get((int)(Math.random() * sillyMusic.size()));
}
public void playBattle()
{
if(!initialized)
{
return;
}
play(nextBattle);
pickNextBattle();
playingIsSilly = false;
}
public void playSilly()
{
if(!initialized)
{
return;
}
play(nextSilly);
pickNextSilly();
playingIsSilly = true;
}
private void play(File next)
{
if(initialized && next != null)
{
Minecraft.getMinecraft().addScheduledTask(() -> {
Minecraft.getMinecraft().getSoundHandler().pauseSounds();
});
String suffix = next.getName().substring(next.getName().length() - 3).toLowerCase();
if(suffix.equals("mid"))
{
if(sequencer.isRunning())
{
sequencer.stop();
}
if(clip.isActive())
{
clip.stop();
clip.close();
}
try {
sequencer.setSequence(new BufferedInputStream(new FileInputStream(next)));
} catch (Exception e)
{
logger.error("Failed to play battle music (midi)");
return;
}
sequencer.setLoopCount(Sequencer.LOOP_CONTINUOUSLY);
sequencer.start();
}
else if(suffix.equals("wav"))
{
if(sequencer.isRunning())
{
sequencer.stop();
}
if(clip.isActive())
{
clip.stop();
clip.close();
}
try
{
clip.open(AudioSystem.getAudioInputStream(next));
} catch(Exception e)
{
logger.error("Failed to load battle music (wav)");
return;
}
clip.loop(Clip.LOOP_CONTINUOUSLY);
clip.start();
}
}
}
public void stopMusic()
{
if(sequencer.isRunning())
{
sequencer.stop();
}
if(clip.isActive())
{
clip.stop();
clip.close();
}
}
public boolean isPlayingSilly()
{
return playingIsSilly;
}
public boolean isPlaying()
{
return sequencer.isRunning() || clip.isActive();
}
}

View file

@ -1,6 +1,9 @@
package com.seodisparate.TurnBasedMinecraft.client;
import org.apache.logging.log4j.Logger;
import com.seodisparate.TurnBasedMinecraft.common.CommonProxy;
import com.seodisparate.TurnBasedMinecraft.common.Config;
import com.seodisparate.TurnBasedMinecraft.common.TurnBasedMinecraftMod;
import net.minecraft.client.Minecraft;
@ -8,11 +11,15 @@ import net.minecraft.client.Minecraft;
public class ClientProxy extends CommonProxy
{
private BattleGui battleGui;
private BattleMusic battleMusic;
private Logger logger;
private Config config;
public ClientProxy()
{
super();
battleGui = new BattleGui();
battleMusic = null; // will be initialized in postInit()
}
@Override
@ -60,4 +67,78 @@ public class ClientProxy extends CommonProxy
Minecraft.getMinecraft().setIngameFocus();
});
}
@Override
public void postInit()
{
battleMusic = new BattleMusic(logger);
}
@Override
public void setLogger(Logger logger)
{
this.logger = logger;
}
@Override
public void playBattleMusic()
{
battleMusic.playBattle();
}
@Override
public void playSillyMusic()
{
battleMusic.playSilly();
}
@Override
public void stopMusic()
{
battleMusic.stopMusic();
}
/**
* Sets what music to play based on type and loaded Config
*/
@Override
public void typeEnteredBattle(String type)
{
if(type == null || type.isEmpty() || config.isBattleMusicType(type))
{
if(battleMusic.isPlaying())
{
if(battleMusic.isPlayingSilly())
{
stopMusic();
playBattleMusic();
}
}
else
{
playBattleMusic();
}
}
else if(config.isSillyMusicType(type))
{
if(battleMusic.isPlaying())
{
if(!battleMusic.isPlayingSilly())
{
stopMusic();
playSillyMusic();
}
}
else
{
playSillyMusic();
}
}
}
@Override
public void setConfig(Config config)
{
this.config = config;
}
}

View file

@ -165,13 +165,27 @@ public class Battle
}
for(Combatant c : this.sideA.values())
{
if(c.entityInfo != null)
{
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, c.entity.getEntityId(), 0, id, c.entityInfo.category);
}
else
{
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, c.entity.getEntityId(), 0, id);
}
}
for(Combatant c : this.sideB.values())
{
if(c.entityInfo != null)
{
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, c.entity.getEntityId(), 0, id, c.entityInfo.category);
}
else
{
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, c.entity.getEntityId(), 0, id);
}
}
lastInstant = System.nanoTime();
state = State.DECISION;
@ -232,7 +246,14 @@ public class Battle
undecidedCount.incrementAndGet();
}
}
if(newCombatant.entityInfo != null)
{
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, newCombatant.entity.getEntityId(), 0, id, newCombatant.entityInfo.category);
}
else
{
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, newCombatant.entity.getEntityId(), 0, id);
}
notifyPlayersBattleInfo();
}
@ -256,7 +277,14 @@ public class Battle
undecidedCount.incrementAndGet();
}
}
if(newCombatant.entityInfo != null)
{
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, newCombatant.entity.getEntityId(), 0, id, newCombatant.entityInfo.category);
}
else
{
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, newCombatant.entity.getEntityId(), 0, id);
}
notifyPlayersBattleInfo();
}

View file

@ -1,5 +1,7 @@
package com.seodisparate.TurnBasedMinecraft.common;
import org.apache.logging.log4j.Logger;
public class CommonProxy
{
public void setBattleGuiTime(int timeRemaining) {}
@ -13,4 +15,18 @@ public class CommonProxy
public void battleGuiTurnEnd() {}
public void battleEnded() {}
public void postInit() {}
public void setLogger(Logger logger) {}
public void playBattleMusic() {}
public void playSillyMusic() {}
public void stopMusic() {}
public void typeEnteredBattle(String type) {}
public void setConfig(Config config) {}
}

View file

@ -35,12 +35,16 @@ public class Config
private int fleeBadProbability = 40;
private int minimumHitPercentage = 1;
private int maxInBattle = 8;
private Set<String> musicBattleTypes;
private Set<String> musicSillyTypes;
public Config(Logger logger)
{
entityInfoMap = new HashMap<String, EntityInfo>();
ignoreBattleTypes = new HashSet<String>();
this.logger = logger;
musicBattleTypes = new HashSet<String>();
musicSillyTypes = new HashSet<String>();
int internalVersion = 0;
try
@ -170,6 +174,38 @@ public class Config
}
} while(!(xmlReader.isEndElement() && xmlReader.getLocalName().equals("IgnoreBattleTypes")));
}
else if(xmlReader.getLocalName().equals("BattleMusic"))
{
do
{
xmlReader.next();
if(xmlReader.isStartElement())
{
if(xmlReader.getLocalName().equals("Normal"))
{
do
{
xmlReader.next();
if(xmlReader.isStartElement())
{
musicBattleTypes.add(xmlReader.getLocalName().toLowerCase());
}
} while(!(xmlReader.isEndElement() && xmlReader.getLocalName().equals("Normal")));
}
else if(xmlReader.getLocalName().equals("Silly"))
{
do
{
xmlReader.next();
if(xmlReader.isStartElement())
{
musicSillyTypes.add(xmlReader.getLocalName().toLowerCase());
}
} while(!(xmlReader.isEndElement() && xmlReader.getLocalName().equals("Silly")));
}
}
} while(!(xmlReader.isEndElement() && xmlReader.getLocalName().equals("BattleMusic")));
}
else if(xmlReader.getLocalName().equals("PlayerStats"))
{
do
@ -454,4 +490,14 @@ public class Config
{
return maxInBattle;
}
public boolean isBattleMusicType(String type)
{
return musicBattleTypes.contains(type.toLowerCase());
}
public boolean isSillyMusicType(String type)
{
return musicSillyTypes.contains(type.toLowerCase());
}
}

View file

@ -32,6 +32,9 @@ public class TurnBasedMinecraftMod
public static final String CONFIG_DIRECTORY = "config/TurnBasedMinecraft/";
public static final String CONFIG_FILE_PATH = CONFIG_DIRECTORY + CONFIG_FILENAME;
public static final String CONFIG_INTERNAL_PATH = "/assets/TurnBasedMinecraft/" + CONFIG_FILENAME;
public static final String MUSIC_ROOT = CONFIG_DIRECTORY + "Music/";
public static final String MUSIC_SILLY = MUSIC_ROOT + "silly/";
public static final String MUSIC_BATTLE = MUSIC_ROOT + "battle/";
private static int CONFIG_FILE_VERSION = 0;
@ -61,6 +64,7 @@ public class TurnBasedMinecraftMod
{
currentBattle = null;
battleManager = null;
commonProxy.setLogger(logger);
// register packets
NWINSTANCE.registerMessage(
@ -93,6 +97,8 @@ public class TurnBasedMinecraftMod
public void postInit(FMLPostInitializationEvent event)
{
config = new Config(logger);
commonProxy.setConfig(config);
commonProxy.postInit();
logger.debug("POSTINIT");
}

View file

@ -233,6 +233,14 @@ public class PacketBattleMessage implements IMessage
TurnBasedMinecraftMod.currentBattle = new Battle(message.amount, null, null, false);
}
TurnBasedMinecraftMod.commonProxy.setBattleGuiAsGui();
if(message.custom.isEmpty())
{
TurnBasedMinecraftMod.commonProxy.typeEnteredBattle(null);
}
else
{
TurnBasedMinecraftMod.commonProxy.typeEnteredBattle(message.custom);
}
break;
case FLEE:
if(message.amount != 0)
@ -254,6 +262,7 @@ public class PacketBattleMessage implements IMessage
Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString(
"Battle has ended!"));
TurnBasedMinecraftMod.commonProxy.battleEnded();
TurnBasedMinecraftMod.commonProxy.stopMusic();
break;
case ATTACK:
Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString(

View file

@ -9,6 +9,18 @@
<passive></passive>
<boss></boss>
</IgnoreBattleTypes>
<!-- BattleMusic determines what categories a type will play music for. -->
<!-- Music is placed in "config/TurnBasedMinecraft/Music/battle/" and "config/TurnBasedMinecraft/Music/silly/" -->
<BattleMusic>
<Normal>
<monster></monster>
<animal></animal>
<boss></boss>
</Normal>
<Silly>
<passive></passive>
</Silly>
</BattleMusic>
<PlayerStats>
<Speed>50</Speed>
<HasteSpeed>80</HasteSpeed> <!-- Speed used if the player entity has "speed" or "haste" effects -->