#ifdef VERTEX_SHADER
-layout(location = 0) in vec2 a_pos;
+layout(location = 0) in vec3 a_pos;
layout(location = 1) in vec4 a_col;
-layout(std140) uniform u_window_matrix_block {
- mat4 u_view;
-};
-
layout(std140) uniform u_world_matrix_block {
+ mat4 u_view;
mat4 u_world;
mat4 u_model;
};
void main() {
- gl_Position = u_view * u_world * u_model * vec4(a_pos, 0, 1);
+ gl_Position = u_view * u_world * u_model * vec4(a_pos, 1);
v_col = a_col;
}
world: ^World;
selected_block: Vector3i;
+Player_Vertex :: struct {
+ pos: Vector3;
+ col: Color;
+}
+player_mesh: ^Mesh(Player_Vertex);
+player_shader: Shader;
+
Game_State :: struct {
init :: game_init;
update :: game_update;
game_init :: (_: rawptr) {
world_shader = shader_make("assets/shaders/world.glsl");
+ player_shader = shader_make("assets/shaders/basic.glsl");
shader_link_world_matrix_block(world_shader);
+ shader_link_world_matrix_block(player_shader);
shader_set_uniform(world_shader, #cstr "u_fog_start", 50.0f);
shader_set_uniform(world_shader, #cstr "u_fog_range", 10.0f);
world = world_make();
player = player_make();
player.camera = ^camera;
+
+ player_mesh = mesh_make(Player_Vertex.[
+ .{ .{-1, -1, -1}, .{1, 0, 0, 1}, },
+ .{ .{ 1, -1, -1}, .{1, 0, 0, 1}, },
+ .{ .{ 1, 1, -1}, .{1, 0, 0, 1}, },
+ .{ .{-1, -1, -1}, .{1, 0, 0, 1}, },
+ .{ .{ 1, 1, -1}, .{1, 0, 0, 1}, },
+ .{ .{-1, 1, -1}, .{1, 0, 0, 1}, },
+
+ .{ .{-1, -1, -1}, .{1, 0, 0, 1}, },
+ .{ .{-1, 1, -1}, .{1, 0, 0, 1}, },
+ .{ .{-1, 1, 1}, .{1, 0, 0, 1}, },
+ .{ .{-1, -1, -1}, .{1, 0, 0, 1}, },
+ .{ .{-1, 1, 1}, .{1, 0, 0, 1}, },
+ .{ .{-1, -1, 1}, .{1, 0, 0, 1}, },
+
+ .{ .{-1, -1, -1}, .{1, 0, 0, 1}, },
+ .{ .{-1, -1, 1}, .{1, 0, 0, 1}, },
+ .{ .{ 1, -1, 1}, .{1, 0, 0, 1}, },
+ .{ .{-1, -1, -1}, .{1, 0, 0, 1}, },
+ .{ .{ 1, -1, 1}, .{1, 0, 0, 1}, },
+ .{ .{ 1, -1, -1}, .{1, 0, 0, 1}, },
+ ], .[]);
}
game_update :: (_: rawptr, dt: f32) {
world_move_center(world, player_chunk);
world_update(world, dt);
+ send_movement_timeout -= dt;
+ if send_movement_timeout < 0 {
+ send_movement_timeout = 0.05f;
+ net_send_movement_update(player.body.pos, player.body.vel, .{1,0,0});
+ }
+
if is_key_just_down(GLFW_KEY_F7) {
debug_screen = !debug_screen;
}
update_world_matrix();
}
+#local {
+ send_movement_timeout := 0.0f;
+}
+
+
game_draw :: (_: rawptr) {
draw_scene();
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);
+
+ shader_use(player_shader);
+ for^ other_players.entries {
+ update_model_matrix(it.value.position);
+ mesh_draw(player_mesh);
+ }
}
@Temporary
push_game_state(Game_State, null);
}
+ case .Player_Joined {
+ joined_packet := cast(^packets.Player_Joined) packet;
+ if joined_packet.player_id == player_id do return;
+
+ buf: [1024] u8;
+ chat_messages << (
+ conv.format(buf, "{} joined the server!", str.{
+ ~~ ^joined_packet.name_data,
+ ~~ joined_packet.name_length
+ })
+ |> string.alloc_copy()
+ );
+
+ other_players[~~ joined_packet.player_id] = .{
+ .{0, 0, 0}, .{0, 0, 0}, .{0, 0, 0}
+ };
+ }
+
case .Connection_Rejected {
cr_packet := cast(^packets.Connection_Rejected) packet;
printf("Connection refused: {}\n", cr_packet.reason);
~~ chat_packet.message_length,
});
}
+
+ case .Player_Moved {
+ moved := cast(^packets.Player_Moved) packet;
+
+ other_players[~~ moved.player_id] = .{
+ position = moved.position,
+ velocity = moved.velocity,
+ facing = moved.facing,
+ };
+ }
}
}
p := new(onet.Packet);
p.flags |= .Reliable;
p.data = .{ ~~msg, sizeof packets.Connect + name.count };
+ p.free_data = true;
onet.peer_send(peer, 0, p);
}
p := new(onet.Packet);
p.flags |= .Reliable;
p.data = .{ ~~msg, sizeof packets.Chat_Message + message.count };
+ p.free_data = true;
+ onet.peer_send(peer, 0, p);
+}
+
+net_send_movement_update :: (position: Vector3, velocity: Vector3, facing: Vector3) {
+ movement := new(packets.Player_Moved);
+ movement.type = .Player_Moved;
+ movement.player_id = player_id;
+ movement.position = position;
+ movement.velocity = velocity;
+ movement.facing = facing;
+
+ p := new(onet.Packet);
+ p.data = .{ ~~movement, sizeof typeof *movement };
+ p.free_data = true;
onet.peer_send(peer, 0, p);
}
+Remote_Player :: struct {
+ position: Vector3;
+ velocity: Vector3;
+ facing: Vector3;
+}
+
+@TEMPORARY
+other_players: Map(u32, Remote_Player);
+
+
#local {
use package core
onet :: package onyx_net
#load "./../src/config"
#load "server"
+#load "./../client/utils/vecmath"
#load "./../shared/packets"
#load "onyx-net/src/module"
id: u16;
name: str;
peer: ^onet.Peer;
+
+ position: Vector3 = .{0,0,0};
+ velocity: Vector3 = .{0,0,0};
+ facing: Vector3 = .{0,0,0};
}
max_connected_players := 8;
respond_with_error(.Server_Full);
}
+
+ // Send a verify connect packet
+ {
+ msg := new(packets.Verify_Connect);
+ msg.type = .Verify_Connect;
+ msg.player_id = ~~next_player_id;
+
+ p := new(onet.Packet);
+ p.flags |= .Reliable;
+ p.data = any_to_buffer(msg);
+ p.free_data = true;
+ onet.peer_send(peer, 0, p);
+ }
+
name := str.{
~~ ^connect_packet.name_data,
~~connect_packet.name_length
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);
- }
-
- // Send a verify connect packet
- msg := new(packets.Verify_Connect);
- msg.type = .Verify_Connect;
- msg.player_id = ~~next_player_id;
+ send_player_joined(~~next_player_id, connected_players[next_player_id].name, null);
- p := new(onet.Packet);
- p.flags |= .Reliable;
- p.data = any_to_buffer(msg);
- p.free_data = true;
- onet.peer_send(peer, 0, p);
+ for^ connected_players.entries {
+ send_player_joined(it.value.id, it.value.name, peer);
+ }
respond_with_error :: macro (reason: packets.Connection_Rejected.Reason) {
msg := new(packets.Connection_Rejected);
packet.free_data = true;
onet.host_broadcast(host, 0, packet);
}
+
+ case .Player_Moved {
+ moved := cast(^packets.Player_Moved) packet;
+ player := ^connected_players[~~ moved.player_id];
+ if player == null do return;
+
+ player.position = moved.position;
+ player.velocity = moved.velocity;
+ player.facing = moved.facing;
+
+ packet := new(onet.Packet);
+ packet.data = memory.copy_slice(packet_data);
+ packet.free_data = true;
+ onet.host_broadcast(host, 0, packet);
+ }
+ }
+}
+
+send_player_joined :: (player_id: u16, player_name: str, dest: ^onet.Peer) {
+ joined, packet_size := new_with_extra(packets.Player_Joined, player_name.count);
+ joined.type = .Player_Joined;
+ joined.player_id = player_id;
+ joined.name_length = ~~ player_name.count;
+ memory.copy(~~ ^joined.name_data, player_name.data, player_name.count);
+
+ packet := new(onet.Packet);
+ packet.flags |= .Reliable;
+ packet.data = .{ ~~joined, packet_size };
+ packet.free_data = true;
+
+ if dest == null {
+ onet.host_broadcast(host, 0, packet);
+ } else {
+ onet.peer_send(dest, 0, packet);
}
}
package packets
+use package main { Vector3 }
Type :: enum (u8) {
Connect;
reason: Reason;
}
+Player_Joined :: struct #pack {
+ use base: Packet_Base;
+ player_id: u16;
+ name_length: u16;
+ name_data: void;
+}
+
+Player_Left :: struct #pack {
+ use base: Packet_Base;
+ player_id: u16;
+}
+Player_Moved :: struct #pack {
+ use base: Packet_Base;
+ player_id: u16;
+ position: Vector3;
+ velocity: Vector3;
+ facing: Vector3;
+}
Chat_Message :: struct #pack {
use base: Packet_Base;