Skip to content

Commit e921c58

Browse files
slugaliskjbpratt
authored andcommitted
add emote combos
1 parent b13a79c commit e921c58

File tree

3 files changed

+97
-0
lines changed

3 files changed

+97
-0
lines changed

combos.go

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package main
2+
3+
import (
4+
"errors"
5+
"strings"
6+
"sync"
7+
)
8+
9+
var ErrComboDuplicate = errors.New("user has already participated in combo")
10+
11+
var combos = Combos{}
12+
13+
type comboVariant struct {
14+
modifiers []string
15+
count int
16+
}
17+
18+
type Combos struct {
19+
lock sync.Mutex
20+
emote string
21+
count int
22+
variants map[string]*comboVariant
23+
participants map[string]struct{}
24+
}
25+
26+
func (c *Combos) Transform(msg *EventDataOut) error {
27+
c.lock.Lock()
28+
defer c.lock.Unlock()
29+
30+
if !isEmoteMessage(msg) {
31+
c.reset()
32+
return nil
33+
}
34+
35+
emote := msg.Entities.Emotes[0]
36+
37+
// if the combo was broken by another emote message reset
38+
if c.emote != emote.Name {
39+
c.reset()
40+
}
41+
42+
if _, ok := c.participants[msg.Nick]; ok {
43+
return ErrComboDuplicate
44+
}
45+
46+
c.emote = emote.Name
47+
c.count++
48+
c.participants[msg.Nick] = struct{}{}
49+
50+
variant := strings.Join(emote.Modifiers, ":")
51+
if _, ok := c.variants[variant]; !ok {
52+
c.variants[variant] = &comboVariant{
53+
modifiers: emote.Modifiers,
54+
count: 0,
55+
}
56+
}
57+
c.variants[variant].count++
58+
59+
// if this was the first emote in the combo don't mark a combo yet
60+
if c.count == 1 {
61+
return nil
62+
}
63+
64+
emote.Combo = c.count
65+
66+
topVariantCount := -1
67+
for _, v := range c.variants {
68+
if v.count > topVariantCount {
69+
topVariantCount = c.count
70+
emote.Modifiers = v.modifiers
71+
}
72+
}
73+
74+
return nil
75+
}
76+
77+
func (c *Combos) reset() {
78+
c.emote = ""
79+
c.count = 0
80+
c.variants = map[string]*comboVariant{}
81+
c.participants = map[string]struct{}{}
82+
}
83+
84+
func isEmoteMessage(msg *EventDataOut) bool {
85+
if len(msg.Entities.Emotes) != 1 {
86+
return false
87+
}
88+
b := msg.Entities.Emotes[0].Bounds
89+
return b[0] == 0 && b[1] == len(msg.Data)
90+
}

connection.go

+6
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,12 @@ func (c *Connection) OnMsg(data []byte) {
457457
out := c.getEventDataOut()
458458
out.Data = msg
459459
out.Entities = entities.Extract(msg)
460+
461+
if err := combos.Transform(out); err == ErrComboDuplicate {
462+
c.SendError("duplicate")
463+
return
464+
}
465+
460466
c.Broadcast("MSG", out)
461467
}
462468

entities.go

+1
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ type Emote struct {
162162
Name string `json:"name,omitempty"`
163163
Modifiers []string `json:"modifiers,omitempty"`
164164
Bounds [2]int `json:"bounds,omitempty"`
165+
Combo int `json:"combo,omitempty"`
165166
}
166167

167168
type Nick struct {

0 commit comments

Comments
 (0)