added client server shared

This commit is contained in:
Vicente Ferrari Smith 2025-12-21 23:02:59 +01:00
parent 6f9de0f566
commit 7d60843598
10 changed files with 482 additions and 0 deletions

27
.zed/debug.json Normal file
View File

@ -0,0 +1,27 @@
// Project-local debug tasks
//
// For more documentation on how to configure debug tasks,
// see: https://zed.dev/docs/debugger
[
{
"adapter": "CodeLLDB",
"label": "zig build run",
"request": "launch",
"build": {
"label": "zig build",
"command": "zig",
"args": ["build"],
"env": {},
"cwd": null,
"use_new_terminal": false,
"allow_concurrent_runs": false,
"reveal": "always",
"reveal_target": "dock",
"hide": "never",
//"tags": [],
"shell": "system",
"show_summary": false,
"show_command": false,
},
},
]

103
.zed/tasks.json Normal file
View File

@ -0,0 +1,103 @@
// Project tasks configuration. See https://zed.dev/docs/tasks for documentation.
//
// Example:
[
{
"label": "Example task",
"command": "for i in {1..5}; do echo \"Hello $i/5\"; sleep 1; done",
//"args": [],
// Env overrides for the command, will be appended to the terminal's environment from the settings.
"env": { "foo": "bar" },
// Current working directory to spawn the command into, defaults to current project root.
//"cwd": "/path/to/working/directory",
// Whether to use a new terminal tab or reuse the existing one to spawn the process, defaults to `false`.
"use_new_terminal": false,
// Whether to allow multiple instances of the same task to be run, or rather wait for the existing ones to finish, defaults to `false`.
"allow_concurrent_runs": false,
// What to do with the terminal pane and tab, after the command was started:
// * `always` always show the task's pane, and focus the corresponding tab in it (default)
// * `no_focus` always show the task's pane, add the task's tab in it, but don't focus it
// * `never` do not alter focus, but still add/reuse the task's tab in its pane
"reveal": "always",
// Where to place the task's terminal item after starting the task:
// * `dock` in the terminal dock, "regular" terminal items' place (default)
// * `center` in the central pane group, "main" editor area
"reveal_target": "dock",
// What to do with the terminal pane and tab, after the command had finished:
// * `never` Do nothing when the command finishes (default)
// * `always` always hide the terminal tab, hide the pane also if it was the last tab in it
// * `on_success` hide the terminal tab on task success only, otherwise behaves similar to `always`
"hide": "never",
// Which shell to use when running a task inside the terminal.
// May take 3 values:
// 1. (default) Use the system's default terminal configuration in /etc/passwd
// "shell": "system"
// 2. A program:
// "shell": {
// "program": "sh"
// }
// 3. A program with arguments:
// "shell": {
// "with_arguments": {
// "program": "/bin/bash",
// "args": ["--login"]
// }
// }
"shell": "system",
// Whether to show the task line in the output of the spawned task, defaults to `true`.
"show_summary": true,
// Whether to show the command line in the output of the spawned task, defaults to `true`.
"show_command": true,
// Represents the tags for inline runnable indicators, or spawning multiple tasks at once.
// "tags": []
},
{
"label": "zig build",
"command": "zig build",
//"args": [],
// Env overrides for the command, will be appended to the terminal's environment from the settings.
//"env": { "foo": "bar" },
// Current working directory to spawn the command into, defaults to current project root.
//"cwd": "/path/to/working/directory",
// Whether to use a new terminal tab or reuse the existing one to spawn the process, defaults to `false`.
"use_new_terminal": false,
// Whether to allow multiple instances of the same task to be run, or rather wait for the existing ones to finish, defaults to `false`.
"allow_concurrent_runs": false,
// What to do with the terminal pane and tab, after the command was started:
// * `always` always show the task's pane, and focus the corresponding tab in it (default)
// * `no_focus` always show the task's pane, add the task's tab in it, but don't focus it
// * `never` do not alter focus, but still add/reuse the task's tab in its pane
"reveal": "always",
// Where to place the task's terminal item after starting the task:
// * `dock` in the terminal dock, "regular" terminal items' place (default)
// * `center` in the central pane group, "main" editor area
"reveal_target": "dock",
// What to do with the terminal pane and tab, after the command had finished:
// * `never` Do nothing when the command finishes (default)
// * `always` always hide the terminal tab, hide the pane also if it was the last tab in it
// * `on_success` hide the terminal tab on task success only, otherwise behaves similar to `always`
"hide": "never",
// Which shell to use when running a task inside the terminal.
// May take 3 values:
// 1. (default) Use the system's default terminal configuration in /etc/passwd
// "shell": "system"
// 2. A program:
// "shell": {
// "program": "sh"
// }
// 3. A program with arguments:
// "shell": {
// "with_arguments": {
// "program": "/bin/bash",
// "args": ["--login"]
// }
// }
"shell": "system",
// Whether to show the task line in the output of the spawned task, defaults to `true`.
"show_summary": true,
// Whether to show the command line in the output of the spawned task, defaults to `true`.
"show_command": true,
// Represents the tags for inline runnable indicators, or spawning multiple tasks at once.
// "tags": []
},
]

