Skip to content

Commit ade784f

Browse files
authored
Notifications (#254)
# Changes * Added `LevelUp` and `PlayerDeath` events * Events now also being handled by discord package * Added a 1 second sleep to end of `main()` to allow queued http requests to complete (maybe) * Tweaks to level up messaging * Adjustments to discord icons * Ad-hoc message change to ERROR's that are server start/stop. # Examples <img width="812" alt="image" src="https://github.com/user-attachments/assets/a3707473-26e0-40a0-a4f5-5e7cbb643d59" />
1 parent 8af62af commit ade784f

File tree

11 files changed

+205
-84
lines changed

11 files changed

+205
-84
lines changed

internal/events/eventtypes.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"github.com/volte6/gomud/internal/configs"
77
"github.com/volte6/gomud/internal/connections"
88
"github.com/volte6/gomud/internal/items"
9+
"github.com/volte6/gomud/internal/stats"
910
)
1011

1112
// Used to apply or remove buffs
@@ -185,3 +186,28 @@ type Log struct {
185186
}
186187

187188
func (l Log) Type() string { return `Log` }
189+
190+
type LevelUp struct {
191+
UserId int
192+
RoomId int
193+
Username string
194+
CharacterName string
195+
NewLevel int
196+
StatsDelta stats.Statistics
197+
TrainingPoints int
198+
StatPoints int
199+
LivesGained int
200+
}
201+
202+
func (l LevelUp) Type() string { return `LevelUp` }
203+
204+
type PlayerDeath struct {
205+
UserId int
206+
RoomId int
207+
Username string
208+
CharacterName string
209+
Permanent bool
210+
KilledByUsers []int
211+
}
212+
213+
func (l PlayerDeath) Type() string { return `PlayerDeath` }
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package hooks
2+
3+
import (
4+
"github.com/volte6/gomud/internal/events"
5+
"github.com/volte6/gomud/internal/mobs"
6+
"github.com/volte6/gomud/internal/mudlog"
7+
"github.com/volte6/gomud/internal/users"
8+
)
9+
10+
// Checks whether their level is too high for a guide
11+
func CheckGuide(e events.Event) bool {
12+
13+
evt, typeOk := e.(events.LevelUp)
14+
if !typeOk {
15+
mudlog.Error("Event", "Expected Type", "LevelUp", "Actual Type", e.Type())
16+
return false
17+
}
18+
19+
user := users.GetByUserId(evt.UserId)
20+
if user == nil {
21+
return true
22+
}
23+
24+
if user.Character.Level >= 5 {
25+
for _, mobInstanceId := range user.Character.CharmedMobs {
26+
if mob := mobs.GetInstance(mobInstanceId); mob != nil {
27+
28+
if mob.MobId == 38 {
29+
mob.Command(`say I see you have grown much stronger and more experienced. My assistance is now needed elsewhere. I wish you good luck!`)
30+
mob.Command(`emote clicks their heels together and disappears in a cloud of smoke.`, 10)
31+
mob.Command(`suicide vanish`, 10)
32+
}
33+
}
34+
}
35+
}
36+
37+
return true
38+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package hooks
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/volte6/gomud/internal/events"
7+
"github.com/volte6/gomud/internal/mudlog"
8+
"github.com/volte6/gomud/internal/templates"
9+
"github.com/volte6/gomud/internal/term"
10+
"github.com/volte6/gomud/internal/users"
11+
)
12+
13+
func SendLevelNotifications(e events.Event) bool {
14+
15+
evt, typeOk := e.(events.LevelUp)
16+
if !typeOk {
17+
mudlog.Error("Event", "Expected Type", "LevelUp", "Actual Type", e.Type())
18+
return false
19+
}
20+
21+
user := users.GetByUserId(evt.UserId)
22+
if user == nil {
23+
return true
24+
}
25+
26+
levelUpData := map[string]interface{}{
27+
"level": evt.NewLevel,
28+
"statsDelta": evt.StatsDelta,
29+
"trainingPoints": evt.TrainingPoints,
30+
"statPoints": evt.StatPoints,
31+
"livesUp": evt.LivesGained,
32+
}
33+
levelUpStr, _ := templates.Process("character/levelup", levelUpData)
34+
35+
user.SendText(levelUpStr)
36+
37+
user.PlaySound(`levelup`, `other`)
38+
39+
events.AddToQueue(events.Broadcast{
40+
Text: fmt.Sprintf(`<ansi fg="magenta-bold">***</ansi> <ansi fg="username">%s</ansi> <ansi fg="yellow">has reached level %d!</ansi> <ansi fg="magenta-bold">***</ansi>%s`, evt.CharacterName, evt.NewLevel, term.CRLFStr),
41+
})
42+
43+
return true
44+
}

