+
+
+Networking Design
+=================
+
+Packets (Client to Server):
+ - Connect
+ - Disconnect
+ - Player_Moved
+
+Packets (Server to Client):
+ - Verify_Connect
+ - Player_Joined
+ - Player_Left
+ - Player_Moved
\ No newline at end of file
// Primary source files
#load "./../src/config"
-#load "main"
+#load_all "./."
#load_all "./gfx"
#load_all "./utils"
#load_all "./world"
--- /dev/null
+
+use package core
+use package glfw3
+use package opengles
+use package stb_truetype
+use package core.intrinsics.onyx { __initialize }
+#local onet :: package onyx_net
+
+#local {
+ world_shader: Shader;
+
+ chat_font: Font;
+
+ fog_color :: Vector3.{ 0.6, 0.6, 0.6 };
+}
+
+font: Font;
+player: Player;
+world: ^World;
+selected_block: Vector3i;
+
+
+@Temporary host: ^onet.Host;
+@Temporary peer: ^onet.Peer;
+
+
+game_init :: () {
+ world_shader = shader_make("assets/shaders/world.glsl");
+
+ shader_link_world_matrix_block(world_shader);
+ shader_set_uniform(world_shader, #cstr "u_fog_start", 50.0f);
+ shader_set_uniform(world_shader, #cstr "u_fog_range", 10.0f);
+
+ font = font_lookup(.{"./assets/fonts/calibri.ttf", 32});
+ chat_font = font_lookup(.{"./assets/fonts/calibri.ttf", 16});
+
+ shader_use(world_shader);
+ world = world_make();
+ player = player_make();
+ player.camera = ^camera;
+
+ __initialize(^camera);
+ camera_set_fov(^camera, 75);
+ ww, wh: i32;
+ glfwGetWindowSize(window, ^ww, ^wh);
+ camera_set_window_size(^camera, ~~ww, ~~wh);
+
+ addr: net.Socket_Address;
+ addr.addr = net.str_to_ipv4("127.0.0.1");
+ addr.port = (package runtime.vars).Game_Port;
+ host', _ := onet.host_create(null, 1);
+ peer = onet.host_connect(host, ^addr, 2);
+}
+
+game_update :: (dt: f32) {
+ for host->get_events(timeout=0) {
+ if it.type == .Connection {
+ chat_messages << "[Connected to server]";
+ }
+
+ if it.type == .Message {
+ chat_messages << string.alloc_copy(it.data);
+ }
+ }
+
+ if is_key_just_down(GLFW_KEY_ESCAPE) {
+ if cursor_grabbed {
+ toggle_cursor_grabbed();
+ } else {
+ glfwSetWindowShouldClose(window, true);
+ }
+ }
+
+ if cursor_grabbed {
+ player_update_controls(^player, dt);
+ player_update(^player, dt);
+ }
+
+ player_update_physics(^player, dt);
+ player_chunk := world_position_to_chunk(world, player.body.pos);
+ world_move_center(world, player_chunk);
+ world_update(world, dt);
+
+ if is_key_just_down(GLFW_KEY_F7) {
+ debug_screen = !debug_screen;
+ }
+
+ update_world_matrix();
+}
+
+game_draw :: () {
+ draw_scene();
+
+ ww, wh: i32;
+ glfwGetWindowSize(window, ^ww, ^wh);
+ font_print(font, ~~(ww / 2), ~~(wh / 2), ".");
+
+ //
+ // A very hacky wait to have the click the capture mouse.
+ immediate_push_scissor(0, 0, 0, 0);
+ if !cursor_grabbed {
+ if draw_button(.{ 0, 0, ~~ww, ~~wh }, "") {
+ toggle_cursor_grabbed();
+ }
+ }
+ immediate_pop_scissor();
+
+ draw_chat();
+}
+
+draw_scene :: () {
+ glClearColor(fog_color.x, fog_color.y, fog_color.z, 1);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ shader_use(world_shader);
+ shader_set_uniform(world_shader, #cstr "u_fog_color", fog_color);
+ shader_set_uniform(world_shader, #cstr "u_texture", 0);
+ glEnable(GL_DEPTH_TEST);
+ world_draw(world);
+
+ glLineWidth(2);
+ chunk_highlight_block(~~selected_block.x, ~~selected_block.y, ~~selected_block.z);
+}
+
+
+chat_messages: [..] [] u8;
+pending_message: [..] u8;
+
+draw_chat :: () {
+ glDisable(GL_DEPTH_TEST);
+
+ ww, wh: i32;
+ glfwGetWindowSize(window, ^ww, ^wh);
+ immediate_set_color(.{0.2, 0.2, 0.2, 0.8});
+ immediate_rectangle(0, ~~(wh - 300), 400, 300);
+
+ font_set_color(.{1, 1, 1});
+ y := cast(f32) (wh - 32);
+ while i := cast(i32) chat_messages.count - 1; i >= 0 {
+ defer i -= 1;
+ y -= 18;
+ font_draw(chat_font, 10, y, chat_messages[i]);
+ }
+
+ if draw_textbox(.{0, ~~(wh - 32), 400, 32}, ^pending_message) == .Enter_Pressed {
+ if pending_message.count > 0 {
+ send_message(string.alloc_copy(pending_message));
+ array.clear(^pending_message);
+ }
+ }
+
+ send_message :: (message: [] u8) {
+ packet := new(onet.Packet);
+ packet.flags |= .Reliable;
+ packet.data = message;
+ onet.peer_send(peer, 0, packet);
+ }
+}
+
+cursor_grabbed := false;
+toggle_cursor_grabbed :: () {
+ cursor_grabbed = !cursor_grabbed;
+
+ if cursor_grabbed {
+ glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
+
+ if glfwRawMouseMotionSupported() == GLFW_TRUE {
+ glfwSetInputMode(window, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE);
+ }
+ } else {
+ glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
+
+ if glfwRawMouseMotionSupported() == GLFW_TRUE {
+ glfwSetInputMode(window, GLFW_RAW_MOUSE_MOTION, GLFW_FALSE);
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+use package glfw3
+
+@GlobalVariable window: GLFWwindow_p;
+
+debug_screen := false;
use package core
use package glfw3
use package opengles
-use package stb_truetype
-use package core.intrinsics.onyx { __initialize }
-#local onet :: package onyx_net
#local runtime :: package runtime
-#local {
- world_shader: Shader;
- font: Font;
- player: Player;
-
- chat_font: Font;
-
- fog_color :: Vector3.{ 0.6, 0.6, 0.6 };
-}
-
-world: ^World;
-selected_block: Vector3i;
-
-@GlobalVariable
-window: GLFWwindow_p;
-
-create_window :: () => {
- #if runtime.compiler_os == .Linux {
- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
- glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
- } else {
- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
- }
- window = glfwCreateWindow(1600, 900, #cstr "Voxel Shooter");
-
- glfwMakeContextCurrent(window);
- glfwSwapInterval(1);
- glfwSetWindowSizeCallback(window, "on_resize");
- glfwSetKeyCallback(window, "on_key");
- glfwSetMouseButtonCallback(window, "on_mouse_button");
-}
-
-#export "on_resize" (window: GLFWwindow_p, width, height: u32) {
- glViewport(0, 0, width, height);
- camera_set_window_size(^camera, ~~width, ~~height);
- update_view_matrix();
- update_window_matrix();
-}
-
-cursor_grabbed := false;
-toggle_cursor_grabbed :: () {
- cursor_grabbed = !cursor_grabbed;
-
- if cursor_grabbed {
- glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
-
- if glfwRawMouseMotionSupported() == GLFW_TRUE {
- glfwSetInputMode(window, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE);
- }
- } else {
- glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
-
- if glfwRawMouseMotionSupported() == GLFW_TRUE {
- glfwSetInputMode(window, GLFW_RAW_MOUSE_MOTION, GLFW_FALSE);
- }
- }
-}
-
-setup_opengl :: () {
+init :: () {
+ window = create_window();
glInit(glfwGetLoadProcAddress());
input_bind_glfw_events(window);
fonts_init();
immediate_init();
- world_shader = shader_make("assets/shaders/world.glsl");
-
- shader_link_world_matrix_block(world_shader);
- shader_set_uniform(world_shader, #cstr "u_fog_start", 50.0f);
- shader_set_uniform(world_shader, #cstr "u_fog_range", 10.0f);
-
- font = font_lookup(.{"./assets/fonts/calibri.ttf", 32});
- chat_font = font_lookup(.{"./assets/fonts/calibri.ttf", 16});
-
- shader_use(world_shader);
- world = world_make();
- player = player_make();
- player.camera = ^camera;
-
- __initialize(^camera);
- camera_set_fov(^camera, 75);
- ww, wh: i32;
- glfwGetWindowSize(window, ^ww, ^wh);
- camera_set_window_size(^camera, ~~ww, ~~wh);
+ game_init();
update_view_matrix();
update_world_matrix();
update_window_matrix();
}
-update :: (dt: f32) {
- input_update();
-
- if is_key_just_down(GLFW_KEY_ESCAPE) {
- if cursor_grabbed {
- toggle_cursor_grabbed();
- } else {
- glfwSetWindowShouldClose(window, true);
- }
- }
-
- if cursor_grabbed {
- player_update_controls(^player, dt);
- player_update(^player, dt);
+create_window :: () => {
+ #if runtime.compiler_os == .Linux {
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
+ glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
+ } else {
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
}
+ window := glfwCreateWindow(1600, 900, #cstr "Voxel Shooter");
- player_update_physics(^player, dt);
- player_chunk := world_position_to_chunk(world, player.body.pos);
- world_move_center(world, player_chunk);
- world_update(world, dt);
+ glfwMakeContextCurrent(window);
+ glfwSwapInterval(1);
+ glfwSetWindowSizeCallback(window, "on_resize");
- if is_key_just_down(GLFW_KEY_F7) {
- debug_screen = !debug_screen;
- }
+ return window;
+}
- update_world_matrix();
+#export "on_resize" (window: GLFWwindow_p, width, height: u32) {
+ glViewport(0, 0, width, height);
+ camera_set_window_size(^camera, ~~width, ~~height);
+ update_view_matrix();
+ update_window_matrix();
}
-#local {
- debug_screen := true;
- game_fps: i32;
+update :: (dt: f32) {
+ input_update();
+
+ game_update(dt);
}
draw :: () {
- defer ui_end_frame();
- defer input_post_update();
- draw_scene();
- draw_chat();
-
- ww, wh: i32;
- glfwGetWindowSize(window, ^ww, ^wh);
- font_print(font, ~~(ww / 2), ~~(wh / 2), ".");
-
- if !cursor_grabbed {
- if draw_button(.{ 200, 200, 200, 200 }, "Resume") {
- toggle_cursor_grabbed();
- }
- }
+ game_draw();
if debug_screen {
immediate_set_color(.{1, 0, 1, 0.5});
immediate_flush();
glfwSwapBuffers(window);
+ input_post_update();
+ ui_end_frame();
}
-draw_scene :: () {
- glClearColor(fog_color.x, fog_color.y, fog_color.z, 1);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- shader_use(world_shader);
- shader_set_uniform(world_shader, #cstr "u_fog_color", fog_color);
- shader_set_uniform(world_shader, #cstr "u_texture", 0);
- glEnable(GL_DEPTH_TEST);
- world_draw(world);
-
- glLineWidth(2);
- chunk_highlight_block(~~selected_block.x, ~~selected_block.y, ~~selected_block.z);
-}
-
-chat_messages: [..] [] u8;
-pending_message: [..] u8;
-
-draw_chat :: () {
- glDisable(GL_DEPTH_TEST);
-
- ww, wh: i32;
- glfwGetWindowSize(window, ^ww, ^wh);
- immediate_set_color(.{0.2, 0.2, 0.2, 0.8});
- immediate_rectangle(0, ~~(wh - 300), 400, 300);
-
- font_set_color(.{1, 1, 1});
- y := cast(f32) (wh - 32);
- while i := cast(i32) chat_messages.count - 1; i >= 0 {
- defer i -= 1;
- y -= 18;
- font_draw(chat_font, 10, y, chat_messages[i]);
- }
-
- if draw_textbox(.{0, ~~(wh - 32), 400, 32}, ^pending_message) == .Enter_Pressed {
- if pending_message.count > 0 {
- send_message(string.alloc_copy(pending_message));
- array.clear(^pending_message);
- }
- }
-
- send_message :: (message: [] u8) {
- packet := new(onet.Packet);
- packet.flags |= .Reliable;
- packet.data = message;
- onet.peer_send(peer, 0, packet);
- }
-}
-
-host: ^onet.Host;
-peer: ^onet.Peer;
-
main_loop :: () {
last := glfwGetTime();
now := last;
frame_count := 0;
while !glfwWindowShouldClose(window) {
- for host->get_events(timeout=0) {
- if it.type == .Message {
- chat_messages << string.alloc_copy(it.data);
- }
- }
-
glfwPollEvents();
now = glfwGetTime();
os.exit(1);
}
- addr: net.Socket_Address;
- addr.addr = net.str_to_ipv4("127.0.0.1");
- addr.port = 5123;
- host', _ := onet.host_create(null, 1);
- println(_);
- peer = onet.host_connect(host, ^addr, 2);
-
- create_window();
- setup_opengl();
+ init();
main_loop();
}
+
+
+
+#local game_fps: i32;
#local {
- keys_this_frame : Set(Key_Descriptor) // Keys currently being pressed this frame
- keys_last_frame : Set(Key_Descriptor) // Keys being pressed in the last frame
+ keys_this_frame : Set(Key_Descriptor) // Keys currently being pressed this frame
+ keys_last_frame : Set(Key_Descriptor) // Keys being pressed in the last frame
- key_codepoints : [..] u32
+ key_codepoints : [..] u32
- buttons_this_frame: [8] bool // Mouse buttons being pressed this frame
- buttons_last_frame: [8] bool // Mouse buttons being pressed last frame
+ buttons_this_frame: [8] bool // Mouse buttons being pressed this frame
+ buttons_last_frame: [8] bool // Mouse buttons being pressed last frame
- scroll_x: f64
- scroll_y: f64
+ scroll_x: f64
+ scroll_y: f64
- character_mode := false;
+ character_mode := false;
}
#init () {
- set.init(^keys_this_frame);
- set.init(^keys_last_frame);
+ set.init(^keys_this_frame);
+ set.init(^keys_last_frame);
}
Key_Descriptor :: struct {
- key: u32;
- scancode: u32 = 0;
- mod: u32 = 0;
+ key: u32;
+ scancode: u32 = 0;
+ mod: u32 = 0;
}
#match hash.to_u32 (use x: Key_Descriptor) => hash.to_u32(key);
#operator == macro (x, y: Key_Descriptor) => x.key == y.key;
}
input_post_update :: () {
- set.clear(^keys_last_frame);
- for keys_this_frame.entries do keys_last_frame << it.value;
+ set.clear(^keys_last_frame);
+ for keys_this_frame.entries do keys_last_frame << it.value;
- for 8 do buttons_last_frame[it] = buttons_this_frame[it];
+ for 8 do buttons_last_frame[it] = buttons_this_frame[it];
- last_mouse_x = mouse_x;
- last_mouse_y = mouse_y;
- scroll_x = 0;
- scroll_y = 0;
+ last_mouse_x = mouse_x;
+ last_mouse_y = mouse_y;
+ scroll_x = 0;
+ scroll_y = 0;
- array.clear(^key_codepoints);
+ array.clear(^key_codepoints);
}
input_get_chars_this_frame :: () -> [] u32 {
- return key_codepoints;
+ return key_codepoints;
}
input_get_keys_this_frame :: () -> Iterator(Key_Descriptor) {
}
index = 0;
- return .{ null, next };
+ return .{ null, next };
}
input_capture_keys :: () {
- character_mode = true;
+ character_mode = true;
}
input_release_keys :: () {
- character_mode = false;
+ character_mode = false;
}
is_key_down :: (key) => !character_mode && set.has(^keys_this_frame, .{key});
is_button_just_up :: (button) => !buttons_this_frame[button] && buttons_last_frame[button];
#local {
- last_mouse_x: f64;
- last_mouse_y: f64;
+ last_mouse_x: f64;
+ last_mouse_y: f64;
- mouse_x: f64;
- mouse_y: f64;
+ mouse_x: f64;
+ mouse_y: f64;
}
mouse_get_delta :: () -> (f64, f64) {
- return mouse_x - last_mouse_x, mouse_y - last_mouse_y;
+ return mouse_x - last_mouse_x, mouse_y - last_mouse_y;
}
mouse_get_delta_vector :: () -> Vector2 {
- dmx, dmy := mouse_get_delta();
- return .{ ~~dmx, ~~dmy };
+ dmx, dmy := mouse_get_delta();
+ return .{ ~~dmx, ~~dmy };
}
mouse_get_position :: () -> (f64, f64) {
- mx, my := mouse_x, mouse_y;
- #if #defined(Mouse_Offset_Function) {
- scroll := Mouse_Offset_Function();
- mx -= ~~ scroll.x;
- my -= ~~ scroll.y;
- }
- return mx, my;
+ mx, my := mouse_x, mouse_y;
+ #if #defined(Mouse_Offset_Function) {
+ scroll := Mouse_Offset_Function();
+ mx -= ~~ scroll.x;
+ my -= ~~ scroll.y;
+ }
+ return mx, my;
}
mouse_get_position_vector :: () -> Vector2 {
- mx, my := mouse_x, mouse_y;
- #if #defined(Mouse_Offset_Function) {
- scroll := Mouse_Offset_Function();
- mx -= ~~ scroll.x;
- my -= ~~ scroll.y;
- }
- return .{ ~~mx, ~~my };
+ mx, my := mouse_x, mouse_y;
+ #if #defined(Mouse_Offset_Function) {
+ scroll := Mouse_Offset_Function();
+ mx -= ~~ scroll.x;
+ my -= ~~ scroll.y;
+ }
+ return .{ ~~mx, ~~my };
}
mouse_get_scroll :: () -> (f64, f64) {
- return scroll_x, scroll_y;
+ return scroll_x, scroll_y;
}
mouse_get_scroll_vector :: () -> Vector2 {
- return .{ ~~scroll_x, ~~scroll_y };
+ return .{ ~~scroll_x, ~~scroll_y };
}
input_bind_glfw_events :: (window: GLFWwindow_p) {
- glfwSetKeyCallback(window, INPUT_KEY_EVENT);
- glfwSetCharCallback(window, INPUT_CHAR_EVENT);
- glfwSetMouseButtonCallback(window, INPUT_BUTTON_EVENT);
- glfwSetScrollCallback(window, INPUT_SCROLL_EVENT);
+ glfwSetKeyCallback(window, INPUT_KEY_EVENT);
+ glfwSetCharCallback(window, INPUT_CHAR_EVENT);
+ glfwSetMouseButtonCallback(window, INPUT_BUTTON_EVENT);
+ glfwSetScrollCallback(window, INPUT_SCROLL_EVENT);
}
#local {
- INPUT_BUTTON_EVENT :: "__input_button_event"
- INPUT_KEY_EVENT :: "__input_key_event"
- INPUT_SCROLL_EVENT :: "__input_scroll_event"
- INPUT_CHAR_EVENT :: "__input_char_event"
+ INPUT_BUTTON_EVENT :: "__input_button_event"
+ INPUT_KEY_EVENT :: "__input_key_event"
+ INPUT_SCROLL_EVENT :: "__input_scroll_event"
+ INPUT_CHAR_EVENT :: "__input_char_event"
}
#export INPUT_BUTTON_EVENT (window: GLFWwindow_p, button, action, mod: u32) {
- if action == GLFW_PRESS {
- buttons_this_frame[button] = true;
- }
+ if action == GLFW_PRESS {
+ buttons_this_frame[button] = true;
+ }
- if action == GLFW_RELEASE {
- buttons_this_frame[button] = false;
- }
+ if action == GLFW_RELEASE {
+ buttons_this_frame[button] = false;
+ }
}
#export INPUT_KEY_EVENT (window: GLFWwindow_p, key, scancode, action, mod: u32) {
- if action == GLFW_PRESS {
- keys_this_frame << .{ key, scancode, mod };
- }
+ if action == GLFW_PRESS {
+ keys_this_frame << .{ key, scancode, mod };
+ }
- if action == GLFW_REPEAT {
- set.remove(^keys_last_frame, .{key});
- }
+ if action == GLFW_REPEAT {
+ set.remove(^keys_last_frame, .{key});
+ }
- if action == GLFW_RELEASE {
- set.remove(^keys_this_frame, .{ key });
- }
+ if action == GLFW_RELEASE {
+ set.remove(^keys_this_frame, .{ key });
+ }
}
#export INPUT_CHAR_EVENT (window: GLFWwindow_p, codepoint: u32) {
- if !character_mode do return;
- key_codepoints << codepoint;
+ if !character_mode do return;
+ key_codepoints << codepoint;
}
#export INPUT_SCROLL_EVENT (window: GLFWwindow_p, xoff, yoff: f64) {
- scroll_x = xoff;
- scroll_y = yoff;
+ scroll_x = xoff;
+ scroll_y = yoff;
}
main :: (args) => {
addr: net.Socket_Address;
- addr.port = 5123;
+ addr.port = (package runtime.vars).Game_Port;
host, err := onet.host_create(^addr, 16);
if err != .None {
while true {
for host->get_events(timeout=1000) {
- if it.type == .Connection do printf("{*}\n", it);
- if it.type == .Disconnection do printf("{*}\n", it);
+ 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 {
+ printf("Disconnection from {}:{}\n", net.ipv4_to_str(it.peer.addr.addr), it.peer.addr.port);
+ }
if it.type == .Message {
printf("Message: {}\n", it.data);
--- /dev/null
+
+package packet
+
+Type :: enum (u8) {
+ Connect;
+ Verify_Connect;
+ Disconnect;
+
+ Player_Joined;
+ Player_Left;
+ Player_Moved;
+}
+
+Packet_Base :: struct #pack {
+ type: Type;
+}
+
+Connect :: struct #pack {
+ use base: Packet_Base;
+}
+
+
+
+
+