diff --git a/dealer.go b/dealer.go index 398f4e2..fdfa256 100644 --- a/dealer.go +++ b/dealer.go @@ -3,6 +3,7 @@ package main import ( "fmt" "log" + "strings" "maunium.net/go/mautrix" "maunium.net/go/mautrix/event" @@ -73,17 +74,53 @@ func (d *Dealer) RegisterHandlers() { log.Printf("received membership event for non active game: %v", evt) return } - if evt.Sender != match.P1 || evt.Sender != match.P2 || evt.Sender != d.Client.UserID { + if evt.Sender != match.P1 && evt.Sender != match.P2 && evt.Sender != d.Client.UserID { log.Println("membership event for non player") return } - gameRoom := d.Client.Store.LoadRoom(evt.RoomID) - match.JoinOrLeave(gameRoom, evt) + members, err := d.Client.JoinedMembers(evt.RoomID) + if err != nil { + panic(err) + } + match.JoinOrLeave(members.Joined, evt.Content.AsMember()) }) syncer.OnEventType(event.EventMessage, func(source mautrix.EventSource, evt *event.Event) { - playerRoom, ok := d.PlayerRooms[evt.Sender] - if ok { + playerRoom, pok := d.PlayerRooms[evt.Sender] + if pok { log.Printf("received direct message in room %v", playerRoom) + var roominfo PlayerRoomInfo + _ = d.Client.StateEvent(playerRoom, event.Type{"snen.player", event.StateEventType}, "player_info", &roominfo) + if roominfo.CurrentGame != "" { + //parse as gamecommand + match := d.RoomsList[roominfo.CurrentGame] + if match.Game == nil { + d.Client.SendText(playerRoom, "can't accept game commands yet") + return + } + resp := match.ParseAction(evt.Content.AsMessage().Body) + if resp.Body != "" { + _, err := d.Client.SendText(playerRoom, resp.Body) + if err != nil { + panic(err) + } + d.Client.SendText(roominfo.CurrentGame, fmt.Sprintf("%v played %v", evt.Sender, evt.Content.AsMessage().Body)) + + if !resp.Private { + d.Client.SendText(roominfo.CurrentGame, fmt.Sprintf("Result: %v", resp.Body)) + } + } + } else { + //parse as out of game command + log.Println("out of game command received") + //TODO make this better + msg := evt.Content.AsMessage().Body + msg_s := strings.Split(msg, " ") + if msg_s[0] == "direct" { + d.NewMatch(evt.Sender, id.NewUserID(msg_s[1], d.HomeserverDomain)) + } + + } + return } match, ok := d.RoomsList[evt.RoomID] @@ -95,26 +132,7 @@ func (d *Dealer) RegisterHandlers() { log.Println("ignoring message event from non player") return } - //parse as game command - resp := match.ParseAction(evt.Content.AsMessage().Body) - if resp.Private { - //respond privately - dm, ok := d.PlayerRooms[evt.Sender] - if !ok { - log.Println("tried to send private message to player without room") - return - } - _, err := d.Client.SendText(dm, resp.Body) - if err != nil { - panic(err) - } - } else { - _, err := d.Client.SendText(evt.RoomID, resp.Body) - if err != nil { - panic(err) - } - } - + //parse as in game command i.e. chat }) } @@ -185,7 +203,7 @@ func (d *Dealer) NewMatch(p1, p2 id.UserID) *Match { match := NewMatch() roomname := fmt.Sprintf("tome_match_%v", match.ID) createRes, err := d.Client.CreateRoom(&mautrix.ReqCreateRoom{ - Preset: "public", + Preset: "public_chat", RoomAliasName: roomname, Invite: []id.UserID{p1, p2}, }) @@ -195,9 +213,21 @@ func (d *Dealer) NewMatch(p1, p2 id.UserID) *Match { } match.MatrixRoom = createRes.RoomID match.P1 = p1 + match.P1Room = d.PlayerRooms[p1] match.P2 = p2 + match.P2Room = d.PlayerRooms[p2] match.Dealer = d.Client.UserID d.RoomsList[createRes.RoomID] = match + + d.Client.SendStateEvent(match.P1Room, event.Type{"snen.player", event.StateEventType}, "player_info", PlayerRoomInfo{ + CurrentGame: match.MatrixRoom, + CurrentDeck: []int{}, + }) + d.Client.SendStateEvent(match.P2Room, event.Type{"snen.player", event.StateEventType}, "player_info", PlayerRoomInfo{ + CurrentGame: match.MatrixRoom, + CurrentDeck: []int{}, + }) + return match } diff --git a/match.go b/match.go index aa74574..d6d5bf4 100644 --- a/match.go +++ b/match.go @@ -7,7 +7,6 @@ import ( "git.saintnet.tech/tomecraft/tome_game" "git.saintnet.tech/tomecraft/tome_lib" "github.com/google/uuid" - "maunium.net/go/mautrix" "maunium.net/go/mautrix/event" "maunium.net/go/mautrix/id" ) @@ -16,7 +15,9 @@ type Match struct { ID uuid.UUID Game *tome_game.Game P1 id.UserID + P1Room id.RoomID P2 id.UserID + P2Room id.RoomID Dealer id.UserID MatrixRoom id.RoomID } @@ -31,19 +32,21 @@ func NewMatch() *Match { ID: uuid.New(), Game: nil, P1: "", + P1Room: "", P2: "", + P2Room: "", MatrixRoom: "", } } func (m *Match) ParseAction(msg string) MatchResp { - var cmd *tome_lib.Command - err := json.Unmarshal([]byte(msg), cmd) + var cmd tome_lib.Command + err := json.Unmarshal([]byte(msg), &cmd) if err != nil { log.Printf("error unmarshaling gamecommand %v", err) return MatchResp{Body: "", Private: false} } - res := m.Game.Parse(cmd) + res := m.Game.Parse(&cmd) match_res := MatchResp{ Body: res.String(), Private: (cmd.Type == tome_lib.ActCmd && cmd.String() == "d"), @@ -52,21 +55,30 @@ func (m *Match) ParseAction(msg string) MatchResp { } -func (m *Match) JoinOrLeave(gameRoom *mautrix.Room, evt *event.Event) { - if gameRoom == nil { - panic("no matrix room for game") - } - if evt.Content.AsMember().Membership == event.MembershipJoin { - if gameRoom.GetMembershipState(m.P1) == event.MembershipJoin && gameRoom.GetMembershipState(m.P2) == event.MembershipJoin { +func (m *Match) JoinOrLeave(members map[id.UserID]struct { + DisplayName *string `json:"display_name"` + AvatarURL *string `json:"avatar_url"` +}, evt *event.MemberEventContent) { + _, p1ok := members[m.P1] + _, p2ok := members[m.P2] + if evt.Membership == event.MembershipJoin { + if m.Game != nil { + //players are already here, we don't care about joins + return + } + if p1ok && p2ok { log.Println("both players are in the room now") m.Game = tome_game.NewGame([]int{}, []int{}) } - } else if evt.Content.AsMember().Membership == event.MembershipLeave { - if m.Game.Status != tome_lib.StatusDraw || - m.Game.Status != tome_lib.StatusScourgeWin || - m.Game.Status != tome_lib.StatusSentinalWin { + } else if evt.Membership == event.MembershipLeave { + if !p1ok || !p2ok { + if m.Game.Status != tome_lib.StatusDraw || + m.Game.Status != tome_lib.StatusScourgeWin || + m.Game.Status != tome_lib.StatusSentinalWin { - m.Game.Status = tome_lib.StatusStop + m.Game.Status = tome_lib.StatusStop + log.Println("user left match; stopping") + } } } else { log.Println("disregarding membership event we don't care about") diff --git a/player_room.go b/player_room.go new file mode 100644 index 0000000..fec21b0 --- /dev/null +++ b/player_room.go @@ -0,0 +1,8 @@ +package main + +import "maunium.net/go/mautrix/id" + +type PlayerRoomInfo struct { + CurrentGame id.RoomID `json:'current_game'` + CurrentDeck []int `json:'current_deck'` +}