internal/hooks/NewTurn_LevelUp.go

Lines changed: 0 additions & 81 deletions
This file was deleted.

internal/hooks/hooks.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ func RegisterListeners() {
3939
events.RegisterListener(events.NewTurn{}, AutoSave)
4040
events.RegisterListener(events.NewTurn{}, PruneBuffs)
4141
events.RegisterListener(events.NewTurn{}, ActionPoints)
42-
events.RegisterListener(events.NewTurn{}, LevelUp)
4342

4443
// ItemOwnership
4544
events.RegisterListener(events.ItemOwnership{}, CheckItemQuests)
@@ -52,6 +51,10 @@ func RegisterListeners() {
5251
events.RegisterListener(events.PlayerSpawn{}, HandleJoin)
5352
events.RegisterListener(events.PlayerDespawn{}, HandleLeave, events.Last) // This is a final listener, has to happen last
5453

54+
// Levelup Notifications
55+
events.RegisterListener(events.LevelUp{}, SendLevelNotifications)
56+
events.RegisterListener(events.LevelUp{}, CheckGuide)
57+
5558
// Listener for debugging some stuff (catches all events)
5659
/*
5760
events.RegisterListener(nil, func(e events.Event) bool {

internal/integrations/discord/client.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ func registerListeners() {
5151
events.RegisterListener(events.PlayerSpawn{}, HandlePlayerSpawn)
5252
events.RegisterListener(events.PlayerDespawn{}, HandlePlayerDespawn)
5353
events.RegisterListener(events.Log{}, HandleLogs)
54+
events.RegisterListener(events.LevelUp{}, HandleLevelup)
55+
events.RegisterListener(events.PlayerDeath{}, HandleDeath)
5456
}
5557

5658
// Sends an embed message to discord which includes a colored bar to the left

internal/integrations/discord/listeners.go

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,37 @@ func HandleLogs(e events.Event) bool {
6565
return true
6666
}
6767

68-
msgOut = strings.Replace(msgOut, evt.Level, `**`+evt.Level+`**`, 1)
68+
if strings.Contains(msgOut, `Stopping server`) || strings.Contains(msgOut, `Starting server`) {
69+
msgOut = strings.Replace(msgOut, evt.Level, `**NOTICE**`, 1)
70+
} else {
71+
msgOut = strings.Replace(msgOut, evt.Level, `**`+evt.Level+`**`, 1)
72+
}
73+
74+
message := fmt.Sprintf(":bangbang: %s", msgOut)
75+
SendMessage(message)
76+
77+
return true
78+
}
79+
80+
func HandleLevelup(e events.Event) bool {
81+
evt, typeOk := e.(events.LevelUp)
82+
if !typeOk {
83+
return false
84+
}
85+
86+
message := fmt.Sprintf(`:crown: **%s** *has reached **level %d**!*`, evt.CharacterName, evt.NewLevel)
87+
SendMessage(message)
88+
89+
return true
90+
}
91+
92+
func HandleDeath(e events.Event) bool {
93+
evt, typeOk := e.(events.PlayerDeath)
94+
if !typeOk {
95+
return false
96+
}
6997

70-
message := fmt.Sprintf(":bangbang: %s :bangbang:", msgOut)
98+
message := fmt.Sprintf(`:skull: **%s** *has **DIED**!*`, evt.CharacterName)
7199
SendMessage(message)
72100

73101
return true

internal/usercommands/suicide.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ func Suicide(rest string, user *users.UserRecord, room *rooms.Room, flags events
5454
user.Character.KD.AddMobDeath()
5555
}
5656

57+
killedByUserIds := []int{}
5758
killedBy := ``
5859
for uid, _ := range user.Character.PlayerDamage {
5960

@@ -73,6 +74,8 @@ func Suicide(rest string, user *users.UserRecord, room *rooms.Room, flags events
7374
killedBy += `<ansi fg="username">` + u.Character.Name + `</ansi>`
7475
i++
7576
}
77+
78+
killedByUserIds = append(killedByUserIds, uid)
7679
}
7780

7881
msg := fmt.Sprintf(`<ansi fg="magenta-bold">***</ansi> <ansi fg="username">%s</ansi> has <ansi fg="red-bold">DIED!</ansi> <ansi fg="magenta-bold">***</ansi>%s`, user.Character.Name, term.CRLFStr)
@@ -86,6 +89,15 @@ func Suicide(rest string, user *users.UserRecord, room *rooms.Room, flags events
8689

8790
allowPenalties := user.Character.Level > int(config.OnDeathProtectionLevels)
8891

92+
events.AddToQueue(events.PlayerDeath{
93+
UserId: user.UserId,
94+
RoomId: user.Character.RoomId,
95+
Username: user.Username,
96+
CharacterName: user.Character.Name,
97+
Permanent: allowPenalties && bool(config.PermaDeath) && user.Character.ExtraLives == 0,
98+
KilledByUsers: killedByUserIds,
99+
})
100+
89101
// If permadeath is enabled, do some extra bookkeeping
90102
if allowPenalties && bool(config.PermaDeath) {
91103

internal/users/userrecord.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,36 @@ func (u *UserRecord) GrantXP(amt int, source string) {
135135
u.EventLog.Add(`xp`, fmt.Sprintf(`Gained <ansi fg="yellow-bold">%d experience points</ansi>! <ansi fg="7">(%s)</ansi>`, grantXP, source))
136136
}
137137

138+
if newLevel, statsDelta := u.Character.LevelUp(); newLevel {
139+
140+
c := configs.GetConfig()
141+
142+
livesBefore := u.Character.ExtraLives
143+
144+
if c.PermaDeath && c.LivesOnLevelUp > 0 {
145+
u.Character.ExtraLives += int(c.LivesOnLevelUp)
146+
if u.Character.ExtraLives > int(c.LivesMax) {
147+
u.Character.ExtraLives = int(c.LivesMax)
148+
}
149+
}
150+
151+
u.EventLog.Add(`xp`, fmt.Sprintf(`<ansi fg="username">%s</ansi> is now <ansi fg="magenta-bold">level %d</ansi>!`, u.Character.Name, u.Character.Level))
152+
153+
SaveUser(*u)
154+
155+
events.AddToQueue(events.LevelUp{
156+
UserId: u.UserId,
157+
RoomId: u.Character.RoomId,
158+
Username: u.Username,
159+
CharacterName: u.Character.Name,
160+
NewLevel: u.Character.Level,
161+
StatsDelta: statsDelta,
162+
TrainingPoints: 1,
163+
StatPoints: 1,
164+
LivesGained: u.Character.ExtraLives - livesBefore,
165+
})
166+
167+
}
138168
}
139169

140170
func (u *UserRecord) PlayMusic(musicFileOrId string) {

main.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,9 @@ func main() {
237237
// Otherwise we end up getting flushed file saves incomplete.
238238
wg.Wait()
239239

240+
// Give it a second to disaptch any final messages in the event queue
241+
// Example: discord server shutdown
242+
time.Sleep(1 * time.Second)
240243
}
241244

242245
func handleTelnetConnection(connDetails *connections.ConnectionDetails, wg *sync.WaitGroup) {

0 commit comments

Comments
 (0)