server: create/send payload
This commit is contained in:
+15
-7
@@ -31,8 +31,8 @@ Game :: struct {
|
||||
deck: [dynamic]Card,
|
||||
}
|
||||
|
||||
hand_size :: proc(s: Game) -> int {
|
||||
return s.num_players <= 3 ? 5 : 4
|
||||
hand_size :: proc(g: Game) -> int {
|
||||
return g.num_players <= 3 ? 5 : 4
|
||||
}
|
||||
|
||||
create_deck :: proc() -> (deck: [dynamic]Card) {
|
||||
@@ -45,9 +45,9 @@ create_deck :: proc() -> (deck: [dynamic]Card) {
|
||||
return
|
||||
}
|
||||
|
||||
create_player :: proc(s: ^Game) -> (p: Player) {
|
||||
for i in 0 ..< hand_size(s^) {
|
||||
append(&p.hand, pop(&s.deck))
|
||||
create_player :: proc(g: ^Game) -> (p: Player) {
|
||||
for i in 0 ..< hand_size(g^) {
|
||||
append(&p.hand, pop(&g.deck))
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -63,8 +63,16 @@ create_game :: proc(hint_tokens, lives_left, num_players: int) -> (s: Game) {
|
||||
return
|
||||
}
|
||||
|
||||
print_game :: proc(s: Game) {
|
||||
for p in s.players {
|
||||
delete_game :: proc(g: ^Game) {
|
||||
delete(g.deck)
|
||||
for &p in g.players {
|
||||
delete(p.hand)
|
||||
}
|
||||
delete(g.players)
|
||||
}
|
||||
|
||||
print_game :: proc(g: Game) {
|
||||
for p in g.players {
|
||||
fmt.println("---")
|
||||
for c in p.hand {
|
||||
fmt.println(c.value, c.color)
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ main :: proc() {
|
||||
if !endpoint_ok do panic(fmt.tprintln("failed to parse endpoint:", os.args[2]))
|
||||
num_players, int_ok := strconv.parse_int(os.args[3])
|
||||
if !int_ok do panic(fmt.tprintln("failed to parse number of players:", os.args[3]))
|
||||
if num_players < 2 || num_players > 5 do return
|
||||
if num_players < 1 || num_players > 5 do return
|
||||
run_server(addr, num_players)
|
||||
case:
|
||||
return
|
||||
|
||||
+92
-9
@@ -1,23 +1,106 @@
|
||||
package hanabi
|
||||
|
||||
import "core:fmt"
|
||||
import "core:math/rand"
|
||||
import "core:net"
|
||||
|
||||
run_server :: proc(listen_addr: net.Endpoint, num_players: int) {
|
||||
Comm_World :: struct {
|
||||
sockets: [dynamic]net.TCP_Socket,
|
||||
}
|
||||
|
||||
create_comm_world :: proc(
|
||||
listener: net.TCP_Socket,
|
||||
num_conn: int,
|
||||
) -> (
|
||||
w: Comm_World,
|
||||
err: net.Network_Error,
|
||||
) {
|
||||
for len(w.sockets) < num_conn {
|
||||
client_sock, source := net.accept_tcp(listener) or_return
|
||||
append(&w.sockets, client_sock)
|
||||
fmt.println("player connected:", net.to_string(source))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
delete_comm_world :: proc(w: ^Comm_World) {
|
||||
for sock in w.sockets {
|
||||
net.close(sock)
|
||||
}
|
||||
delete(w.sockets)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
emulates Card, but packs the fields more neatly
|
||||
*/
|
||||
Bit_Card :: bit_field u8 {
|
||||
value: int | 3,
|
||||
color: COLORS | 3,
|
||||
}
|
||||
|
||||
Payload :: struct #packed {
|
||||
num_hints: u8,
|
||||
num_lives: u8,
|
||||
num_cards: u8,
|
||||
cards: []Bit_Card,
|
||||
}
|
||||
|
||||
create_payload :: proc(g: Game, player: int, allocator := context.allocator) -> Payload {
|
||||
cards: [dynamic]Bit_Card
|
||||
for i in 0 ..< g.num_players {
|
||||
if i == player do continue
|
||||
hand := g.players[i].hand[:]
|
||||
for c in hand {
|
||||
append(&cards, Bit_Card{value = c.value, color = c.color})
|
||||
}
|
||||
}
|
||||
return {u8(g.hint_tokens), u8(g.lives_left), u8(len(cards)), cards[:]}
|
||||
}
|
||||
|
||||
send_payload :: proc(sock: net.TCP_Socket, pl: Payload) -> net.Network_Error {
|
||||
data: [dynamic]byte
|
||||
defer delete(data)
|
||||
append(&data, pl.num_hints, pl.num_lives, pl.num_cards)
|
||||
for c in pl.cards do append(&data, transmute(u8)c)
|
||||
net.send(sock, data[:]) or_return
|
||||
return nil
|
||||
}
|
||||
|
||||
DEFAULT_HINT_TOKENS :: 8
|
||||
DEFAULT_LIVES :: 3
|
||||
|
||||
run_server :: proc(
|
||||
listen_addr: net.Endpoint,
|
||||
num_players: int,
|
||||
num_hints := DEFAULT_HINT_TOKENS,
|
||||
num_lives := DEFAULT_LIVES,
|
||||
) {
|
||||
listener, list_err := net.listen_tcp(listen_addr)
|
||||
if list_err != nil do panic(fmt.tprintln("failed to listen:", net.to_string(listen_addr)))
|
||||
defer net.close(listener)
|
||||
|
||||
players: [dynamic]net.TCP_Socket
|
||||
defer delete(players)
|
||||
w, comm_err := create_comm_world(listener, num_players)
|
||||
if comm_err != nil do panic(fmt.tprintln("failed to create comm world:", comm_err))
|
||||
defer delete_comm_world(&w)
|
||||
|
||||
for len(players) < num_players {
|
||||
client_sock, source, err := net.accept_tcp(listener)
|
||||
if err != nil {
|
||||
fmt.eprintln("failed to connect:", err, source)
|
||||
g := create_game(num_hints, num_lives, num_players)
|
||||
defer delete_game(&g)
|
||||
|
||||
current_player := rand.int_max(num_players)
|
||||
game_loop: for {
|
||||
for i in 0 ..< num_players {
|
||||
pl := create_payload(g, i, context.temp_allocator)
|
||||
send_err := send_payload(w.sockets[i], pl)
|
||||
if send_err != nil do panic("failed to send payload")
|
||||
}
|
||||
append(&players, client_sock)
|
||||
fmt.println("player connected:", net.to_string(source))
|
||||
|
||||
fmt.printfln("player %s's turn!", current_player)
|
||||
|
||||
// body
|
||||
|
||||
current_player = (current_player + 1) % num_players
|
||||
free_all(context.temp_allocator)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user