refactored network code; bugfixes
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 18 Apr 2022 04:28:58 +0000 (23:28 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 18 Apr 2022 04:28:58 +0000 (23:28 -0500)
lib/onyx-net
src/client/connect_menu.onyx
src/client/game.onyx
src/client/gfx/shader.onyx
src/client/main.onyx
src/client/net.onyx
src/server/server.onyx
src/shared/packets.onyx

index d851e9c7762bba2c40e9ea0e4fdeb4e935009406..97c1582fda5f2881588a1fc0296ba9401af8bb7e 160000 (submodule)
@@ -1 +1 @@
-Subproject commit d851e9c7762bba2c40e9ea0e4fdeb4e935009406
+Subproject commit 97c1582fda5f2881588a1fc0296ba9401af8bb7e
index 976a629969f9fe5e2c292d6e5e856d1413aaf83f..52d9fbf05b1b47b05ba90cb6c59cffe6066290d2 100644 (file)
@@ -64,7 +64,7 @@ Connecting_Menu :: struct {
         font = font_lookup(.{"./assets/fonts/calibri.ttf", 32});
         net_set_on_connect_callback(.{ _, on_connect });
 
-        connection_timeout = 10.0f; // 10 second timeout
+        connection_timeout = 10.0; // 10 second timeout
     }
 
     on_connect :: (_: rawptr) {
@@ -105,4 +105,4 @@ Connecting_Menu :: struct {
         ty := (wh - 16) / 2;
         font_draw_centered(font, tx, ty, 200, "Connecting...");
     }
-}
\ No newline at end of file
+}
index ed4993c5825a3713661d6fc0e9ffb0fb7b02ba3b..d2f200f0c4dbbf159fb714bb9b69a59affd65eea 100644 (file)
@@ -18,8 +18,9 @@ world: ^World;
 selected_block: Vector3i;
 
 player_shader: Shader;
-world_fog_block: Shader_Block;
 
