Skip to content
This repository has been archived by the owner on Oct 30, 2022. It is now read-only.

Commit

Permalink
rooms lobby and other
Browse files Browse the repository at this point in the history
  • Loading branch information
roby2014 committed Mar 2, 2022
1 parent 6ee68d6 commit 72522b5
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 45 deletions.
12 changes: 8 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,24 @@ func main() {
func setupRouter() {
router = mux.NewRouter()
router.HandleFunc("/", controller.Home)
router.Handle("/login", middleware.IsLogged(controller.Login))
router.HandleFunc("/logout", controller.Logout)
router.Handle("/login", middleware.IsLogged(controller.Login))

// steam user
router.HandleFunc("/api/player/{steamid}", controller.GetSteamUser).Methods("GET")

// player stats
router.HandleFunc("/api/playerstats/{steamid}", controller.GetPlayerStats).Methods("GET")

// create rooms and run them (TODO: database rooms integration)
// create rooms and run them (TODO: no hardcode range)
websocket.Lobby = &websocket.RoomsHub{}
for _, uid := range []int{1, 2, 3, 4, 5} {
newRoom := websocket.NewRoom(uid, 2)
roomRoute := fmt.Sprintf("/chat/%d", uid)
router.HandleFunc(roomRoute, newRoom.HandleWebsocket)
websocket.AddRoomToHub(newRoom)
router.HandleFunc("/api/room/"+fmt.Sprint(uid), newRoom.HandleRoom)
go newRoom.Run()
}

router.HandleFunc("/api/rooms", websocket.RoomsWebsocket)

}
34 changes: 29 additions & 5 deletions websocket/client.go
Original file line number Diff line number Diff line change
@@ -1,23 +1,36 @@
package websocket

import "github.com/gorilla/websocket"
import (
"log"

"github.com/gorilla/websocket"
)

// Client represents a... client
type Client struct {
SteamID string `json:"steamid"`
//name string `json:"name"`
socket *websocket.Conn
room *Room
send chan []byte
}

// Create new client
func newClient(s *websocket.Conn, r *Room) *Client {
func newClient(steamID string, s *websocket.Conn, r *Room) *Client {
return &Client{
socket: s,
room: r,
send: make(chan []byte, messageBufferSize),
SteamID: steamID,
socket: s,
room: r,
send: make(chan []byte, messageBufferSize),
}
}

// Removes a client from slice by its index
func removeClient(s []*Client, i int) []*Client {
s[i] = s[len(s)-1]
return s[:len(s)-1]
}

// Read client messages (from frontend)
func (c *Client) read() {
for {
Expand All @@ -33,9 +46,20 @@ func (c *Client) read() {
// Send message to client (to frontend)
func (c *Client) write() {
for msg := range c.send {
log.Println(string(msg))
if err := c.socket.WriteMessage(websocket.TextMessage, msg); err != nil {
break
}
}
c.socket.Close()
}

// Returns client index on the slice
func (c *Client) GetIndex(slice []*Client) int {
for idx, client := range slice {
if client == c {
return idx
}
}
return -1
}
55 changes: 23 additions & 32 deletions websocket/room.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,56 +2,46 @@ package websocket

import (
"log"
"net/http"

"github.com/gorilla/websocket"
)

// Room represents a single chat room
type Room struct {
id int
maxplayers int
clients map[*Client]bool
ID int `json:"id"`
Maxplayers int `json:"maxplayers"`
Clients []*Client `json:"clients"`
forward chan []byte
join chan *Client
leave chan *Client
}

const (
socketBufferSize = 1024
messageBufferSize = 256
)

var upgrader = &websocket.Upgrader{
ReadBufferSize: socketBufferSize,
WriteBufferSize: socketBufferSize,
CheckOrigin: func(r *http.Request) bool {
// TODO: change origin to frontend url
return true
},
}

// Create a new chat room
func NewRoom(id int, maxplayers int) *Room {
return &Room{
id: id,
maxplayers: maxplayers,
clients: make(map[*Client]bool),
ID: id,
Maxplayers: maxplayers,
Clients: nil,
forward: make(chan []byte),
join: make(chan *Client),
leave: make(chan *Client),
}
}

// Add room to hub
func AddRoomToHub(r *Room) {
Lobby.Rooms = append(Lobby.Rooms, r)
}

// Run chat room and wait for actions
func (r *Room) Run() {
log.Printf("running chat room %d", r.id)
log.Printf("running chat room %d", r.ID)
for {
select {
case client := <-r.join:
r.joinRoom(client)

case client := <-r.leave:
r.leaveRoom(client)

case msg := <-r.forward:
r.printToChatAll(msg)
}
Expand All @@ -60,35 +50,36 @@ func (r *Room) Run() {

// Client joins the room
func (r *Room) joinRoom(c *Client) {
log.Printf("new client in room %v", r.id)
r.clients[c] = true
log.Printf("new client in room %v", r.ID)
r.Clients = append(r.Clients, c)
}

// Client leaves the room
func (r *Room) leaveRoom(c *Client) {
log.Printf("client leaving room %v", r.id)
delete(r.clients, c)
log.Printf("client leaving room %v", r.ID)
r.Clients = removeClient(r.Clients, c.GetIndex(r.Clients))
close(c.send)

}

// Print message to all in the current room
func (r *Room) printToChatAll(msg []byte) {
data := FromJSON(msg)
log.Printf("[room %v] %v: %v", r.id, data.Sender, data)
log.Printf("[room %v] %v: %v", r.ID, data.Sender, data)

for client := range r.clients {
for _, client := range r.Clients {
select {
case client.send <- msg:
// success
default:
// not sure if this is possible/reachable but yeah
delete(r.clients, client)
r.Clients = removeClient(r.Clients, client.GetIndex(r.Clients))
close(client.send)
}
}
}

// Returns true if room is full
func (room *Room) IsFull() bool {
return len(room.clients) == room.maxplayers
return len(room.Clients) == room.Maxplayers
}
60 changes: 56 additions & 4 deletions websocket/server.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,64 @@
package websocket

import (
"log"
"net/http"

"github.com/gorilla/websocket"
)

type RoomsHub struct {
Rooms []*Room `json:"rooms"`
}

var Lobby *RoomsHub

const (
socketBufferSize = 1024
messageBufferSize = 256
)

// /api/rooms/{room_id} - create a client websocket, associating it with a room
func (room *Room) HandleWebsocket(w http.ResponseWriter, r *http.Request) {
// check if room is full
var upgrader = &websocket.Upgrader{
ReadBufferSize: socketBufferSize,
WriteBufferSize: socketBufferSize,
CheckOrigin: func(r *http.Request) bool {
// TODO: change origin to frontend url
return true
},
}

// /api/rooms
func RoomsWebsocket(w http.ResponseWriter, r *http.Request) {
// create client socket
socket, err := upgrader.Upgrade(w, r, nil)
if err != nil {
// TODO: return error
return
}

log.Println("Someone connected to /rooms")

reader(socket)
}

func reader(conn *websocket.Conn) {
defer conn.Close()
for {
msgType, msg, err := conn.ReadMessage()
if err != nil {
log.Fatal(err.Error())
return
}
log.Println(string(msg))
if err := conn.WriteMessage(msgType, msg); err != nil {
log.Fatal(err.Error())
return
}
}
}

// /api/rooms/{room_id} - create a client websocket, putting him in this room
func (room *Room) HandleRoom(w http.ResponseWriter, r *http.Request) {
if room.IsFull() {
// TODO: return error
return
Expand All @@ -20,7 +72,7 @@ func (room *Room) HandleWebsocket(w http.ResponseWriter, r *http.Request) {
}

// create new client associated to a room
client := newClient(socket, room)
client := newClient("1337", socket, room)

// join the room
room.join <- client
Expand Down

0 comments on commit 72522b5

Please sign in to comment.