diff --git a/_datafiles/world/default/audio.yaml b/_datafiles/world/default/audio.yaml new file mode 100644 index 00000000..d1dc7a20 --- /dev/null +++ b/_datafiles/world/default/audio.yaml @@ -0,0 +1,29 @@ +# Sound that plays when a "change" confirmation/activation occurs +change: + filepath: sound/other/change.mp3 + volume: 80 +# When a target is hit in combat +hit-other: + filepath: sound/combat/hit-other.mp3 +# When receiving a hit in combat +hit-self: + filepath: sound/combat/hit-self.mp3 +# Plays at login screen +intro: + filepath: music/intro.mp3 + volume: 20 +# When Leveling up +levelup: + filepath: sound/other/levelup.mp3 +# When missing a hit in combat +miss: + filepath: sound/combat/miss1.mp3 +# When a purchase is made +purchase: + filepath: sound/other/buy.mp3 +# When someone leaves the room +room-exit: + filepath: sound/movement/room-exit.mp3 +# When someone enters the room +room-enter: + filepath: sound/movement/room-enter.mp3 \ No newline at end of file diff --git a/_datafiles/world/empty/audio.yaml b/_datafiles/world/empty/audio.yaml new file mode 100644 index 00000000..d1dc7a20 --- /dev/null +++ b/_datafiles/world/empty/audio.yaml @@ -0,0 +1,29 @@ +# Sound that plays when a "change" confirmation/activation occurs +change: + filepath: sound/other/change.mp3 + volume: 80 +# When a target is hit in combat +hit-other: + filepath: sound/combat/hit-other.mp3 +# When receiving a hit in combat +hit-self: + filepath: sound/combat/hit-self.mp3 +# Plays at login screen +intro: + filepath: music/intro.mp3 + volume: 20 +# When Leveling up +levelup: + filepath: sound/other/levelup.mp3 +# When missing a hit in combat +miss: + filepath: sound/combat/miss1.mp3 +# When a purchase is made +purchase: + filepath: sound/other/buy.mp3 +# When someone leaves the room +room-exit: + filepath: sound/movement/room-exit.mp3 +# When someone enters the room +room-enter: + filepath: sound/movement/room-enter.mp3 \ No newline at end of file diff --git a/internal/audio/audio.go b/internal/audio/audio.go new file mode 100644 index 00000000..1c900047 --- /dev/null +++ b/internal/audio/audio.go @@ -0,0 +1,48 @@ +package audio + +import ( + "log/slog" + "os" + "time" + + "github.com/pkg/errors" + "github.com/volte6/gomud/internal/configs" + "gopkg.in/yaml.v2" +) + +type AudioConfig struct { + FilePath string `yaml:"filepath,omitempty"` + Volume int `yaml:"volume,omitempty"` +} + +var ( + audioLookup = map[string]AudioConfig{} +) + +func GetFile(identifier string) AudioConfig { + if f, ok := audioLookup[identifier]; ok { + return f + } + return AudioConfig{} +} + +func LoadAudioConfig() { + + start := time.Now() + + path := string(configs.GetConfig().FolderDataFiles) + `/audio.yaml` + + bytes, err := os.ReadFile(path) + if err != nil { + panic(errors.Wrap(err, `filepath: `+path)) + } + + clear(audioLookup) + + err = yaml.Unmarshal(bytes, &audioLookup) + if err != nil { + panic(errors.Wrap(err, `filepath: `+path)) + } + + slog.Info("...LoadAudioConfig()", "loadedCount", len(audioLookup), "Time Taken", time.Since(start)) +} diff --git a/internal/combat/combat.go b/internal/combat/combat.go index e2d992b2..7819c0c0 100644 --- a/internal/combat/combat.go +++ b/internal/combat/combat.go @@ -43,9 +43,9 @@ func AttackPlayerVsMob(user *users.UserRecord, mob *mobs.Mob) AttackResult { mob.Character.TrackPlayerDamage(user.UserId, attackResult.DamageToTarget) if attackResult.Hit { - user.PlaySound(`sound/combat/hit-other.mp3`, `combat`) + user.PlaySound(`hit-other`, `combat`) } else { - user.PlaySound(`sound/combat/miss1.mp3`, `combat`) + user.PlaySound(`miss`, `combat`) } return attackResult @@ -67,10 +67,10 @@ func AttackPlayerVsPlayer(userAtk *users.UserRecord, userDef *users.UserRecord) } if attackResult.Hit { - userAtk.PlaySound(`sound/combat/hit-other.mp3`, `combat`) - userDef.PlaySound(`sound/combat/hit-self.mp3`, `combat`) + userAtk.PlaySound(`hit-other`, `combat`) + userDef.PlaySound(`hit-self`, `combat`) } else { - userAtk.PlaySound(`sound/combat/miss1.mp3`, `combat`) + userAtk.PlaySound(`miss`, `combat`) } return attackResult @@ -89,7 +89,7 @@ func AttackMobVsPlayer(mob *mobs.Mob, user *users.UserRecord) AttackResult { } if attackResult.Hit { - user.PlaySound(`sound/combat/hit-self.mp3`, `combat`) + user.PlaySound(`hit-self`, `combat`) } return attackResult diff --git a/internal/mobcommands/go.go b/internal/mobcommands/go.go index 2e7239f8..218c8c89 100644 --- a/internal/mobcommands/go.go +++ b/internal/mobcommands/go.go @@ -138,8 +138,8 @@ func Go(rest string, mob *mobs.Mob, room *rooms.Room) (bool, error) { destRoom.SendTextToExits(`You hear someone moving around.`, true, room.GetPlayers(rooms.FindAll)...) - room.PlaySound(`sound/movement/room-exit.mp3`, `movement`, 100) - destRoom.PlaySound(`sound/movement/room-enter.mp3`, `movement`, 100) + room.PlaySound(`room-exit`, `movement`) + destRoom.PlaySound(`room-enter`, `movement`) return true, nil } diff --git a/internal/rooms/rooms.go b/internal/rooms/rooms.go index a273bec4..04caceaf 100644 --- a/internal/rooms/rooms.go +++ b/internal/rooms/rooms.go @@ -8,6 +8,7 @@ import ( "strings" "time" + "github.com/volte6/gomud/internal/audio" "github.com/volte6/gomud/internal/buffs" "github.com/volte6/gomud/internal/configs" "github.com/volte6/gomud/internal/events" @@ -248,12 +249,14 @@ func (r *Room) SendText(txt string, excludeUserIds ...int) { } -func (r *Room) PlaySound(soundFile string, category string, volume int, excludeUserIds ...int) { +func (r *Room) PlaySound(soundId string, category string, excludeUserIds ...int) { - if volume < 1 { - volume = 1 - } else if volume > 100 { - volume = 100 + volume := 100 + if soundConfig := audio.GetFile(soundId); soundConfig.FilePath != `` { + soundId = soundConfig.FilePath + if soundConfig.Volume > 0 && soundConfig.Volume <= 100 { + volume = soundConfig.Volume + } } for _, userId := range r.players { @@ -277,7 +280,7 @@ func (r *Room) PlaySound(soundFile string, category string, volume int, excludeU events.AddToQueue(events.MSP{ UserId: userId, SoundType: `SOUND`, - SoundFile: soundFile, + SoundFile: soundId, Volume: volume, Category: category, }) diff --git a/internal/usercommands/buy.go b/internal/usercommands/buy.go index bac46efa..b3db7456 100644 --- a/internal/usercommands/buy.go +++ b/internal/usercommands/buy.go @@ -332,7 +332,7 @@ func tryPurchase(request string, user *users.UserRecord, room *rooms.Room, shopM // Give them the item newItm := items.New(matchedShopItem.ItemId) user.Character.StoreItem(newItm) - user.PlaySound(`sound/other/buy.mp3`, `other`) + user.PlaySound(`purchase`, `other`) iSpec := newItm.GetSpec() if iSpec.QuestToken != `` { diff --git a/internal/usercommands/go.go b/internal/usercommands/go.go index a01fdc4d..4cb7cf82 100644 --- a/internal/usercommands/go.go +++ b/internal/usercommands/go.go @@ -321,8 +321,8 @@ func Go(rest string, user *users.UserRecord, room *rooms.Room) (bool, error) { scripting.TryRoomScriptEvent(`onEnter`, user.UserId, destRoom.RoomId) - room.PlaySound(`sound/movement/room-exit.mp3`, `movement`, user.UserId) - destRoom.PlaySound(`sound/movement/room-enter.mp3`, `movement`, user.UserId) + room.PlaySound(`room-exit`, `movement`, user.UserId) + destRoom.PlaySound(`room-enter`, `movement`, user.UserId) } } diff --git a/internal/usercommands/use.go b/internal/usercommands/use.go index 1c664853..bed6ace4 100644 --- a/internal/usercommands/use.go +++ b/internal/usercommands/use.go @@ -47,7 +47,7 @@ func Use(rest string, user *users.UserRecord, room *rooms.Room) (bool, error) { container.AddItem(newItem) room.Containers[containerName] = container - room.PlaySound(`sound/other/change.mp3`, `other`, 100) + room.PlaySound(`change`, `other`) user.SendText(``) user.SendText(fmt.Sprintf(`The %s produces a %s!`, containerName, newItem.DisplayName())) diff --git a/internal/users/userrecord.go b/internal/users/userrecord.go index b9eadd4f..c5edae8c 100644 --- a/internal/users/userrecord.go +++ b/internal/users/userrecord.go @@ -9,6 +9,7 @@ import ( "strings" "time" + "github.com/volte6/gomud/internal/audio" "github.com/volte6/gomud/internal/buffs" "github.com/volte6/gomud/internal/characters" "github.com/volte6/gomud/internal/configs" @@ -145,33 +146,39 @@ func (u *UserRecord) GrantXP(amt int, source string) { } -func (u *UserRecord) PlayMusic(musicFile string) { +func (u *UserRecord) PlayMusic(musicFileOrId string) { + + v := 100 + if soundConfig := audio.GetFile(musicFileOrId); soundConfig.FilePath != `` { + musicFileOrId = soundConfig.FilePath + if soundConfig.Volume > 0 && soundConfig.Volume <= 100 { + v = soundConfig.Volume + } + } events.AddToQueue(events.MSP{ UserId: u.UserId, SoundType: `MUSIC`, - SoundFile: musicFile, - Volume: 100, + SoundFile: musicFileOrId, + Volume: v, }) } -func (u *UserRecord) PlaySound(soundFile string, category string, volume ...int) { +func (u *UserRecord) PlaySound(soundId string, category string) { v := 100 - if len(volume) > 0 { - v = volume[0] - if v < 1 { - v = 1 - } else if v > 100 { - v = 100 + if soundConfig := audio.GetFile(soundId); soundConfig.FilePath != `` { + soundId = soundConfig.FilePath + if soundConfig.Volume > 0 && soundConfig.Volume <= 100 { + v = soundConfig.Volume } } events.AddToQueue(events.MSP{ UserId: u.UserId, SoundType: `SOUND`, - SoundFile: soundFile, + SoundFile: soundId, Volume: v, Category: category, }) diff --git a/main.go b/main.go index e7d48c7a..92313d35 100644 --- a/main.go +++ b/main.go @@ -19,6 +19,7 @@ import ( "github.com/gorilla/websocket" "github.com/natefinch/lumberjack" + "github.com/volte6/gomud/internal/audio" "github.com/volte6/gomud/internal/buffs" "github.com/volte6/gomud/internal/characters" "github.com/volte6/gomud/internal/colorpatterns" @@ -327,10 +328,16 @@ func handleTelnetConnection(connDetails *connections.ConnectionDetails, wg *sync // The default behavior is to just send a welcome screen first inputhandlers.LoginInputHandler(clientInput, sharedState) - connections.SendTo( - term.MspCommand.BytesWithPayload([]byte("!!MUSIC(music/intro.mp3 V=20 L=-1 C=1)")), - clientInput.ConnectionId, - ) + if audioConfig := audio.GetFile(`intro`); audioConfig.FilePath != `` { + v := 100 + if audioConfig.Volume > 0 && audioConfig.Volume <= 100 { + v = audioConfig.Volume + } + connections.SendTo( + term.MspCommand.BytesWithPayload([]byte("!!MUSIC("+audioConfig.FilePath+" V="+strconv.Itoa(v)+" L=-1 C=1)")), + clientInput.ConnectionId, + ) + } var userObject *users.UserRecord var sug suggestions.Suggestions @@ -578,10 +585,16 @@ func HandleWebSocketConnection(conn *websocket.Conn) { clientInput.ConnectionId, ) - connections.SendTo( - []byte("!!MUSIC(music/intro.mp3 V=20 L=-1 C=1)"), - clientInput.ConnectionId, - ) + if audioConfig := audio.GetFile(`intro`); audioConfig.FilePath != `` { + v := 100 + if audioConfig.Volume > 0 && audioConfig.Volume <= 100 { + v = audioConfig.Volume + } + connections.SendTo( + []byte("!!MUSIC("+audioConfig.FilePath+" V="+strconv.Itoa(v)+" L=-1 C=1)"), + clientInput.ConnectionId, + ) + } for { _, message, err := conn.ReadMessage() @@ -802,5 +815,6 @@ func loadAllDataFiles(isReload bool) { keywords.LoadAliases() mutators.LoadDataFiles() colorpatterns.LoadColorPatterns() + audio.LoadAudioConfig() characters.CompileAdjectiveSwaps() // This should come after loading color patterns. } diff --git a/world.go b/world.go index 068b4c26..30e61a64 100644 --- a/world.go +++ b/world.go @@ -981,6 +981,10 @@ func (w *World) MessageTick() { continue } + if msp.SoundFile == `` { + continue + } + if user := users.GetByUserId(msp.UserId); user != nil { if msp.SoundType == `MUSIC` { diff --git a/world.roundtick.go b/world.roundtick.go index 238159b6..1a7c99b0 100644 --- a/world.roundtick.go +++ b/world.roundtick.go @@ -1770,7 +1770,7 @@ func (w *World) CheckForLevelUps() { } } - user.PlaySound(`sound/other/levelup.mp3`, `other`) + user.PlaySound(`levelup`, `other`) users.SaveUser(*user)