From: Brendan Hansen Date: Mon, 4 Apr 2022 18:17:23 +0000 (-0500) Subject: "connecting" to the server X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=9438c57559bf5e5b72d44bd4c74541c08fd38b3e;p=voxel-shooter.git "connecting" to the server --- diff --git a/src/client/build.onyx b/src/client/build.onyx index 2d1168e..3c7bdc5 100644 --- a/src/client/build.onyx +++ b/src/client/build.onyx @@ -13,6 +13,8 @@ #load_all "./utils" #load_all "./world" +#load_all "./../shared" + // Onyx modules #load "glfw3/module" #load "opengles/module" diff --git a/src/client/connect_menu.onyx b/src/client/connect_menu.onyx index 4ddf29d..ffa1ba4 100644 --- a/src/client/connect_menu.onyx +++ b/src/client/connect_menu.onyx @@ -19,14 +19,13 @@ Connect_Menu :: struct { leave :: (_: rawptr) { array.free(^ip_addr); array.free(^port); - array.free(^name); } join :: (_: rawptr) { net_connect(ip_addr, ~~ conv.str_to_i64(port)); pop_game_state(); - push_game_state(Game_State, null); + push_game_state(Connecting_Menu, null); } draw :: (_: rawptr) { @@ -38,12 +37,53 @@ Connect_Menu :: struct { glClearColor(0.1, 0.1, 0.1, 1); glClear(GL_COLOR_BUFFER_BIT); - draw_textbox(.{0, 0, 200, 40}, ^ip_addr, "IP Address"); - draw_textbox(.{0, 40, 200, 40}, ^port, "Port"); - draw_textbox(.{0, 80, 200, 40}, ^name, "Name"); + ww, wh := camera.window_width, camera.window_height; - if draw_button(.{0, 120, 200, 40}, "Join") { + tx := (ww - 200) / 2; + ty := (wh - 160) / 2; + draw_textbox(.{tx, ty+0, 200, 40}, ^ip_addr, "IP Address"); + draw_textbox(.{tx, ty+40, 200, 40}, ^port, "Port"); + draw_textbox(.{tx, ty+80, 200, 40}, ^name, "Name"); + + if draw_button(.{tx, ty+120, 200, 40}, "Join") { join(_); } } +} + + + +Connecting_Menu :: struct { + #persist font: Font + + init :: (_: rawptr) { + font = font_lookup(.{"./assets/fonts/calibri.ttf", 32}); + net_set_on_connect_callback(.{ _, on_connect }); + } + + on_connect :: (_: rawptr) { + net_send_connect(name); + array.free(^name); @HACK // This feels gross to free this down here. + } + + update :: (_: rawptr, dt: f32) { + net_pulse(); + } + + draw :: (_: rawptr) { + if is_key_just_down(GLFW_KEY_ESCAPE) { + net_disconnect(); + glfwSetWindowShouldClose(window, true); + } + + glDisable(GL_DEPTH_TEST); + glClearColor(0.1, 0.1, 0.1, 1); + glClear(GL_COLOR_BUFFER_BIT); + + ww, wh := camera.window_width, camera.window_height; + + tx := (ww - 200) / 2; + ty := (wh - 16) / 2; + font_draw_centered(font, tx, ty, 200, "Connecting..."); + } } \ No newline at end of file diff --git a/src/client/game.onyx b/src/client/game.onyx index 7a884d7..e3236ec 100644 --- a/src/client/game.onyx +++ b/src/client/game.onyx @@ -101,6 +101,7 @@ draw_scene :: () { chunk_highlight_block(~~selected_block.x, ~~selected_block.y, ~~selected_block.z); } +@Temporary chat_messages: [..] [] u8; draw_chat :: () { @@ -122,7 +123,7 @@ draw_chat :: () { #persist pending_message: [..] u8; if draw_textbox(.{0, ~~(wh - 32), 400, 32}, ^pending_message) == .Enter_Pressed { if pending_message.count > 0 { - net_send_message(string.alloc_copy(pending_message)); + net_send_chat_message(string.alloc_copy(pending_message)); array.clear(^pending_message); } } diff --git a/src/client/net.onyx b/src/client/net.onyx index a343fd6..d35eb59 100644 --- a/src/client/net.onyx +++ b/src/client/net.onyx @@ -1,5 +1,4 @@ - net_connect :: (ip_addr: [] u8, port: u16) { addr: net.Socket_Address; addr.addr = net.str_to_ipv4(ip_addr); @@ -8,33 +7,95 @@ net_connect :: (ip_addr: [] u8, port: u16) { peer = onet.host_connect(host, ^addr, 2); } +net_disconnect :: () { + onet.peer_send_disconnect(peer); + onet.peer_flush_outgoing_commands(peer); + onet.peer_disconnect(peer); +} + +net_set_on_connect_callback :: (callback: On_Connect_Callback) { + on_connect_callback = callback; +} + net_pulse :: () { for host->get_events(timeout=0) { if it.type == .Connection { - chat_messages << "[Connected to server]"; + if on_connect_callback.func != null_proc { + on_connect_callback.func(on_connect_callback.data); + } } if it.type == .Message { - chat_messages << string.alloc_copy(it.data); + net_handle_packet(it.data); + } + } +} + +net_handle_packet :: (packet_data: [] u8) { + packet := cast(^packets.Packet_Base) packet_data.data; + switch packet.type { + case .Verify_Connect { + vc_packet := cast(^packets.Verify_Connect) packet; + player_id = vc_packet.player_id; + + push_game_state(Game_State, null); + } + + case .Chat_Message { + chat_packet := cast(^packets.Chat_Message) packet; + chat_messages << string.alloc_copy(.{ + ~~ ^chat_packet.message_data, + ~~ chat_packet.message_length, + }); } } } -@Temporary -net_send_message :: (message: str) { - packet := new(onet.Packet); - packet.flags |= .Reliable; - packet.data = message; - onet.peer_send(peer, 0, packet); +net_send_connect :: (name: str) { + msg := cast(^packets.Connect) calloc(sizeof packets.Connect + name.count); + msg.type = .Connect; + msg.client_version = (package runtime.vars).Game_Version; + msg.name_length = ~~ name.count; + memory.copy(~~ ^msg.name_data, name.data, name.count); + + p := new(onet.Packet); + p.flags |= .Reliable; + p.data = .{ ~~msg, sizeof packets.Connect + name.count }; + onet.peer_send(peer, 0, p); +} + +net_send_chat_message :: (message: str) { + msg := cast(^packets.Chat_Message) calloc(sizeof packets.Chat_Message + message.count); + msg.type = .Chat_Message; + msg.sender_id = player_id; + msg.message_length = ~~ message.count; + memory.copy(~~ ^msg.message_data, message.data, message.count); + + p := new(onet.Packet); + p.flags |= .Reliable; + p.data = .{ ~~msg, sizeof packets.Chat_Message + message.count }; + onet.peer_send(peer, 0, p); } #local { use package core - onet :: package onyx_net + onet :: package onyx_net + packets :: package packets host: ^onet.Host; peer: ^onet.Peer; + + @TEMPORARY @HACK + player_id: u16; + + On_Connect_Callback :: struct { + data: rawptr; + func: (rawptr) -> void; + } + on_connect_callback: On_Connect_Callback; + + any_to_buffer :: macro (x: ^$T) => ([] u8).{ ~~x, sizeof T }; } diff --git a/src/server/build.onyx b/src/server/build.onyx index 0f46cd2..de3b1a2 100644 --- a/src/server/build.onyx +++ b/src/server/build.onyx @@ -10,4 +10,6 @@ package runtime.vars #load "./../src/config" #load "server" +#load "./../shared/packets" + #load "onyx-net/src/module" diff --git a/src/server/server.onyx b/src/server/server.onyx index c25f9a0..76a8e7f 100644 --- a/src/server/server.onyx +++ b/src/server/server.onyx @@ -1,27 +1,126 @@ use package core +use package core.intrinsics.onyx {__initialize} #local { - onet :: package onyx_net + onet :: package onyx_net + packets :: package packets } -main :: (args) => { +Player_Data :: struct { + id: u16; + name: str; + peer: ^onet.Peer; +} + +max_connected_players := 8; +next_player_id := 1; +connected_players: Map(u32, Player_Data); + +host: ^onet.Host; + +setup_server :: () { addr: net.Socket_Address; addr.port = (package runtime.vars).Game_Port; - host, err := onet.host_create(^addr, 16); + host', err := onet.host_create(^addr, 16); if err != .None { + println(err); os.exit(1); } +} + +handle_packet :: (peer: ^onet.Peer, packet_data: [] u8) { + packet := cast(^packets.Packet_Base) packet_data.data; + switch packet.type { + case .Connect { + connect_packet := cast(^packets.Connect) packet; + + if connect_packet.client_version != (package runtime.vars).Game_Version { + respond_with_error(.Client_Version_Wrong); + } + + if connected_players.entries.count >= max_connected_players { + respond_with_error(.Server_Full); + } + + name := str.{ + ~~ ^connect_packet.name_data, + ~~connect_packet.name_length + }; + + defer next_player_id += 1; + connected_players[next_player_id] = .{ + id = ~~ next_player_id, + name = string.alloc_copy(name), + peer = peer, + }; + + { + msg_buffer: [128] u8; + msg := conv.format(msg_buffer, "{} joined the server.\n", connected_players[next_player_id].name); + print(msg); + send_chat_message(0, msg); + } + + msg := new(packets.Verify_Connect); @LEAK + msg.type = .Verify_Connect; + msg.player_id = ~~next_player_id; + + p := new(onet.Packet); @LEAK + p.flags |= .Reliable; + p.data = any_to_buffer(msg); + onet.peer_send(peer, 0, p); + + respond_with_error :: macro (reason: packets.Connection_Rejected.Reason) { + msg := new(packets.Connection_Rejected); @LEAK + msg.type = .Connection_Rejected; + msg.reason = reason; + + p := new(onet.Packet); @LEAK + p.flags |= .Reliable; + p.data = any_to_buffer(msg); + onet.peer_send(peer, 0, p); + return; + } + } + + case .Chat_Message { + packet := new(onet.Packet); @LEAK + packet.flags |= .Reliable; + packet.data = memory.copy_slice(packet_data); + onet.host_broadcast(host, 0, packet); + } + } +} + +send_chat_message :: (from: u16, msg: [] u8) { + chat_packet, packet_size := new_with_extra(packets.Chat_Message, msg.count); @LEAK + chat_packet.type = .Chat_Message; + chat_packet.sender_id = from; + chat_packet.message_length = ~~ msg.count; + memory.copy(~~ ^chat_packet.message_data, msg.data, msg.count); + + packet := new(onet.Packet); @LEAK + packet.flags |= .Reliable; + packet.data = .{ ~~chat_packet, packet_size }; + onet.host_broadcast(host, 0, packet); +} + +any_to_buffer :: macro (x: ^$T) => ([] u8).{ ~~x, sizeof T }; +new_with_extra :: macro ($T: type_expr, extra: u32) -> (^T, u32) { + size := sizeof T + extra; + ptr := cast(^T) calloc(size); + __initialize(ptr); + return ptr, size; +} + +loop :: () { while true { for host->get_events(timeout=1000) { if it.type == .Connection { printf("Connection from {}:{}\n", net.ipv4_to_str(it.peer.addr.addr), it.peer.addr.port); - packet := new(onet.Packet); - packet.flags |= .Reliable; - packet.data = aprintf("{}:{} connected", net.ipv4_to_str(it.peer.addr.addr), it.peer.addr.port); @LEAK - onet.host_broadcast(host, 0, packet); @LEAK } if it.type == .Disconnection { @@ -29,13 +128,14 @@ main :: (args) => { } if it.type == .Message { - printf("Message: {}\n", it.data); - - packet := new(onet.Packet); - packet.flags |= .Reliable; - packet.data = string.alloc_copy(it.data); @LEAK - onet.host_broadcast(host, 0, packet); @LEAK + handle_packet(it.peer, it.data); } } } } + + +main :: (args) => { + setup_server(); + loop(); +} diff --git a/src/shared/packets.onyx b/src/shared/packets.onyx index fffaab5..4421cc2 100644 --- a/src/shared/packets.onyx +++ b/src/shared/packets.onyx @@ -1,5 +1,5 @@ -package packet +package packets Type :: enum (u8) { Connect; @@ -7,6 +7,8 @@ Type :: enum (u8) { Connection_Rejected; Disconnect; + Chat_Message; + Player_Joined; Player_Left; Player_Moved; @@ -18,8 +20,9 @@ Packet_Base :: struct #pack { Connect :: struct #pack { use base: Packet_Base; - name: str; client_version: u32; + name_length: u16; + name_data: void; } Verify_Connect :: struct #pack { @@ -31,10 +34,18 @@ Connection_Rejected :: struct #pack { use base: Packet_Base; Reason :: enum { - Server_Full :: 1; - Outdated_Client :: 2; + Server_Full :: 1; + Client_Version_Wrong :: 2; } reason: Reason; } + +Chat_Message :: struct #pack { + use base: Packet_Base; + sender_id: u16; // Should this be a Player ID? + message_length: u16; + message_data: void; +} +