diff --git a/internal/app/chat_view.go b/internal/app/chat_view.go index d632395..c6d8b1d 100644 --- a/internal/app/chat_view.go +++ b/internal/app/chat_view.go @@ -5,6 +5,7 @@ import ( "github.com/gdamore/tcell/v2" "github.com/jordanorelli/astro-domu/internal/math" + "github.com/jordanorelli/astro-domu/internal/sim" "github.com/jordanorelli/blammo" ) @@ -12,6 +13,7 @@ type chatView struct { *blammo.Log composing string inFocus bool + history []sim.ChatMessage } func (c *chatView) handleEvent(ui *UI, e tcell.Event) bool { @@ -28,6 +30,13 @@ func (c *chatView) handleEvent(ui *UI, e tcell.Event) bool { break } + if key == tcell.KeyEnter { + // ugh lol + go ui.client.Send(sim.SendChatMessage{Text: c.composing}) + c.composing = "" + break + } + if key == tcell.KeyRune { c.composing = fmt.Sprintf("%s%c", c.composing, t.Rune()) c.Info("composing: %v", c.composing) @@ -40,6 +49,13 @@ func (c *chatView) handleEvent(ui *UI, e tcell.Event) bool { } func (c *chatView) draw(b *buffer) { + chatHeight := b.height - 1 + for i := 0; i < math.Min(chatHeight, len(c.history)); i++ { + msg := c.history[len(c.history)-1-i] + s := fmt.Sprintf("%12s: %s", msg.From, msg.Text) + b.writeString(s, math.Vec{0, b.height - 2 - i}, tcell.StyleDefault) + } + b.writeString(c.composing, math.Vec{0, b.height - 1}, tcell.StyleDefault) if c.inFocus { diff --git a/internal/app/ui.go b/internal/app/ui.go index 5cbfcd8..b37cfed 100644 --- a/internal/app/ui.go +++ b/internal/app/ui.go @@ -6,6 +6,7 @@ import ( "github.com/gdamore/tcell/v2" "github.com/jordanorelli/astro-domu/internal/exit" "github.com/jordanorelli/astro-domu/internal/math" + "github.com/jordanorelli/astro-domu/internal/sim" "github.com/jordanorelli/astro-domu/internal/wire" "github.com/jordanorelli/blammo" ) @@ -17,8 +18,8 @@ type UI struct { room *wire.Room client *wire.Client - gameView view - chatView view + gameView *gameView + chatView *chatView focussed view } @@ -57,7 +58,8 @@ func (ui *UI) Run() { }, } ui.chatView = &chatView{ - Log: ui.Child("chat-view"), + Log: ui.Child("chat-view"), + history: make([]sim.ChatMessage, 0, 32), } ui.focussed = ui.gameView @@ -140,6 +142,10 @@ func (ui *UI) handleNotification(v wire.Value) bool { ui.room.Entities = n.Entities return true + case *sim.ChatMessage: + ui.chatView.history = append(ui.chatView.history, *n) + return true + default: ui.Info("ignoring notification: %v", n) return false diff --git a/internal/math/abs.go b/internal/math/abs.go index 4472870..f1f9da8 100644 --- a/internal/math/abs.go +++ b/internal/math/abs.go @@ -21,3 +21,18 @@ func Max(a, b int, more ...int) int { } return v } + +func Min(a, b int, more ...int) int { + var v int + if a < b { + v = a + } else { + v = b + } + for _, next := range more { + if next < v { + v = next + } + } + return v +} diff --git a/internal/sim/chat.go b/internal/sim/chat.go new file mode 100644 index 0000000..c367788 --- /dev/null +++ b/internal/sim/chat.go @@ -0,0 +1,30 @@ +package sim + +import ( + "github.com/jordanorelli/astro-domu/internal/wire" +) + +type SendChatMessage struct { + Text string `json:"text"` +} + +func (SendChatMessage) NetTag() string { return "chat/send-msg" } + +func (m *SendChatMessage) exec(w *world, r *room, p *player, seq int) result { + for _, p2 := range r.players { + p2.outbox <- wire.Response{Body: ChatMessage{From: p.name, Text: m.Text}} + } + return result{reply: wire.OK{}} +} + +type ChatMessage struct { + From string `json:"from"` + Text string `json:"text"` +} + +func (ChatMessage) NetTag() string { return "chat/msg" } + +func init() { + wire.Register(func() wire.Value { return new(SendChatMessage) }) + wire.Register(func() wire.Value { return new(ChatMessage) }) +}