77
src/client/main.zig Normal file
View File

@ -0,0 +1,77 @@
const std = @import("std");
const zm = @import("zmath");
const shared = @import("shared");
var stdout: *std.io.Writer = undefined;
pub fn main() !void {
std.log.info("Helllo Client!", .{});
var dbg_allocator = std.heap.DebugAllocator(.{}).init;
defer _ = dbg_allocator.deinit();
const allocator = dbg_allocator.allocator();
var stdout_buffer: [1024]u8 = undefined;
var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
stdout = &stdout_writer.interface;
std.log.info("{s}", .{@typeName(shared.chunk.Chunk)});
try stdout.flush();
const address = try std.net.Address.parseIp4("127.0.0.1", shared.protocol.SERVER_PORT);
var connection = try std.net.tcpConnectToAddress(address);
std.log.info("Connected to server", .{});
var the_chunk = try shared.chunk.initChunk(allocator);
defer shared.chunk.deinitChunk(&the_chunk, allocator);
shared.chunk.spawn(&the_chunk, shared.entity.Player, allocator, .{
.pos = zm.f32x4(1, 1, 0, 0),
.hp = 10,
});
shared.chunk.spawn(&the_chunk, shared.entity.Monster, allocator, .{
.pos = zm.f32x4(1, 1, 0, 0),
.hp = 20,
});
shared.chunk.spawn(&the_chunk, shared.entity.Projectile, allocator, .{
.pos = zm.f32x4(0, 0, 0, 0),
.vel = zm.f32x4(0.2, 0, 0, 0),
});
shared.chunk.updateChunk(&the_chunk);
var send_buf: [1024]u8 = undefined;
var writer = connection.writer(&send_buf);
try shared.protocol.sendHello(&writer.interface, .{ .msg = "Hello from client" });
var recv_buf: [1024]u8 = undefined;
var reader = connection.reader(&recv_buf);
const line = try shared.protocol.recvLine(reader.interface());
std.log.info("{s}", .{line});
}
//fn handle_connection(connection: std.net.Server.Connection) !void {}
// test "simple test" {
// const gpa = std.testing.allocator;
// var list: std.ArrayList(i32) = .empty;
// defer list.deinit(gpa); // Try commenting this out and see if zig detects the memory leak!
// try list.append(gpa, 42);
// try std.testing.expectEqual(@as(i32, 42), list.pop());
// }
// test "fuzz example" {
// const Context = struct {
// fn testOne(context: @This(), input: []const u8) anyerror!void {
// _ = context;
// // Try passing `--fuzz` to `zig build test` and see if it manages to fail this test case!
// try std.testing.expect(!std.mem.eql(u8, "canyoufindme", input));
// }
// };
// try std.testing.fuzz(Context{}, Context.testOne, .{});
// }

83
src/server/main.zig Normal file
View File