+@Relocate
+world_fog_block: Shader_Block;
 World_Fog :: struct {
     u_fog_color: Vector3;
     u_fog_start: f32;
@@ -39,12 +40,13 @@ game_init :: (_: rawptr) {
 
     shader_link_world_matrix_block(world_shader);
     shader_link_world_matrix_block(player_shader);
-    shader_block_link(^world_fog_block, world_shader, #cstr "u_game_fog_block");
-    shader_block_link(^world_fog_block, player_shader, #cstr "u_game_fog_block");
 
     world_fog_block = shader_block_create(World_Fog);
     shader_block_update(^world_fog_block, "u_fog_start", 50.0f);
     shader_block_update(^world_fog_block, "u_fog_range", 10.0f);
+    shader_block_update(^world_fog_block, "u_fog_color", fog_color);
+    shader_block_link(^world_fog_block, world_shader, #cstr "u_game_fog_block");
+    shader_block_link(^world_fog_block, player_shader, #cstr "u_game_fog_block");
 
     font      = font_lookup(.{"./assets/fonts/calibri.ttf", 32});
     chat_font = font_lookup(.{"./assets/fonts/calibri.ttf", 16});
@@ -131,7 +133,6 @@ draw_scene :: () {
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
     shader_use(world_shader);
-    shader_block_update(^world_fog_block, "u_fog_color", fog_color);
     shader_set_uniform(world_shader, #cstr "u_texture", 0);
     glEnable(GL_DEPTH_TEST);
     world_draw(world);
@@ -194,4 +195,4 @@ toggle_cursor_grabbed :: () {
             glfwSetInputMode(window, GLFW_RAW_MOUSE_MOTION, GLFW_FALSE);
         }
     }
-}
\ No newline at end of file
+}
index 7aafca94de7a1ed36989cac357565c817b150d1d..2bd3a176ad0d12f9b3eae5c354962d344e8e0cd8 100644 (file)
@@ -178,7 +178,9 @@ Shader_Block :: struct {
 }
 
 shader_block_create :: (T: type_expr) -> Shader_Block {
-    #persist next_block_id := 0;
+    // This is 2 beacuse the window and world matrix blocks are
+    // not allocated using this procedure.
+    #persist next_block_id := 2;
 
     block: Shader_Block;
     block.type = T;
@@ -216,4 +218,4 @@ shader_block_update :: (s: ^Shader_Block, field: str, value: $T) {
             break;
         }
     }
-}
\ No newline at end of file
+}
index 0369bd307a4e56f944a0912087c1c73bf58ccbe2..99eece89998d302df7279a94344d7133d861e002 100644 (file)
@@ -67,6 +67,7 @@ init :: () {
     shaders_init();
     fonts_init();
     immediate_init();
+    net_register_handles();
     
     __initialize(^camera);
     camera_set_fov(^camera, 75);
@@ -177,7 +178,7 @@ main_loop :: () {
     }
 }
 
-main :: (args) => {
+main :: () {
     if !glfwInit() {
         println("Failed to initialize GLFW");
         os.exit(1);
index 4898ff0ccdcc34363f0511499ba54e282a030af8..8244f7cdf83e58a85b27df363a8c3629f3aaa696 100644 (file)
@@ -1,4 +1,21 @@
 
+net_register_handles :: () {
+    use type_info;
+
+    for_all_types() {
+        if struct_inherits(type_idx, Packet_Handler) {
+            func := get_struct_method(type_idx, "handle");
+            if func == null do continue;
+
+            struct_type_info := cast(^Type_Info_Struct) type_info;
+            packet_type := *cast(^packets.Type) struct_type_info.members[0].default;
+            packet_handles[packet_type] = *cast(^(rawptr) -> void) func.data;
+        }
+    }
+
+    println(packet_handles);
+}
+
 net_connect :: (ip_addr: [] u8, port: u16) {
     addr: net.Socket_Address;
     addr.addr = net.str_to_ipv4(ip_addr);
@@ -31,90 +48,104 @@ net_pulse :: () {
     }
 }
 
-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;
+#local packet_handles: Map(packets.Type, (rawptr) -> void);
 
-            push_game_state(Game_State, null);
-        }
+Packet_Handler :: struct {
+    type: packets.Type;
+}
 
-        case .Player_Joined {
-            joined_packet := cast(^packets.Player_Joined) packet;
+#local Verify_Connect_Handle :: struct {
+    use base := Packet_Handler.{ .Verify_Connect };
 
-            name := string.alloc_copy(.{
-                ~~ ^joined_packet.name_data,
-                ~~ joined_packet.name_length
-            });
+    handle :: (packet: ^packets.Verify_Connect) {
+        player_id = packet.player_id;
 
-            other_players[~~ joined_packet.player_id] = .{
-                name,
-                .{0, 0, 0}, .{0, 0, 0}, .{0, 0, 0},
-                false
-            };
+        push_game_state(Game_State, null);
+    }
+}
 
-            if joined_packet.player_id != player_id {
-                buf: [1024] u8;
-                chat_messages << (conv.format(buf, "{} joined the server!", name) |> string.alloc_copy());
-            }
-        }
+#local Player_Joined_Handle :: struct {
+    use base := Packet_Handler.{ .Player_Joined };
 
-        case .Connection_Rejected {
-            cr_packet := cast(^packets.Connection_Rejected) packet;
-            printf("Connection refused: {}\n", cr_packet.reason);
+    handle :: (packet: ^packets.Player_Joined) {
+        name := string.alloc_copy(packet->name());
 
-            pop_game_state();
-            push_game_state(Connect_Menu, null);
+        other_players[~~ packet.player_id] = .{
+            name,
+            .{0, 0, 0}, .{0, 0, 0}, .{0, 0, 0},
+            false
+        };
+
+        if packet.player_id != player_id {
+            buf: [1024] u8;
+            chat_messages << (conv.format(buf, "{} joined the server!", name) |> string.alloc_copy());
         }
+    }
+}
 
-        case .Chat_Message {
-            chat_packet := cast(^packets.Chat_Message) packet;
+#local Connection_Rejected_Handle :: struct {
+    use base := Packet_Handler.{ .Connection_Rejected };
 
-            buf: [1024] u8;
-            msg: str;
-
-            sender := ^other_players[~~ chat_packet.sender_id];
-            if sender != null {
-                msg = conv.format(buf, "[{}] {}\n", sender.name, str.{
-                    ~~ ^chat_packet.message_data,
-                    ~~ chat_packet.message_length,
-                });
-            } else {
-                msg = .{
-                    ~~ ^chat_packet.message_data,
-                    ~~ chat_packet.message_length,
-                };
-            }
+    handle :: (packet: ^packets.Connection_Rejected) {
+        @NetworkErrors // Handle this case.
+        printf("Connection refused: {}\n", packet.reason);
 
-            chat_messages << string.alloc_copy(msg);
-        }
+        pop_game_state();
+        push_game_state(Connect_Menu, null);
+    }
+}
+
+#local Chat_Message_Handle :: struct {
+    use base := Packet_Handler.{ .Chat_Message };
 
-        case .Player_Moved {
-            moved := cast(^packets.Player_Moved) packet;
-            if moved.player_id == player_id do return;
+    handle :: (packet: ^packets.Chat_Message) {
+        buf: [1024] u8;
+        msg: str;
 
-            player := ^other_players[~~ moved.player_id];
-            player.position  = moved.position;
-            player.velocity  = moved.velocity;
-            player.facing    = moved.facing;
-            player.on_ground = moved.on_ground;
+        sender := map.get_ptr(^other_players, ~~ packet.sender_id);
+        if sender != null {
+            msg = conv.format(buf, "[{}] {}\n", sender.name, packet->message());
+        } else {
+            msg = packet->message();
         }
 
-        case .Block_Updates {
-            block_updates := cast(^packets.Block_Updates) packet;
+        chat_messages << string.alloc_copy(msg);
+    }
+}
 
-            update_count := block_updates.update_count;
-            updates := ([] packets.Block_Updates.Update).{ ~~^block_updates.updates, ~~update_count };
-            for updates {
-                pos := it.position;
-                world_set_block(world, pos.x, pos.y, pos.z, it.new_block);
-            }
+#local Player_Moved_Handle :: struct {
+    use base := Packet_Handler.{ .Player_Moved };
+
+    handle :: (packet: ^packets.Player_Moved) {
+        if packet.player_id == player_id do return;
+
+        player := map.get_ptr(^other_players, ~~ packet.player_id);
+        player.position  = packet.position;
+        player.velocity  = packet.velocity;
+        player.facing    = packet.facing;
+        player.on_ground = packet.on_ground;
+    }
+}
+
+#local Block_Updates_Handle :: struct {
+    use base := Packet_Handler.{ .Block_Updates };
+
+    handle :: (packet: ^packets.Block_Updates) {
+        updates := packet->updates();
+        for updates {
+            pos := it.position;
+            world_set_block(world, pos.x, pos.y, pos.z, it.new_block);
         }
     }
 }
 
+net_handle_packet :: (packet_data: [] u8) {
+    packet := cast(^packets.Packet_Base) packet_data.data;
+    if packet_handles[~~ packet.type] != null_proc {
+        packet_handles[~~ packet.type](packet);
+    }
+}
+
 net_send_connect :: (name: str) {
     msg := cast(^packets.Connect) calloc(sizeof packets.Connect + name.count);
     msg.type = .Connect;
@@ -173,7 +204,7 @@ net_send_block_updates :: (updates: [] packets.Block_Updates.Update) {
     block_updates.type = .Block_Updates;
     block_updates.update_count = ~~updates.count;
 
-    block_update := cast(^packets.Block_Updates.Update) ^block_updates.updates;
+    block_update := cast(^packets.Block_Updates.Update) ^block_updates.update_data;
     for updates.count {
         block_update[it].position  = updates[it].position;
         block_update[it].new_block = updates[it].new_block;
index 9fd480ac237b4aa60a8a2a7a4cbe372bea57a230..a81ae80587ae3896d27abfa78a9c79032d2a3bb0 100644 (file)
@@ -62,10 +62,7 @@ handle_packet :: (peer: ^onet.Peer, packet_data: [] u8) {
                 onet.peer_send(peer, 0, p);
             }
 
-            name := str.{
-                ~~ ^connect_packet.name_data,
-                ~~connect_packet.name_length
-            };
+            name := connect_packet->name();
 
             defer next_player_id += 1;
             connected_players[next_player_id] = .{
index be3312a7ca1b1f67fb9ab8acff177665d08a587a..53d839dfcf0e6eb311c2f24f4aaef8ac78d79709 100644 (file)
@@ -17,6 +17,7 @@ Type :: enum (u8) {
 
     Block_Updates;
 }
+#match (package core.hash).to_u32 macro (t: Type) => cast(u32) t;
 
 Packet_Base :: struct #pack {
     type: Type;
@@ -27,6 +28,8 @@ Connect :: struct #pack {
     client_version: u32;
     name_length: u16;
     name_data: void;
+
+    name :: (use conn: ^Connect) => str.{~~^name_data, ~~name_length};
 }
 
 Verify_Connect :: struct #pack {
@@ -54,6 +57,8 @@ Player_Joined :: struct #pack {
     player_id: u16;
     name_length: u16;
     name_data: void;
+
+    name :: (use pj: ^Player_Joined) => str.{~~^name_data, ~~name_length};
 }
 
 Player_Left :: struct #pack {
@@ -75,15 +80,21 @@ Chat_Message :: struct #pack {
     sender_id: u16; // Should this be a Player ID?
     message_length: u16;
     message_data:   void;
+
+    message :: (use msg: ^Chat_Message) => str.{~~^message_data, ~~message_length};
 }
 
 Block_Updates :: struct #pack {
     use base := Packet_Base.{ .Block_Updates };
     update_count: u16;
-    updates:      void;
+    update_data:  void;
 
     Update :: struct {
         position:  Vector3i;
         new_block: Block;
     }
+
+    updates :: (use bu: ^Block_Updates) => ([] Update).{
+        ~~^update_data, ~~update_count
+    };
 }
\ No newline at end of file