@ -0,0 +1,83 @@
const std = @import("std");
const zm = @import("zmath");
const shared = @import("shared");
var stdout: *std.io.Writer = undefined;
pub fn main() !void {
std.log.info("Helllo Server!", .{});
var dbg_allocator = std.heap.DebugAllocator(.{}).init;
defer _ = dbg_allocator.deinit();
const allocator = dbg_allocator.allocator();
var stdout_buffer: [1024]u8 = undefined;
var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
stdout = &stdout_writer.interface;
std.log.info("{s}", .{@typeName(shared.chunk.Chunk)});
try stdout.flush();
const address = try std.net.Address.parseIp4("127.0.0.1", shared.protocol.SERVER_PORT);
var server = try address.listen(.{});
defer server.deinit();
var the_chunk = try shared.chunk.initChunk(allocator);
defer shared.chunk.deinitChunk(&the_chunk, allocator);
shared.chunk.spawn(&the_chunk, shared.entity.Player, allocator, .{
.pos = zm.f32x4(1, 1, 0, 0),
.hp = 10,
});
shared.chunk.spawn(&the_chunk, shared.entity.Monster, allocator, .{
.pos = zm.f32x4(1, 1, 0, 0),
.hp = 20,
});
shared.chunk.spawn(&the_chunk, shared.entity.Projectile, allocator, .{
.pos = zm.f32x4(0, 0, 0, 0),
.vel = zm.f32x4(0.2, 0, 0, 0),
});
shared.chunk.updateChunk(&the_chunk);
while (true) {
const connection = try server.accept();
defer connection.stream.close();
std.log.info("Client connected", .{});
var recv_buffer: [4096]u8 = undefined;
var send_buffer: [4096]u8 = undefined;
var reader = connection.stream.reader(&recv_buffer);
var writer = connection.stream.writer(&send_buffer);
const line = try shared.protocol.recvLine(reader.interface());
std.log.info("Received: {s}", .{line});
try shared.protocol.sendHello(&writer.interface, .{ .msg = "Hello from server!" });
}
}
//fn handle_connection(connection: std.net.Server.Connection) !void {}
// test "simple test" {
// const gpa = std.testing.allocator;
// var list: std.ArrayList(i32) = .empty;
// defer list.deinit(gpa); // Try commenting this out and see if zig detects the memory leak!
// try list.append(gpa, 42);
// try std.testing.expectEqual(@as(i32, 42), list.pop());
// }
// test "fuzz example" {
// const Context = struct {
// fn testOne(context: @This(), input: []const u8) anyerror!void {
// _ = context;
// // Try passing `--fuzz` to `zig build test` and see if it manages to fail this test case!
// try std.testing.expect(!std.mem.eql(u8, "canyoufindme", input));
// }
// };
// try std.testing.fuzz(Context{}, Context.testOne, .{});
// }

99
src/shared/chunk.zig Normal file
View File

@ -0,0 +1,99 @@
const std = @import("std");
const entity = @import("entity.zig");
const misc = @import("misc.zig");
fn Storage(comptime T: type) type {
return struct {
items: std.ArrayList(T),
pub fn init(allocator: std.mem.Allocator) !@This() {
return .{
.items = try std.ArrayList(T).initCapacity(allocator, 32),
};
}
pub fn deinit(self: *@This(), allocator: std.mem.Allocator) void {
self.items.deinit(allocator);
}
pub fn update(self: *@This()) void {
for (self.items.items, 0..) |*item, i| {
_ = i;
if (@hasDecl(T, "update"))
item.update();
}
}
};
}
pub fn initChunk(allocator: std.mem.Allocator) !Chunk {
var chunk: Chunk = undefined;
switch (@typeInfo(Chunk)) {
.@"struct" => |s| {
inline for (s.fields) |field| {
const StorageT = field.type;
@field(chunk, field.name) = try StorageT.init(allocator);
}
},
else => unreachable,
}
return chunk;
}
pub fn deinitChunk(chunk: *Chunk, allocator: std.mem.Allocator) void {
switch (@typeInfo(Chunk)) {
.@"struct" => |s| {
inline for (s.fields) |field| {
@field(chunk, field.name).deinit(allocator);
}
},
else => unreachable,
}
}
fn _Chunk(comptime Types: anytype) type {
const FieldCount = Types.len;
var fields: [FieldCount]std.builtin.Type.StructField = undefined;
inline for (Types, 0..) |T, i| {
fields[i] = .{
.name = misc.short_type_name(T),
.type = Storage(T),
.default_value_ptr = null,
.is_comptime = false,
.alignment = @alignOf(Storage(T)),
};
}
return @Type(.{
.@"struct" = .{
.layout = .auto,
.fields = &fields,
.decls = &.{},
.is_tuple = false,
},
});
}
pub const Chunk = _Chunk(entity.EntityKinds);
pub fn updateChunk(chunk: *Chunk) void {
const info = @typeInfo(Chunk);
switch (info) {
.@"struct" => |s| {
inline for (s.fields) |field| {
@field(chunk, field.name).update();
}
},
else => unreachable,
}
}
pub fn spawn(chunk: anytype, comptime T: type, allocator: std.mem.Allocator, value: T) void {
std.log.info("hello!? {s}", .{@typeName(T)});
@field(chunk, misc.short_type_name(T)).items.append(allocator, value) catch unreachable;
}

36
src/shared/entity.zig Normal file
View File

@ -0,0 +1,36 @@
const std = @import("std");
const zm = @import("zmath");
pub const EntityKinds = .{
Player,
Monster,
Projectile,
};
pub const Player = struct {
pos: zm.Vec,
hp: i32,
pub fn update(self: *Player) void {
std.log.info("pos=({})", .{self.pos});
}
};
pub const Monster = struct {
pos: zm.Vec,
hp: i32,
pub fn update(self: *Monster) void {
std.log.info("pos=({})", .{self.pos});
}
};
pub const Projectile = struct {
pos: zm.Vec,
vel: zm.Vec,
pub fn update(self: *Projectile) void {
self.pos = self.pos + self.vel;
std.log.info("pos=({})", .{self.pos});
}
};

7
src/shared/misc.zig Normal file
View File

@ -0,0 +1,7 @@
const std = @import("std");
pub fn short_type_name(comptime T: type) [:0]const u8 {
const full = @typeName(T);
const base = full[std.mem.lastIndexOf(u8, full, ".").? + 1 ..];
return base ++ "\x00";
}

15
src/shared/protocol.zig Normal file
View File

@ -0,0 +1,15 @@
const std = @import("std");
pub const SERVER_PORT: u16 = 1337;
pub const Hello = struct {
msg: []const u8,
};
pub fn sendHello(writer: *std.io.Writer, hello: Hello) !void {
try writer.print("{s}\n", .{hello.msg});
}
pub fn recvLine(reader: *std.io.Reader) ![]u8 {
return try reader.takeDelimiterExclusive('\n');
}

4
src/shared/shared.zig Normal file
View File

@ -0,0 +1,4 @@
pub const entity = @import("entity.zig");
pub const chunk = @import("chunk.zig");
pub const misc = @import("misc.zig");
pub const protocol = @import("protocol.zig");

31
zzz.rad_proj Normal file
View File

@ -0,0 +1,31 @@
// raddbg 0.9.24 project file
recent_file: path: "../../AppData/Local/Microsoft/WinGet/Packages/zig.zig_Microsoft.Winget.Source_8wekyb3d8bbwe/zig-x86_64-windows-0.15.2/lib/std/start.zig"
recent_file: path: "src/client/main.zig"
target:
{
executable: "zig-out/bin/server.exe"
working_directory: "zig-out/bin/"
enabled: 1
}
target:
{
executable: "zig-out/bin/client.exe"
working_directory: "zig-out/bin/"
enabled: 1
}
debug_info:
{
path: "C:/Users/vfs/Dev/zzz/zig-out/bin/server.pdb"
timestamp: 66201747551645
}
debug_info:
{
path: "C:/Users/vfs/Dev/zzz/zig-out/bin/client.pdb"
timestamp: 66201747551558
}
breakpoint:
{
source_location: "src/client/main.zig:8:1"
hit_count: 1
}