Compare commits

..
23 Commits
Author SHA1 Message Date
vfs 077ceb810e i don't know 2026-02-19 22:12:59 +01:00
vfs 35bbc5cbfd v 2026-02-08 15:22:38 +01:00
vfs 5a79ae71c0 . 2026-02-08 15:22:31 +01:00
vfs 29c136d34c ... 2026-02-05 12:32:12 +01:00
vfs 9a5c15e47e bit streaming 2026-02-05 12:32:01 +01:00
vfs 5864401129 . 2026-02-04 15:36:53 +01:00
vfs 5eba80a6c6 not even compiling :( gotta go to bed 2026-02-03 23:20:48 +01:00
vfs 395320a794 . 2026-02-03 19:27:23 +01:00
vfs bab331083e how to use bufzilla? 2026-02-03 17:49:10 +01:00
vfs fb238a1966 . 2026-02-03 13:22:20 +01:00
vfs c6fdd68afe . 2026-02-03 10:19:36 +01:00
vfs ee790cf700 working on protocol architecture 2026-02-02 23:42:54 +01:00
vfs 510c19fbd5 enet 2026-02-02 11:12:50 +01:00
vfs b91bce8840 enough fonting, more servering? 2026-02-02 01:25:01 +01:00
vfs e6d8607d3f . 2026-02-02 00:43:52 +01:00
vfs 719973ad19 actually fix the tracy version to a commit so we don't have to regenerate a new hash every time someone makes a commit on this very popular repository! 2026-02-02 00:43:45 +01:00
vfs 49ce31ee2e just setting up the environment 2026-02-01 23:06:37 +01:00
vfs 6d69fa8898 w/e 2026-01-29 23:00:03 +01:00
vfs c41f8866d9 Merge commit 'a06333f66fac3bc338f46d81ff8113d03f3988ec' as 'vendor/enet' 2026-01-29 22:03:15 +01:00
vfs a06333f66f Squashed 'vendor/enet/' content from commit 8be2368
git-subtree-dir: vendor/enet
git-subtree-split: 8be2368a8001f28db44e81d5939de5e613025023
2026-01-29 22:03:14 +01:00
vfs 2d778ef20e let's try again as a remote subtree 2026-01-29 22:02:22 +01:00
vfs c36b868f46 Merge commit '1384a4ba576664fce62c8c35675cdbad701e97ba' as 'vendor/enet' 2026-01-29 22:00:54 +01:00
vfs 1384a4ba57 Squashed 'vendor/enet/' content from commit 8be2368
git-subtree-dir: vendor/enet
git-subtree-split: 8be2368a8001f28db44e81d5939de5e613025023
2026-01-29 22:00:54 +01:00
32 changed files with 2326 additions and 2010 deletions

No files matched your search

+13 -2
View File
@@ -5,7 +5,7 @@
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"name": "(lldb) Launch", "name": "Client",
"type": "lldb", "type": "lldb",
"request": "launch", "request": "launch",
"program": "${workspaceFolder}/zig-out/bin/client", "program": "${workspaceFolder}/zig-out/bin/client",
@@ -13,7 +13,18 @@
"cwd": "${workspaceFolder}", "cwd": "${workspaceFolder}",
"internalConsoleOptions": "openOnSessionStart", "internalConsoleOptions": "openOnSessionStart",
"preLaunchTask": "build", "preLaunchTask": "build",
"sourceLanguages": ["zig"] "sourceLanguages": ["zig"],
},
{
"name": "Server",
"type": "lldb",
"request": "launch",
"program": "${workspaceFolder}/zig-out/bin/server",
"args": [],
"cwd": "${workspaceFolder}",
"internalConsoleOptions": "openOnSessionStart",
"preLaunchTask": "build",
"sourceLanguages": ["zig"],
} }
] ]
} }
+13 -1
View File
@@ -6,7 +6,19 @@
{ {
"label": "build", "label": "build",
"type": "shell", "type": "shell",
"command": "zig build", "command": "zig",
"args": ["build"],
"options": {
"cwd": "${workspaceRoot}"
},
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared",
"showReuseMessage": true,
"clear": true,
},
"problemMatcher": [], "problemMatcher": [],
"group": { "group": {
"kind": "build", "kind": "build",
+127 -54
View File
@@ -1,8 +1,16 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin");
const raylib_src = @import("raylib");
pub fn build(b: *std.Build) void { pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{ .default_target = .{ .cpu_model = .native } }); const target = b.standardTargetOptions(.{
const optimize = b.standardOptimizeOption(.{ .preferred_optimize_mode = .ReleaseFast }); .default_target = if (builtin.target.os.tag == .windows)
.{ .os_tag = .windows, .abi = .msvc }
else
.{},
});
const optimize = b.standardOptimizeOption(.{ .preferred_optimize_mode = .Debug });
const assets = b.addInstallDirectory(.{ const assets = b.addInstallDirectory(.{
.source_dir = b.path("assets"), .source_dir = b.path("assets"),
@@ -24,13 +32,12 @@ pub fn build(b: *std.Build) void {
.imports = &.{ .imports = &.{
.{ .{
.name = "shared", .name = "shared",
.module = shared .module = shared,
}, },
}, },
}), }),
.use_llvm = true, .use_llvm = true,
}); });
client.root_module.strip = true;
const server = b.addExecutable(.{ const server = b.addExecutable(.{
.name = "server", .name = "server",
@@ -39,31 +46,44 @@ pub fn build(b: *std.Build) void {
.target = target, .target = target,
.optimize = optimize, .optimize = optimize,
.imports = &.{ .imports = &.{
.{ .name = "shared", .module = shared }, .{
.name = "shared",
.module = shared,
},
}, },
}), }),
.use_llvm = true, .use_llvm = true,
}); });
server.root_module.strip = true;
const ztracy = b.dependency( // tracy
"ztracy", {
const tracy = b.dependency(
"tracy",
.{ .{
.enable_ztracy = true,
.enable_fibers = false,
.on_demand = false,
}
);
client.root_module.addImport("ztracy", ztracy.module("root"));
client.linkLibrary(ztracy.artifact("tracy"));
const mach_freetype = b.dependency("mach_freetype", .{
.target = target, .target = target,
.optimize = optimize, .optimize = optimize,
}); .enable_tracy = true,
client.root_module.addImport("mach-freetype", mach_freetype.module("mach-freetype")); .enable_fibers = false,
client.root_module.addImport("mach-harfbuzz", mach_freetype.module("mach-harfbuzz")); .on_demand = false,
},
);
client.root_module.addImport("tracy", tracy.module("tracy"));
}
// freetype
{
const freetype = b.dependency(
"freetype",
.{
.target = target,
.optimize = optimize,
}
);
client.root_module.addImport("freetype", freetype.module("freetype"));
}
// kb_text_shape
{
client.root_module.addCSourceFile(.{ client.root_module.addCSourceFile(.{
.file = b.path("vendor/kb_text_shape/kb_text_shape.h"), .file = b.path("vendor/kb_text_shape/kb_text_shape.h"),
.language = .c, .language = .c,
@@ -82,7 +102,10 @@ pub fn build(b: *std.Build) void {
.optimize = optimize, .optimize = optimize,
}); });
client.root_module.addImport("kb", kb_text_shape.createModule()); client.root_module.addImport("kb", kb_text_shape.createModule());
}
// stb_rect_pack
{
client.root_module.addCSourceFile(.{ .file = b.path("vendor/stb/stb_rect_pack.h"), .language = .c, .flags = &.{} }); client.root_module.addCSourceFile(.{ .file = b.path("vendor/stb/stb_rect_pack.h"), .language = .c, .flags = &.{} });
const stb_rect_pack = b.addTranslateC(.{ const stb_rect_pack = b.addTranslateC(.{
.root_source_file = b.path("vendor/stb/stb_rect_pack.h"), .root_source_file = b.path("vendor/stb/stb_rect_pack.h"),
@@ -90,7 +113,10 @@ pub fn build(b: *std.Build) void {
.optimize = optimize, .optimize = optimize,
}); });
client.root_module.addImport("stb_rect_pack", stb_rect_pack.createModule()); client.root_module.addImport("stb_rect_pack", stb_rect_pack.createModule());
}
// zmath
{
const zmath = b.dependency( const zmath = b.dependency(
"zmath", "zmath",
.{ .{
@@ -101,68 +127,81 @@ pub fn build(b: *std.Build) void {
client.root_module.addImport("zmath", zmath.module("root")); client.root_module.addImport("zmath", zmath.module("root"));
server.root_module.addImport("zmath", zmath.module("root")); server.root_module.addImport("zmath", zmath.module("root"));
shared.addImport("zmath", zmath.module("root")); shared.addImport("zmath", zmath.module("root"));
const znet = b.dependency(
"znet",
.{
.target = target,
.optimize = optimize,
} }
);
client.root_module.addImport("znet", znet.module("znet"));
server.root_module.addImport("znet", znet.module("znet"));
const bufzilla = b.dependency(
"bufzilla",
.{
.target = target,
.optimize = optimize,
});
client.root_module.addImport("bufzilla", bufzilla.module("bufzilla"));
server.root_module.addImport("bufzilla", bufzilla.module("bufzilla"));
const raylib_dep = b.dependency("raylib_zig", .{ // ENet
{
const enet = b.dependency("enet", .{
.target = target, .target = target,
.optimize = optimize, .optimize = optimize,
}); });
const raylib = raylib_dep.module("raylib"); // main raylib module // shared.linkLibrary(enet.artifact("enet"));
const raygui = raylib_dep.module("raygui"); // raygui module client.root_module.linkLibrary(enet.artifact("enet"));
const raylib_artifact = raylib_dep.artifact("raylib"); // raylib C library server.root_module.linkLibrary(enet.artifact("enet"));
raylib_artifact.root_module.addCMacro("SUPPORT_CUSTOM_FRAME_CONTROL", ""); }
client.linkLibrary(raylib_artifact); // // Bufzilla
client.root_module.addImport("raylib", raylib); // {
client.root_module.addImport("raygui", raygui); // const bufzilla = b.dependency(
// "bufzilla",
// .{
// .target = target,
// .optimize = optimize,
// });
// shared.addImport("bufzilla", bufzilla.module("bufzilla"));
// client.root_module.addImport("bufzilla", bufzilla.module("bufzilla"));
// server.root_module.addImport("bufzilla", bufzilla.module("bufzilla"));
// }
// Raylib
{
const raylib_dep = b.dependency("raylib", .{ .target = target, .optimize = optimize });
const raylib_lib = raylib_dep.artifact("raylib");
raylib_lib.root_module.addCMacro("SUPPORT_CUSTOM_FRAME_CONTROL", "");
client.root_module.linkLibrary(raylib_lib);
if (target.result.os.tag == .windows)
client.root_module.linkSystemLibrary("shell32", .{ .needed = true });
}
client.root_module.link_libc = true;
server.root_module.link_libc = true;
b.installArtifact(client); b.installArtifact(client);
b.installArtifact(server); b.installArtifact(server);
b.getInstallStep().dependOn(&assets.step); b.getInstallStep().dependOn(&assets.step);
const run_step = b.step("run", "Run the app"); const run_client_step = b.step("run-client", "Run the client");
const run_server_step = b.step("run-server", "Run the server");
const run_cmd_client = b.addRunArtifact(client); const run_cmd_client = b.addRunArtifact(client);
const run_cmd_server = b.addRunArtifact(server); const run_cmd_server = b.addRunArtifact(server);
run_step.dependOn(&run_cmd_client.step); run_client_step.dependOn(&run_cmd_client.step);
run_step.dependOn(&run_cmd_server.step); run_server_step.dependOn(&run_cmd_server.step);
run_cmd_client.step.dependOn(b.getInstallStep()); run_cmd_client.step.dependOn(b.getInstallStep());
run_cmd_server.step.dependOn(b.getInstallStep()); run_cmd_server.step.dependOn(b.getInstallStep());
if (b.args) |args| { if (b.args) |args| {
run_cmd_client.addArgs(args); run_cmd_client.addArgs(args);
run_cmd_server.addArgs(args);
} }
// Creates an executable that will run `test` blocks from the provided module. // Creates an executable that will run `test` blocks from the provided module.
// Here `mod` needs to define a target, which is why earlier we made sure to // Here `mod` needs to define a target, which is why earlier we made sure to
// set the releative field. // set the releative field.
// const mod_tests = b.addTest(.{ const shared_tests = b.addTest(.{
// .root_module = mod, .root_module = shared,
// }); .use_llvm = true,
});
// A run step that will run the test executable. // A run step that will run the test executable.
// const run_mod_tests = b.addRunArtifact(mod_tests); const run_shared_tests = b.addRunArtifact(shared_tests);
// Creates an executable that will run `test` blocks from the executable's // Creates an executable that will run `test` blocks from the executable's
// root module. Note that test executables only test one module at a time, // root module. Note that test executables only test one module at a time,
@@ -177,8 +216,8 @@ pub fn build(b: *std.Build) void {
// A top level step for running all tests. dependOn can be called multiple // A top level step for running all tests. dependOn can be called multiple
// times and since the two run steps do not depend on one another, this will // times and since the two run steps do not depend on one another, this will
// make the two of them run in parallel. // make the two of them run in parallel.
// const test_step = b.step("test", "Run tests"); const test_step = b.step("test", "Run tests");
// test_step.dependOn(&run_mod_tests.step); test_step.dependOn(&run_shared_tests.step);
// test_step.dependOn(&run_exe_tests.step); // test_step.dependOn(&run_exe_tests.step);
// Just like flags, top level steps are also listed in the `--help` menu. // Just like flags, top level steps are also listed in the `--help` menu.
@@ -193,3 +232,37 @@ pub fn build(b: *std.Build) void {
// Lastly, the Zig build system is relatively simple and self-contained, // Lastly, the Zig build system is relatively simple and self-contained,
// and reading its source code will allow you to master it. // and reading its source code will allow you to master it.
} }
fn getRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: raylib_src.Options) *std.Build.Step.Compile {
const raylib_dep = b.dependency("raylib", .{
.target = target,
.optimize = optimize,
.raudio = options.raudio,
.rmodels = options.rmodels,
.rshapes = options.rshapes,
.rtext = options.rtext,
.rtextures = options.rtextures,
.platform = options.platform,
.linkage = options.linkage,
.linux_display_backend = options.linux_display_backend,
.opengl_version = options.opengl_version,
.android_api_version = options.android_api_version,
.android_ndk = options.android_ndk,
});
const raylib = raylib_dep.artifact("raylib");
b.installArtifact(raylib);
return raylib;
}
fn getModule(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) *std.Build.Module {
if (b.modules.contains("raylib")) {
return b.modules.get("raylib").?;
}
return b.addModule("raylib", .{
.root_source_file = b.path("lib/raylib.zig"),
.target = target,
.optimize = optimize,
});
}
+12 -15
View File
@@ -40,25 +40,22 @@
.url = "git+https://github.com/Gota7/zig-sdl3?ref=master#79b0d1f1ef10a424037025f6af44fe06bf7e062c", .url = "git+https://github.com/Gota7/zig-sdl3?ref=master#79b0d1f1ef10a424037025f6af44fe06bf7e062c",
.hash = "sdl3-0.1.5-NmT1Q3ARJgDmFWtbbK3KBb7vufbQD0EjD4Me4Fbdq0p3", .hash = "sdl3-0.1.5-NmT1Q3ARJgDmFWtbbK3KBb7vufbQD0EjD4Me4Fbdq0p3",
}, },
.raylib_zig = .{ .enet = .{
.url = "git+https://github.com/raylib-zig/raylib-zig#7d4761b878f43671024ce197f721827b5355a67e", .path = "vendor/enet",
.hash = "raylib_zig-5.6.0-dev-KE8REGlNBQDR7NML06VBtT7gP3VZNY70E5WohAxzqrNn",
},
.znet = .{
.url = "git+https://github.com/connellr023/znet#cb11fb0c4a2b668128c436fbbccd111223c74898",
.hash = "znet-0.0.0-PGDNtD9RAAChe8Ky4dhWhS2XH77-xyf1X8HcDBwpM3kA",
}, },
.bufzilla = .{ .bufzilla = .{
.url = "https://github.com/theseyan/bufzilla/archive/refs/tags/v0.3.2.tar.gz", .url = "https://github.com/theseyan/bufzilla/archive/refs/tags/v0.3.3.tar.gz",
.hash = "bufzilla-0.3.0-gU6dXi67AQAg3WIFrNQ0iafrvexj3iBwVcczrVzrN3Ir", .hash = "bufzilla-0.3.0-gU6dXie7AQDTXB7ptRjLa1plj3txaUVKFvT39e3v-pop",
}, },
.ztracy = .{ .tracy = .{
.url = "git+https://github.com/zig-gamedev/ztracy#d95d2a193b9f97944a17026c9a42b5d0f9a88c94", .path = "vendor/tracy",
.hash = "ztracy-0.14.0-dev-zHJSqzUHGQAmhJybhlwtl1QKevUBw4M5YKZqPfWx2y99",
}, },
.mach_freetype = .{ .freetype = .{
.url = "git+https://github.com/hexops/mach-freetype#44f481e3435592810a7c55fc2f37e470dcba2a9c", .path = "vendor/freetype",
.hash = "mach_freetype-0.0.0-AAAAAG4nCAANuVIO0Lmyh-H-eN2d60k-xlxIW_Xv90jq", },
.raylib = .{
.url = "git+https://github.com/raysan5/raylib/#403c2cbccff44cac0c0bbae034c00191eeee7b4c",
.hash = "raylib-5.6.0-dev-whq8uKAqDQWosMsUzhDBAbuDSmbxaqJeydmpgv5e8wzU",
}, },
}, },
.paths = .{ .paths = .{
+10
View File
@@ -3,3 +3,13 @@ pub const c = @cImport({
@cInclude("raymath.h"); @cInclude("raymath.h");
@cInclude("rlgl.h"); @cInclude("rlgl.h");
}); });
pub const enet = @cImport({
@cInclude("enet/enet.h");
});
pub const rl = @cImport({
@cInclude("raylib.h");
@cInclude("rlgl.h");
@cInclude("raymath.h");
});
+73
View File
@@ -0,0 +1,73 @@
const std = @import("std");
const shared = @import("shared");
const enet = @import("c.zig").enet;
pub fn spawn(self: *shared.chunk.Chunk, allocator: std.mem.Allocator, comptime T: type, value: T) !shared.entity.id {
std.debug.assert(value.id != shared.entity.INVALID_ID);
const ptr = try allocator.create(T);
errdefer allocator.destroy(ptr);
ptr.* = value;
const ref = shared.entity.makeRef(T, ptr);
try self.entities.append(allocator, ref);
return ptr.id;
}
pub fn find(self: *shared.chunk.Chunk, id: shared.entity.id) ?shared.entity.Ref {
for (self.entities.items) |ref| {
switch (ref) {
inline else => |ptr| {
if (ptr.id == id) {
return ref;
}
}
}
}
return null;
}
pub fn findT(self: *shared.chunk.Chunk, comptime T: type, id: shared.entity.id) ?*T {
for (self.entities.items) |ref| {
switch (ref) {
inline else => |ptr| {
if (ptr.id == id and @TypeOf(ptr) == *T) {
return ptr;
}
}
}
}
return null;
}
pub fn despawn(self: *shared.chunk.Chunk, allocator: std.mem.Allocator, id: shared.entity.id) bool {
var i: usize = 0;
while (i < self.entities.items.len) {
const ref = self.entities.items[i];
var found = false;
switch (ref) {
inline else => |ptr| {
if (ptr.id == id) {
allocator.destroy(ptr);
found = true;
}
},
}
if (found) {
_ = self.entities.swapRemove(i);
return true;
}
i += 1;
}
return false;
}
+1
View File
@@ -1,4 +1,5 @@
const std = @import("std"); const std = @import("std");
const shared = @import("shared");
const ConnectState = union(enum) { const ConnectState = union(enum) {
disconnected, disconnected,
+21 -13
View File
@@ -2,21 +2,29 @@ const rl = @import("raylib");
const shared = @import("shared"); const shared = @import("shared");
const zm = @import("zmath"); const zm = @import("zmath");
pub const Elf = struct { // pub const Elf = struct {
elf: shared.entity.Elf, // elf: shared.entity.Elf,
boy: rl.Texture, // boy: rl.Texture,
// pub fn init() Elf {
// return .{
// .elf = .{ .hp = 10, .pos = zm.f32x4(0, 0, 0, 0) },
// .boy = rl.loadTexture("assets/tile_0000.png") catch unreachable,
// };
// }
// pub fn draw(self: *Elf) void {
// const src = rl.Rectangle.init(0, 0, @floatFromInt(self.boy.width), @floatFromInt(self.boy.height));
// const dst = rl.Rectangle.init(100 + 100 * zm.cos(@as(f32, @floatCast(rl.getTime()))), 100 + 100 * zm.sin(@as(f32, @floatCast(rl.getTime()))), 2.0 * @as(f32, @floatFromInt(self.boy.width)), 2.0 * @as(f32, @floatFromInt(self.boy.height)));
// self.boy.drawPro(src, dst, .{ .x = 0, .y = 0 }, 0, .white);
// }
// };
pub fn draw_soldier(self: *shared.entity.Soldier) void {
pub fn init() Elf {
return .{
.elf = .{ .hp = 10, .pos = zm.f32x4(0, 0, 0, 0) },
.boy = rl.loadTexture("assets/tile_0000.png") catch unreachable,
};
} }
pub fn draw(self: *Elf) void { pub fn draw_alien(self: *shared.entity.Alien) void {
const src = rl.Rectangle.init(0, 0, @floatFromInt(self.boy.width), @floatFromInt(self.boy.height));
const dst = rl.Rectangle.init(100 + 100 * zm.cos(@as(f32, @floatCast(rl.getTime()))), 100 + 100 * zm.sin(@as(f32, @floatCast(rl.getTime()))), 2.0 * @as(f32, @floatFromInt(self.boy.width)), 2.0 * @as(f32, @floatFromInt(self.boy.height)));
self.boy.drawPro(src, dst, .{ .x = 0, .y = 0 }, 0, .white);
} }
};
+40 -45
View File
@@ -1,10 +1,9 @@
const std = @import("std"); const std = @import("std");
const rl = @import("raylib"); const rl = @import("c.zig").rl;
const kb = @import("kb"); const kb = @import("kb");
const ft = @import("mach-freetype"); const ft = @import("freetype");
const hb = @import("mach-harfbuzz");
const rp = @import("stb_rect_pack"); const rp = @import("stb_rect_pack");
const ztracy = @import("ztracy"); const tracy = @import("tracy");
pub var ft_lib : ft.Library = undefined; pub var ft_lib : ft.Library = undefined;
pub var shader : rl.Shader = undefined; pub var shader : rl.Shader = undefined;
@@ -39,7 +38,6 @@ pub const Font = struct {
face : ft.Face, face : ft.Face,
glyphs : std.AutoHashMap(u32, Glyph), glyphs : std.AutoHashMap(u32, Glyph),
kbts_font : kb.kbts_font, kbts_font : kb.kbts_font,
// texture : c.Texture2D,
texture : rl.Texture2D, texture : rl.Texture2D,
kb_file_data : []u8, kb_file_data : []u8,
@@ -57,7 +55,7 @@ pub const Font = struct {
var face = try ft_lib.createFaceMemory(file_data, 0); var face = try ft_lib.createFaceMemory(file_data, 0);
var glyphs = std.AutoHashMap(u32, Glyph).init(allocator); var glyphs = std.AutoHashMap(u32, Glyph).init(allocator);
try face.setCharSize(0, size * 64, 0, 96 * @as(u16, @intFromFloat(rl.getWindowScaleDPI().y))); try face.setCharSize(0, size * 64, 0, 96 * @as(u16, @intFromFloat(rl.GetWindowScaleDPI().y)));
try face.selectCharmap(.unicode); try face.selectCharmap(.unicode);
var rects = try std.ArrayList(rp.stbrp_rect).initCapacity(allocator, 1024); var rects = try std.ArrayList(rp.stbrp_rect).initCapacity(allocator, 1024);
@@ -77,7 +75,7 @@ pub const Font = struct {
.width = ATLAS_SIZE, .width = ATLAS_SIZE,
.height = ATLAS_SIZE, .height = ATLAS_SIZE,
.mipmaps = 1, .mipmaps = 1,
.format = rl.PixelFormat.uncompressed_grayscale, .format = rl.PIXELFORMAT_UNCOMPRESSED_GRAYSCALE,
}; };
for (0..face.numGlyphs()) |index| { for (0..face.numGlyphs()) |index| {
@@ -85,7 +83,7 @@ pub const Font = struct {
const bmp = face.glyph().bitmap(); const bmp = face.glyph().bitmap();
try rects.append(allocator, .{ try rects.append(allocator, .{
.id = @intCast(index),//@intCast(face.glyph().glyphIndex()), .id = @intCast(index),
.w = @max(1, @as(c_int, @intCast(bmp.width()))), .w = @max(1, @as(c_int, @intCast(bmp.width()))),
.h = @max(1, @as(c_int, @intCast(bmp.rows()))), .h = @max(1, @as(c_int, @intCast(bmp.rows()))),
.x = 0, .x = 0,
@@ -123,12 +121,12 @@ pub const Font = struct {
const width : i32 = @intCast(bmp.width()); const width : i32 = @intCast(bmp.width());
const height : i32 = @intCast(bmp.rows()); const height : i32 = @intCast(bmp.rows());
const dpi_width : f32 = @as(f32, @floatFromInt(width)) / rl.getWindowScaleDPI().x; const dpi_width : f32 = @as(f32, @floatFromInt(width)) / rl.GetWindowScaleDPI().x;
const dpi_height : f32 = @as(f32, @floatFromInt(height)) / rl.getWindowScaleDPI().y; const dpi_height : f32 = @as(f32, @floatFromInt(height)) / rl.GetWindowScaleDPI().y;
const bearing_x : i32 = face.glyph().bitmapLeft(); const bearing_x : i32 = face.glyph().bitmapLeft();
const bearing_y : i32 = face.glyph().bitmapTop(); const bearing_y : i32 = face.glyph().bitmapTop();
const dpi_bearing_x : f32 = @as(f32, @floatFromInt(bearing_x)) / rl.getWindowScaleDPI().x; const dpi_bearing_x : f32 = @as(f32, @floatFromInt(bearing_x)) / rl.GetWindowScaleDPI().x;
const dpi_bearing_y : f32 = @as(f32, @floatFromInt(bearing_y)) / rl.getWindowScaleDPI().y; const dpi_bearing_y : f32 = @as(f32, @floatFromInt(bearing_y)) / rl.GetWindowScaleDPI().y;
const descent : i32 = height - bearing_y; const descent : i32 = height - bearing_y;
const ascent : i32 = height - descent; const ascent : i32 = height - descent;
const dpi_descent : f32 = dpi_height - dpi_bearing_y; const dpi_descent : f32 = dpi_height - dpi_bearing_y;
@@ -166,7 +164,7 @@ pub const Font = struct {
try glyphs.put(glyph.index, glyph); try glyphs.put(glyph.index, glyph);
} }
const texture = try rl.loadTextureFromImage(atlas); const texture = rl.LoadTextureFromImage(atlas);
var kbts_font = kb.kbts_FontFromMemory(kb_file_data.ptr, @intCast(kb_file_data.len), 0, null, null); var kbts_font = kb.kbts_FontFromMemory(kb_file_data.ptr, @intCast(kb_file_data.len), 0, null, null);
@@ -174,9 +172,6 @@ pub const Font = struct {
std.log.info("[Error] [kb_text_shape] Failed to load the font.", .{}); std.log.info("[Error] [kb_text_shape] Failed to load the font.", .{});
} }
const hb_blob = hb.Blob.initFromFile(filename);
_ = hb_blob;
return .{ return .{
.face = face, .face = face,
.glyphs = glyphs, .glyphs = glyphs,
@@ -190,7 +185,7 @@ pub const Font = struct {
self.glyphs.deinit(); self.glyphs.deinit();
self.face.deinit(); self.face.deinit();
kb.kbts_FreeFont(&self.kbts_font); kb.kbts_FreeFont(&self.kbts_font);
self.texture.unload(); rl.UnloadTexture(self.texture);
allocator.free(self.kb_file_data); allocator.free(self.kb_file_data);
} }
@@ -207,17 +202,17 @@ pub const Font = struct {
if (text.len == 0) if (text.len == 0)
return; return;
const zone = ztracy.ZoneNC(@src(), "render_text", 0x00_ff_00_00); const zone = tracy.ZoneNC(@src(), "render_text", 0x00_ff_00_00);
defer zone.End(); defer zone.End();
rl.beginShaderMode(shader); rl.BeginShaderMode(shader);
rl.gl.rlSetTexture(self.texture.id); rl.rlSetTexture(self.texture.id);
rl.gl.rlBegin(rl.gl.rl_quads); rl.rlBegin(rl.RL_QUADS);
if (nice_background) { if (nice_background) {
self.render_text( self.render_text(
text, text,
pos.add(.{.x = 3.0, .y = -3.0}), rl.Vector2Add(pos, .{.x = 3.0, .y = -3.0}),
window_space, window_space,
rl.Color{ .r = 0, .g = 0, .b = 0, .a = 255 }, rl.Color{ .r = 0, .g = 0, .b = 0, .a = 255 },
rl.Color{ .r = 0, .g = 0, .b = 0, .a = 0 }, rl.Color{ .r = 0, .g = 0, .b = 0, .a = 0 },
@@ -231,7 +226,7 @@ pub const Font = struct {
_ = background; _ = background;
const font_ascent : f32 = @floatFromInt(self.face.size().metrics().ascender >> 6); const font_ascent : f32 = @floatFromInt(self.face.size().metrics().ascender >> 6);
const dpi_font_ascent = font_ascent / rl.getWindowScaleDPI().y; const dpi_font_ascent = font_ascent / rl.GetWindowScaleDPI().y;
render_pos.y += dpi_font_ascent; render_pos.y += dpi_font_ascent;
@@ -243,7 +238,7 @@ pub const Font = struct {
return; return;
} }
const zone2 = ztracy.ZoneNC(@src(), "ShapeUtf8", 0x00_ff_00_00); const zone2 = tracy.ZoneNC(@src(), "ShapeUtf8", 0x00_ff_00_00);
kb.kbts_ShapeBegin(Context, kb.KBTS_DIRECTION_DONT_KNOW, kb.KBTS_LANGUAGE_DONT_KNOW); kb.kbts_ShapeBegin(Context, kb.KBTS_DIRECTION_DONT_KNOW, kb.KBTS_LANGUAGE_DONT_KNOW);
kb.kbts_ShapeUtf8(Context, text.ptr, @intCast(text.len), kb.KBTS_USER_ID_GENERATION_MODE_CODEPOINT_INDEX); kb.kbts_ShapeUtf8(Context, text.ptr, @intCast(text.len), kb.KBTS_USER_ID_GENERATION_MODE_CODEPOINT_INDEX);
kb.kbts_ShapeEnd(Context); kb.kbts_ShapeEnd(Context);
@@ -254,11 +249,11 @@ pub const Font = struct {
var Run = kb.kbts_run{}; var Run = kb.kbts_run{};
while (my_kbts_ShapeRun(Context, &Run) != 0) { while (my_kbts_ShapeRun(Context, &Run) != 0) {
const zone3 = ztracy.ZoneNC(@src(), "shape run", 0x00_ff_00_00); const zone3 = tracy.ZoneNC(@src(), "shape run", 0x00_ff_00_00);
defer zone3.End(); defer zone3.End();
if ((Run.Flags & kb.KBTS_BREAK_FLAG_LINE_HARD) != 0) { if ((Run.Flags & kb.KBTS_BREAK_FLAG_LINE_HARD) != 0) {
const font_linegap : f32 = @floatFromInt(self.face.size().metrics().height >> 6); const font_linegap : f32 = @floatFromInt(self.face.size().metrics().height >> 6);
const dpi_font_linegap = font_linegap / rl.getWindowScaleDPI().y; const dpi_font_linegap = font_linegap / rl.GetWindowScaleDPI().y;
cursor_y += dpi_font_linegap; cursor_y += dpi_font_linegap;
cursor_x = 0; cursor_x = 0;
@@ -266,7 +261,7 @@ pub const Font = struct {
var g : [*c]kb.kbts_glyph = null; var g : [*c]kb.kbts_glyph = null;
while (kb.kbts_GlyphIteratorNext(&Run.Glyphs, &g) != 0) { while (kb.kbts_GlyphIteratorNext(&Run.Glyphs, &g) != 0) {
const zone4 = ztracy.ZoneNC(@src(), "glyph iterator", 0x00_ff_00_00); const zone4 = tracy.ZoneNC(@src(), "glyph iterator", 0x00_ff_00_00);
defer zone4.End(); defer zone4.End();
const RunGlyph : *kb.kbts_glyph = g.?; const RunGlyph : *kb.kbts_glyph = g.?;
const CodepointIndex : i32 = RunGlyph.UserIdOrCodepointIndex; const CodepointIndex : i32 = RunGlyph.UserIdOrCodepointIndex;
@@ -277,23 +272,23 @@ pub const Font = struct {
const advance_x : f32 = @floatFromInt(ft.mulFix(RunGlyph.AdvanceX, @intCast(self.face.size().metrics().x_scale)) >> 6); const advance_x : f32 = @floatFromInt(ft.mulFix(RunGlyph.AdvanceX, @intCast(self.face.size().metrics().x_scale)) >> 6);
const advance_y : f32 = @floatFromInt(ft.mulFix(RunGlyph.AdvanceY, @intCast(self.face.size().metrics().y_scale)) >> 6); const advance_y : f32 = @floatFromInt(ft.mulFix(RunGlyph.AdvanceY, @intCast(self.face.size().metrics().y_scale)) >> 6);
const dpi_advance_x = advance_x / rl.getWindowScaleDPI().x; const dpi_advance_x = advance_x / rl.GetWindowScaleDPI().x;
const dpi_advance_y = advance_y / rl.getWindowScaleDPI().y; const dpi_advance_y = advance_y / rl.GetWindowScaleDPI().y;
const offset_x : f32 = @floatFromInt(ft.mulFix(RunGlyph.OffsetX, @intCast(self.face.size().metrics().x_scale)) >> 6); const offset_x : f32 = @floatFromInt(ft.mulFix(RunGlyph.OffsetX, @intCast(self.face.size().metrics().x_scale)) >> 6);
const offset_y : f32 = @floatFromInt(ft.mulFix(RunGlyph.OffsetY, @intCast(self.face.size().metrics().y_scale)) >> 6); const offset_y : f32 = @floatFromInt(ft.mulFix(RunGlyph.OffsetY, @intCast(self.face.size().metrics().y_scale)) >> 6);
const dpi_offset_x = offset_x / rl.getWindowScaleDPI().x; const dpi_offset_x = offset_x / rl.GetWindowScaleDPI().x;
const dpi_offset_y = offset_y / rl.getWindowScaleDPI().y; const dpi_offset_y = offset_y / rl.GetWindowScaleDPI().y;
if (self.glyphs.getPtr(RunGlyph.Id)) |glyph| { if (self.glyphs.getPtr(RunGlyph.Id)) |glyph| {
var v0 = rl.Vector2.zero(); var v0 = rl.Vector2{};
var v1 = rl.Vector2.zero(); var v1 = rl.Vector2{};
v0 = render_pos.add(.{ .x = cursor_x + glyph.dpi_bearing_x + dpi_offset_x, v0 = rl.Vector2Add(render_pos, .{ .x = cursor_x + glyph.dpi_bearing_x + dpi_offset_x,
.y = cursor_y - glyph.dpi_bearing_y - dpi_offset_y }); .y = cursor_y - glyph.dpi_bearing_y - dpi_offset_y });
v1 = v0.add(rl.Vector2{ .x = glyph.dpi_width, .y = glyph.dpi_height }); v1 = rl.Vector2Add(v0, rl.Vector2{ .x = glyph.dpi_width, .y = glyph.dpi_height });
const p0 : rl.Vector4 = .{ .x = v0.x, .y = v0.y, .z = 0.0, .w = 1.0 }; const p0 : rl.Vector4 = .{ .x = v0.x, .y = v0.y, .z = 0.0, .w = 1.0 };
const p1 : rl.Vector4 = .{ .x = v1.x, .y = v1.y, .z = 0.0, .w = 1.0 }; const p1 : rl.Vector4 = .{ .x = v1.x, .y = v1.y, .z = 0.0, .w = 1.0 };
@@ -303,13 +298,13 @@ pub const Font = struct {
const st0 = glyph.st0; const st0 = glyph.st0;
const st1 = glyph.st1; const st1 = glyph.st1;
rl.gl.rlColor4ub(colour.r, colour.g, colour.b, colour.a); rl.rlColor4ub(colour.r, colour.g, colour.b, colour.a);
rl.gl.rlNormal3f(0.0, 0.0, 1.0); rl.rlNormal3f(0.0, 0.0, 1.0);
rl.gl.rlTexCoord2f(st0.x, st0.y); rl.gl.rlVertex2f(p0.x, p0.y); rl.rlTexCoord2f(st0.x, st0.y); rl.rlVertex2f(p0.x, p0.y);
rl.gl.rlTexCoord2f(st0.x, st1.y); rl.gl.rlVertex2f(p0.x, p1.y); rl.rlTexCoord2f(st0.x, st1.y); rl.rlVertex2f(p0.x, p1.y);
rl.gl.rlTexCoord2f(st1.x, st1.y); rl.gl.rlVertex2f(p1.x, p1.y); rl.rlTexCoord2f(st1.x, st1.y); rl.rlVertex2f(p1.x, p1.y);
rl.gl.rlTexCoord2f(st1.x, st0.y); rl.gl.rlVertex2f(p1.x, p0.y); rl.rlTexCoord2f(st1.x, st0.y); rl.rlVertex2f(p1.x, p0.y);
} else { } else {
std.log.warn("kb_text_shape found the glyph, but we didn't load it from the font. index {}", .{RunGlyph.Id}); std.log.warn("kb_text_shape found the glyph, but we didn't load it from the font. index {}", .{RunGlyph.Id});
@@ -320,9 +315,9 @@ pub const Font = struct {
} }
} }
rl.gl.rlEnd(); rl.rlEnd();
rl.gl.rlSetTexture(0); rl.rlSetTexture(0);
rl.endShaderMode(); rl.EndShaderMode();
} }
pub fn size_row(self: *Font, str: []const u8, n: i32, max_width: f32) struct {rl.Vector2, f32, i32} { pub fn size_row(self: *Font, str: []const u8, n: i32, max_width: f32) struct {rl.Vector2, f32, i32} {
@@ -373,7 +368,7 @@ pub const Font = struct {
}; };
fn my_kbts_ShapeRun(Context: ?*kb.kbts_shape_context, Run: [*c]kb.kbts_run) c_int { fn my_kbts_ShapeRun(Context: ?*kb.kbts_shape_context, Run: [*c]kb.kbts_run) c_int {
const zone = ztracy.ZoneNC(@src(), "my_kbts_ShapeRun", 0x00_ff_00_00); const zone = tracy.ZoneNC(@src(), "my_kbts_ShapeRun", 0x00_ff_00_00);
defer zone.End(); defer zone.End();
return kb.kbts_ShapeRun(Context, Run); return kb.kbts_ShapeRun(Context, Run);
} }
+156 -239
View File
@@ -1,20 +1,22 @@
const std = @import("std"); const std = @import("std");
const zm = @import("zmath"); const zm = @import("zmath");
const znet = @import("znet"); // const bufzilla = @import("bufzilla");
const rl = @import("raylib"); const ft = @import("freetype");
const bufzilla = @import("bufzilla"); const tracy = @import("tracy");
const ft = @import("mach-freetype");
const ztracy = @import("ztracy");
const kb = @import("kb"); const kb = @import("kb");
const shared = @import("shared"); const shared = @import("shared");
const c = @import("c.zig").c;
const enet = @import("c.zig").enet;
const rl = @import("c.zig").rl;
const client = @import("client.zig"); const client = @import("client.zig");
const entity = @import("entity.zig"); const entity = @import("entity.zig");
const misc = @import("misc.zig"); const misc = @import("misc.zig");
const font = @import("font.zig"); const font = @import("font.zig");
const chunk = @import("chunk.zig");
const dt : f32 = 1.0 / 200.0; const dt : f32 = 1.0 / 240.0;
var t : f32 = 0; var t : f32 = 0;
var gt : f32 = 0; var gt : f32 = 0;
var accumulator : f32 = 0; var accumulator : f32 = 0;
@@ -28,10 +30,10 @@ var running: bool = true;
var dbg_allocator = std.heap.DebugAllocator(.{}){}; var dbg_allocator = std.heap.DebugAllocator(.{}){};
// var connection: ?std.net.Stream = undefined; var the_chunk : shared.chunk.Chunk = undefined;
pub fn main() !void { pub fn main() !void {
const tracy_zone = ztracy.ZoneNC(@src(), "main", 0x00_ff_00_00); const tracy_zone = tracy.ZoneNC(@src(), "main", 0x00_ff_00_00);
defer tracy_zone.End(); defer tracy_zone.End();
const allocator = dbg_allocator.allocator(); const allocator = dbg_allocator.allocator();
@@ -39,8 +41,6 @@ pub fn main() !void {
const deinit_status = dbg_allocator.deinit(); const deinit_status = dbg_allocator.deinit();
if (deinit_status == .leak) { if (deinit_status == .leak) {
@panic("LEAKED!"); @panic("LEAKED!");
} else {
// @panic("SUCCESS!");
} }
} }
@@ -48,22 +48,24 @@ pub fn main() !void {
_ = try stdout.write("Hello, Client!\n"); _ = try stdout.write("Hello, Client!\n");
try znet.init(); if (enet.enet_initialize() != 0) {
defer znet.deinit(); std.log.info("Failed to load ENet", .{});
// rl.setConfigFlags(.{ .window_highdpi = true, .vsync_hint = true }); return;
rl.initWindow(screen_width, screen_height, "zzz"); }
defer rl.closeWindow();
defer enet.enet_deinitialize();
rl.SetConfigFlags(rl.FLAG_WINDOW_HIGHDPI);
rl.InitWindow(screen_width, screen_height, "zzz");
defer rl.CloseWindow();
font.ft_lib = try ft.Library.init(); font.ft_lib = try ft.Library.init();
const sizes = [_]i32{ const sizes = [_]i32{
26, 30,
}; };
var vollkorn: [sizes.len]font.Font = undefined; var vollkorn: [sizes.len]font.Font = undefined;
var inconsolata: [sizes.len]font.Font = undefined;
var arabic: [sizes.len]font.Font = undefined;
// var japanese: [sizes.len]font.Font = undefined;
for (sizes, 0..) |pt, i| { for (sizes, 0..) |pt, i| {
vollkorn[i] = try font.Font.init( vollkorn[i] = try font.Font.init(
@@ -71,88 +73,27 @@ pub fn main() !void {
pt, pt,
allocator allocator
); );
inconsolata[i] = try font.Font.init(
"assets/fonts/Inconsolata/static/Inconsolata-Regular.ttf",
@intCast(pt),
allocator
);
arabic[i] = try font.Font.init(
"assets/fonts/Amiri/Amiri-Regular.ttf",
@intCast(pt),
allocator
);
// japanese[i] = try font.Font.init(
// "assets/fonts/Noto_Sans_JP/static/NotoSansJP-Regular.ttf",
// @intCast(pt),
// allocator
// );
} }
defer { defer {
for (&vollkorn) |*f| f.deinit(allocator); for (&vollkorn) |*f| f.deinit(allocator);
for (&inconsolata) |*f| f.deinit(allocator);
for (&arabic) |*f| f.deinit(allocator);
// for (&japanese) |*f| f.deinit(allocator);
} }
font.shader = try rl.loadShader(null, "assets/text.frag"); font.shader = rl.LoadShader(null, "assets/text.frag");
// const test_shader1 = try c.LoadShader(null, "assets/test_1.frag"); // const test_shader1 = try rl.LoadShader(null, "assets/test_1.frag");
// const test_shader2 = try c.LoadShader(null, "assets/test_2.frag"); // const test_shader2 = try rl.LoadShader(null, "assets/test_2.frag");
// font.shader = try rl.loadShader(null, "assets/text.frag"); const host = enet.enet_host_create(null, 32, 2, 0, 0);
// const test_shader1 = try rl.loadShader(null, "assets/test_1.frag"); defer enet.enet_host_destroy(host);
// const test_shader2 = try rl.loadShader(null, "assets/test_2.frag");
// const img = rl.genImageColor(32, 32, .blank); var address = enet.ENetAddress{ .port = shared.protocol_v1.SERVER_PORT };
// const tx = try rl.loadTextureFromImage(img); _ = enet.enet_address_set_host(&address, "localhost");
// rl.unloadImage(img);
const host = try znet.Host.init(.{ const peer = enet.enet_host_connect(host, &address, 2, 0);
.addr = null, defer enet.enet_peer_reset(peer);
.peer_limit = 1,
.channel_limit = .max,
.incoming_bandwidth = .unlimited,
.outgoing_bandwidth = .unlimited,
});
defer host.deinit();
// const peer = try host.connect(.{ the_chunk = try shared.chunk.Chunk.init(allocator);
// .addr = try .init(.{ defer the_chunk.deinit(allocator);
// .ip = .{ .ipv4 = "127.0.0.1" },
// .port = .{ .uint = 5000 },
// }),
// .channel_limit = .max,
// .data = 0,
// });
// connect() catch |err| switch (err) {
// error.ConnectionRefused => {
// std.log.err("server refused connection", .{});
// },
// else => {
// std.log.err("unexpected connect error: {}", .{err});
// return err;
// },
// };
// try stdout.flush();
// var the_chunk = try shared.chunk.initChunk(allocator);
// defer shared.chunk.deinitChunk(&the_chunk, allocator);
// shared.chunk.updateChunk(&the_chunk);
//var elf = entity.Elf.init();
// var send_buf: [1024]u8 = undefined;
// var writer = if (connection) |*conn| conn.writer(&send_buf) else return;
// try shared.protocol.sendHello(&writer.interface, .{ .msg = "Hello from client" });
// var recv_buf: [1024]u8 = undefined;
// var reader = if (connection) |*conn| conn.reader(&recv_buf) else return;
// const line = try reader.interface().takeDelimiterExclusive('\n');
// std.log.info("{s}", .{line});
// const camera = rl.Camera{ // const camera = rl.Camera{
// .fovy = 45, // .fovy = 45,
@@ -175,15 +116,13 @@ pub fn main() !void {
// rl.playMusicStream(music); // rl.playMusicStream(music);
// std.log.info("is music playing? {}", .{rl.isMusicStreamPlaying(music)}); // std.log.info("is music playing? {}", .{rl.isMusicStreamPlaying(music)});
var old_time : f32 = @floatCast(rl.getTime()); var old_time : f32 = @floatCast(rl.GetTime());
// var old_time : f32 = @floatCast(rl.getTime());
while (!rl.windowShouldClose()) { while (!rl.WindowShouldClose()) {
const tracy_main_zone = ztracy.ZoneNC(@src(), "loop", 0x00_ff_00_00); const tracy_main_zone = tracy.ZoneNC(@src(), "loop", 0x00_aa_33_10);
defer tracy_main_zone.End(); defer tracy_main_zone.End();
const new_time : f32 = @floatCast(rl.getTime()); const new_time : f32 = @floatCast(rl.GetTime());
// const new_time : f32 = @floatCast(rl.getTime());
var frame_time = new_time - old_time; var frame_time = new_time - old_time;
old_time = new_time; old_time = new_time;
@@ -193,31 +132,31 @@ pub fn main() !void {
t += frame_time; t += frame_time;
accumulator += frame_time * k; accumulator += frame_time * k;
// std.log.info("t: {}", .{t});
while (try host.service(0)) |event| switch (event) { var event = enet.ENetEvent{};
.connect => |data| { while (enet.enet_host_service(host, &event, 0) > 0) {
_ = data; switch (event.type) {
// std.log.info("{}", .{data.peer}); enet.ENET_EVENT_TYPE_CONNECT => {
std.log.info("A new client connected from {d}:{d}.", .{
event.peer.*.address.host,
event.peer.*.address.port
});
event.peer.*.data = @constCast(@ptrCast("Client information"));
}, },
.disconnect => |data| { enet.ENET_EVENT_TYPE_RECEIVE => {
_ = data; try on_packet(allocator, event.packet, event.peer, event.channelID);
// std.log.info("{}", .{data.peer});
enet.enet_packet_destroy(event.packet);
}, },
.receive => |data| { enet.ENET_EVENT_TYPE_DISCONNECT => {
defer data.packet.deinit(); std.log.info("disconnect", .{});
const slice = data.packet.dataSlice();
var reader = bufzilla.Reader(.{}).init(slice);
const id = try reader.readPath("id");
std.log.info("{any}", .{id});
}, },
}; else => {}
}
}
rl.pollInputEvents(); rl.PollInputEvents();
// if (peer.state() == .connected) { // if (peer.state() == .connected) {
// const packet = try znet.Packet.init("Hello, Server!", 0, .reliable); // const packet = try znet.Packet.init("Hello, Server!", 0, .reliable);
@@ -228,137 +167,39 @@ pub fn main() !void {
// rl.updateMusicStream(music); // rl.updateMusicStream(music);
while (accumulator > dt * k) { while (accumulator > dt * k) {
// update(dt * cast(float) k); the_chunk.update(dt * k);
accumulator -= dt * k; accumulator -= dt * k;
gt += dt * k; gt += dt * k;
} }
rl.beginDrawing(); const drawing_zone = tracy.ZoneNC(@src(), "Drawing", 0x00_ff_00_00);
rl.clearBackground(.sky_blue);
rl.BeginDrawing();
rl.ClearBackground(rl.SKYBLUE);
// const lorem = @embedFile("embeds/lorem.txt"); // const lorem = @embedFile("embeds/lorem.txt");
for (the_chunk.entities.items) |e| {
switch (e) {
.Soldier => |soldier| {
entity.render_soldier(soldier);
},
.Alien => |alien| {
entity.render_alien(alien);
}
}
}
vollkorn[0].render_text( vollkorn[0].render_text(
"The night is long and cold outside.", "The night is long and cold outside.",
rl.Vector2{ .x = 0, .y = 0 }, rl.Vector2{ .x = 0, .y = 0 },
true, true,
.white, rl.WHITE,
.blank, rl.BLANK,
false, false,
true true
); );
// arabic[0].render_text(
// "الليل طويل وبارد في الخارج",
// rl.Vector2{ .x = 0, .y = 100},
// true,
// .white,
// .blank,
// false,
// true
// );
// var y : f32 = 0;
// var it = std.mem.splitScalar(u8, lorem, '\n');
// while (it.next()) |line| {
// vollkorn[0].render_text(
// line,
// rl.Vector2{ .x = 0, .y = y},
// true,
// .white,
// .blank,
// false,
// true
// );
// const font_linegap : f32 = @floatFromInt(vollkorn[0].face.size().metrics().height >> 6);
// const dpi_font_linegap = font_linegap / rl.getWindowScaleDPI().y;
// y += dpi_font_linegap;
// }
// for (&vollkorn) |*f| {
// f.render_text(
// "Whereas, disregard and contempt for human rights have resulted!",
// rl.Vector2{ .x = 0, .y = y},
// true,
// .white,
// .blank,
// false,
// true
// );
// // const font_ascent : f32 = @floatFromInt(f.face.size().metrics().ascender >> 6);
// // const dpi_font_ascent = font_ascent / rl.getWindowScaleDPI().y;
// // const font_descent : f32 = @floatFromInt(f.face.size().metrics().descender >> 6);
// // const dpi_font_descent = font_descent / rl.getWindowScaleDPI().y;
// const font_linegap : f32 = @floatFromInt(f.face.size().metrics().height >> 6);
// const dpi_font_linegap = font_linegap / rl.getWindowScaleDPI().y;
// y += dpi_font_linegap;
// }
// for (&inconsolata) |*f| {
// f.render_text(
// "Whereas, disregard and contempt for human rights have resulted!",
// rl.Vector2{ .x = 0, .y = y},
// true,
// .white,
// .blank,
// false,
// true
// );
// // const font_ascent : f32 = @floatFromInt(f.face.size().metrics().ascender >> 6);
// // const dpi_font_ascent = font_ascent / rl.getWindowScaleDPI().y;
// // const font_descent : f32 = @floatFromInt(f.face.size().metrics().descender >> 6);
// // const dpi_font_descent = font_descent / rl.getWindowScaleDPI().y;
// const font_linegap : f32 = @floatFromInt(f.face.size().metrics().height >> 6);
// const dpi_font_linegap = font_linegap / rl.getWindowScaleDPI().y;
// y += dpi_font_linegap;
// }
// for (&japanese) |*f| {
// f.render_text(
// "外は夜が長くて寒い",
// c.Vector2{ .x = 0, .y = y},
// true,
// c.WHITE,
// c.BLANK,
// false,
// true
// );
// const font_ascent : f32 = @floatFromInt(f.face.size().metrics().ascender >> 6);
// const dpi_font_ascent = font_ascent / c.GetWindowScaleDPI().y;
// y += dpi_font_ascent;
// }
// for (&arabic) |*f| {
// const font_ascent : f32 = @floatFromInt(f.face.size().metrics().ascender >> 6);
// const dpi_font_ascent = font_ascent / rl.getWindowScaleDPI().y;
// y += dpi_font_ascent;
// }
// f.render_text(
// "Whereas, disregard and contempt for human rights have resulted!",
// rl.Vector2.init(0, 0),
// true,
// rl.Color.white,
// rl.Color.blank,
// false,
// true
// );
// rl.beginShaderMode(test_shader1); // rl.beginShaderMode(test_shader1);
// rl.gl.rlBegin(rl.gl.rl_quads); // rl.gl.rlBegin(rl.gl.rl_quads);
@@ -482,20 +323,96 @@ pub fn main() !void {
// rl.drawSphere(.{ .x = 0, .y = 0, .z = 0 }, 1, .red); // rl.drawSphere(.{ .x = 0, .y = 0, .z = 0 }, 1, .red);
// rl.endMode3D(); // rl.endMode3D();
rl.endDrawing(); rl.EndDrawing();
drawing_zone.End();
const swap_zone = ztracy.ZoneNC(@src(), "swapScreenBuffer", 0x00_ff_00_00); const swap_zone = tracy.ZoneNC(@src(), "SwapScreenBuffer", 0x00_ff_00_00);
rl.swapScreenBuffer(); rl.SwapScreenBuffer();
swap_zone.End(); swap_zone.End();
frame += 1; frame += 1;
ztracy.FrameMark(); tracy.FrameMark();
}
}
fn on_packet(allocator: std.mem.Allocator, packet: *enet.ENetPacket, peer: *enet.ENetPeer, channelID: i32) !void {
// std.log.info("A packet of length {d} containing {s} was received from {s} on channel {d}.", .{
// packet.*.dataLength,
// packet.*.data,
// @as([*:0]const u8, @ptrCast(peer.*.data.?)),
// channelID});
_ = peer;
_ = channelID;
const bytes: []const u8 = packet.*.data[0 .. packet.*.dataLength];
var reader = shared.bits.BitReader.init(bytes);
const msg : shared.protocol_v1.Message = try reader.deserialize(allocator, shared.protocol_v1.Message);
try on_message(allocator, msg);
}
fn on_message(allocator: std.mem.Allocator, msg: shared.protocol_v1.Message) !void {
switch (msg) {
.spawn_entity => |se| { try on_spawn_entity(allocator, se); },
.update_entity => |ue| { on_update_entity(ue); },
.despawn_entity => |de| { on_despawn_entity(allocator, de); },
}
}
fn on_spawn_entity(allocator: std.mem.Allocator, p: shared.protocol_v1.EntityPayload) !void {
// _ = allocator; _ = se;
switch (p) {
.soldier => |s| {
const soldier = shared.entity.Soldier{
.id = s.id,
.hp = s.hp,
.pos = s.pos,
.vel = s.vel,
};
_ = try chunk.spawn(&the_chunk, allocator, shared.entity.Soldier, soldier);
},
.alien => |a| {
const alien = shared.entity.Alien{
.id = a.id,
.hp = a.hp,
.pos = a.pos,
};
_ = try chunk.spawn(&the_chunk, allocator, shared.entity.Alien, alien);
},
}
}
fn on_update_entity(p: shared.protocol_v1.EntityPayload) void {
switch (p) {
.soldier => |s| {
if (chunk.findT(&the_chunk, shared.entity.Soldier, s.id)) |soldier| {
soldier.hp = s.hp;
soldier.pos = s.pos;
soldier.vel = s.vel;
}
},
.alien => |a| {
if (chunk.findT(&the_chunk, shared.entity.Alien, a.id)) |alien| {
alien.hp = a.hp;
alien.pos = a.pos;
}
},
}
}
fn on_despawn_entity(allocator: std.mem.Allocator, p: shared.protocol_v1.EntityPayload) void {
switch (p) {
.soldier => |s| { _ = chunk.despawn(&the_chunk, allocator, s.id); },
.alien => |a| { _ = chunk.despawn(&the_chunk, allocator, a.id); },
} }
} }
fn connect() !void { fn connect() !void {
// const address = try std.net.Address.parseIp4("127.0.0.1", shared.protocol.SERVER_PORT); // const address = try std.net.Address.parseIp4("127.0.0.1", shared.protocol_v1.SERVER_PORT);
// connection = try std.net.tcpConnectToAddress(address); // connection = try std.net.tcpConnectToAddress(address);
+7 -17
View File
@@ -1,4 +1,4 @@
const rl = @import("raylib"); const rl = @import("c.zig").rl;
const FPS_CAPTURE_FRAMES_COUNT : i32 = 30; // 30 captures const FPS_CAPTURE_FRAMES_COUNT : i32 = 30; // 30 captures
const FPS_AVERAGE_TIME_SECONDS : f32 = 0.5; // 500 milliseconds const FPS_AVERAGE_TIME_SECONDS : f32 = 0.5; // 500 milliseconds
@@ -10,33 +10,23 @@ var average : f32 = 0;
var last : f32 = 0; var last : f32 = 0;
pub fn drawFPS(posX : i32, posY : i32, fpsFrame : f32) void { pub fn drawFPS(posX : i32, posY : i32, fpsFrame : f32) void {
var color : rl.Color = .lime; // Good FPS var color : rl.Color = rl.LIME; // Good FPS
const fps : i32 = getFPS(fpsFrame); const fps : i32 = getFPS(fpsFrame);
if ((fps < 30) and (fps >= 15)) {color = .orange;} // Warning FPS if ((fps < 30) and (fps >= 15)) {color = rl.ORANGE;} // Warning FPS
else if (fps < 15) color = .red; // Low FPS else if (fps < 15) color = rl.RED; // Low FPS
rl.drawText(rl.textFormat("%2i FPS", .{fps}), posX, posY, 20, color); rl.DrawText(rl.TextFormat("%2i FPS", fps), posX, posY, 20, color);
} }
pub fn getFPS(fpsFrame : f32) i32 { pub fn getFPS(fpsFrame : f32) i32 {
var fps : i32 = 0; var fps : i32 = 0;
// if we reset the window, reset the FPS info
// if (frame == 0)
// {
// average = 0;
// last = 0;
// index = 0;
// for (0..FPS_CAPTURE_FRAMES_COUNT) |i| history[i] = 0;
// }
if (fpsFrame == 0) return 0; if (fpsFrame == 0) return 0;
if ((rl.getTime() - last) > FPS_STEP) if ((rl.GetTime() - last) > FPS_STEP)
{ {
last = @floatCast(rl.getTime()); last = @floatCast(rl.GetTime());
index = (index + 1) % FPS_CAPTURE_FRAMES_COUNT; index = (index + 1) % FPS_CAPTURE_FRAMES_COUNT;
average -= history[index]; average -= history[index];
history[index] = fpsFrame / FPS_CAPTURE_FRAMES_COUNT; history[index] = fpsFrame / FPS_CAPTURE_FRAMES_COUNT;
+3
View File
@@ -0,0 +1,3 @@
pub const enet = @cImport({
@cInclude("enet/enet.h");
});
+37 -24
View File
@@ -1,43 +1,56 @@
const std = @import("std"); const std = @import("std");
const znet = @import("znet"); // const bufzilla = @import("bufzilla");
const bufzilla = @import("bufzilla");
const shared = @import("shared"); const shared = @import("shared");
const server = @import("server.zig"); const server = @import("server.zig");
const enet = @import("c.zig").enet;
pub fn spawn(chunk: *shared.chunk.Chunk, comptime T: type, allocator: std.mem.Allocator, value: T) !void { pub fn spawn(self: *shared.chunk.Chunk, allocator: std.mem.Allocator, host: *enet.ENetHost, comptime T: type, value: T) !shared.entity.id {
std.debug.assert(value.id == shared.entity.INVALID_ID); std.debug.assert(value.id == shared.entity.INVALID_ID);
const id = server.next_entity_id; const id = server.next_entity_id;
server.next_entity_id += 1; server.next_entity_id += 1;
var entity = value; const ptr = try allocator.create(T);
entity.id = id; errdefer allocator.destroy(ptr);
inline for (@typeInfo(shared.chunk.Chunk).@"struct".fields) |field| { ptr.* = value;
if (field.type == shared.chunk.Storage(T)) { ptr.id = id;
try @field(chunk, field.name).items.append(allocator, entity);
break; const ref = shared.entity.makeRef(T, ptr);
}
} try self.entities.append(allocator, ref);
_ = host;
// std.log.info("{}", .{shared.protocol.makeSpawnMessage(T, entity)});
// serialize entity // serialize entity
var buffer: [128]u8 = undefined; // const msg = shared.protocol.makeSpawnMessage(T, entity);
var fixed = std.io.Writer.fixed(&buffer);
const msg = shared.protocol.makeSpawnMessage(T, entity); // const data = fixed.buffered();
// const packet = enet.enet_packet_create(data.ptr, data.len + 1, enet.ENET_PACKET_FLAG_RELIABLE);
var writer = bufzilla.Writer.init(&fixed); // enet.enet_host_broadcast(host, 0, packet);
try writer.writeAny(msg);
const encoded = fixed.buffered(); return ptr.id;
const packet = try znet.Packet.init(encoded, 0, .reliable);
var iterator = server.host.iterPeers();
while (iterator.next()) |peer| {
if (peer.state() == .connected) {
try peer.send(packet);
} }
pub fn broadcastChanges(chunk: *shared.chunk.Chunk, allocator: std.mem.Allocator, host: *enet.ENetHost) !void {
var aw = try std.ArrayList(u8).initCapacity(allocator, 128);
defer aw.deinit(allocator);
var writer = shared.bits.BitWriter.init(&aw);
for (chunk.entities.items) |e| {
const msg = shared.protocol_v1.makeMessage(.update_entity, e);
try writer.serialize(allocator, msg);
} }
const encoded = writer.written();
const packet = enet.enet_packet_create(encoded.ptr, encoded.len, enet.ENET_PACKET_FLAG_RELIABLE);
enet.enet_host_broadcast(host, 0, packet);
} }
+112 -56
View File
@@ -1,84 +1,101 @@
const std = @import("std"); const std = @import("std");
const zm = @import("zmath"); const zm = @import("zmath");
const znet = @import("znet"); const enet = @import("c.zig").enet;
// const bufzilla = @import("bufzilla");
const shared = @import("shared"); const shared = @import("shared");
const chunk = @import("chunk.zig"); const chunk = @import("chunk.zig");
const server = @import("server.zig"); const server = @import("server.zig");
const dt : f32 = 1.0 / 200.0; const dt : f32 = 1.0 / 240.0;
var t : f32 = 0; var t : f32 = 0;
var gt : f32 = 0; var gt : f32 = 0;
var accumulator : f32 = 0;
var k : f32 = 1.0; var k : f32 = 1.0;
var frame : i32 = 0; var frame : i32 = 0;
var stdout: *std.io.Writer = undefined; const frame_dt_ns: i128 = std.time.ns_per_s / 10;
var dbg_allocator = std.heap.DebugAllocator(.{}){};
const log = std.log.scoped(.server);
pub fn main() !void { pub fn main() !void {
std.log.info("Hello Server!", .{});
var dbg_allocator = std.heap.DebugAllocator(.{}).init;
defer _ = dbg_allocator.deinit();
const allocator = dbg_allocator.allocator(); const allocator = dbg_allocator.allocator();
defer {
const deinit_status = dbg_allocator.deinit();
if (deinit_status == .leak) {
@panic("LEAKED!");
}
}
var stdout_buffer: [1024]u8 = undefined; var stdout = std.fs.File.stdout();
var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer); _ = try stdout.write("Hello, Server!\n");
stdout = &stdout_writer.interface;
try stdout.flush(); if (enet.enet_initialize() != 0) {
log.info("Failed to load ENet", .{});
return;
}
defer enet.enet_deinitialize();
try znet.init(); const address = enet.ENetAddress{ .host = enet.ENET_HOST_ANY, .port = shared.protocol_v1.SERVER_PORT };
defer znet.deinit(); const host = enet.enet_host_create(&address, 32, 2, 0, 0);
if (host == null) {
@panic("host is null");
}
defer enet.enet_host_destroy(host);
server.host = try znet.Host.init(.{ var the_chunk = try shared.chunk.Chunk.init(allocator);
.addr = try .init(.{ defer the_chunk.deinit(allocator);
.ip = .any,
.port = .{ .uint = 5000 },
}),
.peer_limit = 32,
.channel_limit = .max,
.incoming_bandwidth = .unlimited,
.outgoing_bandwidth = .unlimited,
});
// const address = try std.net.Address.parseIp4("127.0.0.1", shared.protocol.SERVER_PORT); _ = try chunk.spawn(
// var tcp_server = try address.listen(.{}); &the_chunk,
allocator,
host,
shared.entity.Soldier,
.{
.hp = 10,
.pos = zm.f32x4(5.0, 0, 0, 0),
.vel = zm.f32x4(0, 0, 0, 0),
}
);
// defer tcp_server.deinit(); var last_time: i128 = std.time.nanoTimestamp();
var next_frame_deadline: i128 = last_time + frame_dt_ns;
var the_chunk = try shared.chunk.initChunk(allocator); var accumulator: f32 = 0;
defer shared.chunk.deinitChunk(&the_chunk, allocator);
var old_time = std.time.nanoTimestamp();
while (true) { while (true) {
const new_time = std.time.nanoTimestamp(); const now = std.time.nanoTimestamp();
var frame_time : f32 = @as(f32, @floatFromInt(new_time - old_time)) / 1_000_000_000.0; var delta_ns = now - last_time;
old_time = new_time; last_time = now;
if (frame_time > 0.25) if (delta_ns > std.time.ns_per_s / 4)
frame_time = 0.25; delta_ns = std.time.ns_per_s / 4;
t += frame_time; const delta_s: f32 = @floatCast(@as(f64, @floatFromInt(delta_ns)) / 1e9);
accumulator += frame_time * k;
// std.log.info("t: {}", .{t}); t += delta_s;
accumulator += delta_s * k;
while (try server.host.service(0)) |event| switch (event) { log.info("Starting a the frame {} at time {}", .{frame, t});
.connect => |data| {
_ = data; var event = enet.ENetEvent{};
// std.log.info("{}", .{data.peer}); while (enet.enet_host_service(host, &event, 0) > 0) {
switch (event.type) {
enet.ENET_EVENT_TYPE_CONNECT => {
try on_connect(allocator, host, event.peer, &the_chunk);
}, },
.disconnect => |data| { enet.ENET_EVENT_TYPE_RECEIVE => {
_ = data; log.info("receive", .{});
// std.log.info("{}", .{data.peer});
}, },
.receive => |data| { enet.ENET_EVENT_TYPE_DISCONNECT => {
std.log.info("{s}", .{data.packet.dataSlice()}); log.info("disconnect", .{});
defer data.packet.deinit();
}, },
}; else => {},
}
}
// const connection = try tcp_server.accept(); // const connection = try tcp_server.accept();
// defer connection.stream.close(); // defer connection.stream.close();
@@ -87,18 +104,13 @@ pub fn main() !void {
// var reader = connection.stream.reader(&recv_buffer); // var reader = connection.stream.reader(&recv_buffer);
// const line = try reader.interface().takeDelimiterExclusive('\n'); // const line = try reader.interface().takeDelimiterExclusive('\n');
// std.log.info("Received: {s}", .{line}); // log.info("Received: {s}", .{line});
// var send_buffer: [4096]u8 = undefined; // var send_buffer: [4096]u8 = undefined;
// var writer = connection.stream.writer(&send_buffer); // var writer = connection.stream.writer(&send_buffer);
// const w = &writer.interface; // const w = &writer.interface;
// try shared.protocol.sendHello(w, .{ .msg = "Hello from server!" }); // try shared.protocol.sendHello(w, .{ .msg = "Hello from server!" });
try chunk.spawn(&the_chunk, shared.entity.Elf, allocator, .{
.pos = zm.f32x4(1, 1, 0, 0),
.hp = 10,
});
// try chunk.spawn(&the_chunk, shared.entity.Monster, allocator, .{ // try chunk.spawn(&the_chunk, shared.entity.Monster, allocator, .{
// .pos = zm.f32x4(1, 1, 0, 0), // .pos = zm.f32x4(1, 1, 0, 0),
// .hp = 20, // .hp = 20,
@@ -109,8 +121,52 @@ pub fn main() !void {
// .vel = zm.f32x4(0.2, 0, 0, 0), // .vel = zm.f32x4(0.2, 0, 0, 0),
// }, w); // }, w);
shared.chunk.updateChunk(&the_chunk); while (accumulator > dt * k) {
the_chunk.update(dt * k);
accumulator -= dt * k;
gt += dt * k;
} }
try chunk.broadcastChanges(&the_chunk, allocator, host);
const spin_ns: i128 = 100_000; // 0.1 ms
while (true) {
const _t = std.time.nanoTimestamp();
const remaining = next_frame_deadline - _t;
if (remaining <= 0)
break;
if (remaining > spin_ns)
std.Thread.sleep(@intCast(remaining - spin_ns));
}
next_frame_deadline += frame_dt_ns;
frame += 1;
}
}
fn on_connect(allocator: std.mem.Allocator, host: *enet.ENetHost, peer: *enet.ENetPeer, the_chunk: *shared.chunk.Chunk) !void {
var aw = try std.ArrayList(u8).initCapacity(allocator, 128);
defer aw.deinit(allocator);
_ = peer;
var writer = shared.bits.BitWriter.init(&aw);
for (the_chunk.entities.items) |e| {
const msg = shared.protocol_v1.makeMessage(.spawn_entity, e);
try writer.serialize(allocator, msg);
}
const encoded = writer.written();
const packet = enet.enet_packet_create(encoded.ptr, encoded.len, enet.ENET_PACKET_FLAG_RELIABLE);
enet.enet_host_broadcast(host, 0, packet);
} }
//fn handle_connection(connection: std.net.Server.Connection) !void {} //fn handle_connection(connection: std.net.Server.Connection) !void {}
+286
View File
@@ -0,0 +1,286 @@
const std = @import("std");
// pub fn serialize(writer: *BitWriter, allocator: std.mem.Allocator, comptime T: type, value: T) !void {
// const info = @typeInfo(T);
// switch (info) {
// .int, .bool => {
// try writer.write(allocator, T, value);
// },
// .@"struct" => |s| {
// if (!s.is_packed)
// @compileError("serialize only supports packed structs (got " ++ @typeName(T) ++ ")");
// inline for (s.fields) |field| {
// const field_value = @field(value, field.name);
// try serialize(writer, allocator, field_value);
// }
// },
// .@"union" => |u| {
// if (u.layout != .@"packed")
// @compileError("serialize only supports packed structs (got " ++ @typeName(T) ++ ")");
// inline for (u.fields) |field| {
// const field_value = @field(value, field.name);
// try serialize(writer, allocator, field_value);
// }
// },
// else => @compileError("Unsupported type in serialize: " ++ @typeName(T)),
// }
// }
pub const BitWriter = struct {
// We store a pointer to the ArrayList so we can grow it
bytes: *std.ArrayList(u8),
bit_offset: usize = 0,
pub fn init(bytes: *std.ArrayList(u8)) BitWriter {
return .{ .bytes = bytes };
}
pub fn serialize(self: *BitWriter, allocator: std.mem.Allocator, value: anytype) !void {
const T = @TypeOf(value);
const info = @typeInfo(T);
switch (info) {
.@"struct" => |s| {
inline for (s.fields) |f|
try self.serialize(allocator, @field(value, f.name));
},
.@"union" => |u| {
const E = u.tag_type orelse @compileError(std.fmt.comptimePrint("Union {s} has to tag type.", .{@typeName(T)}));
try self.serialize(allocator, @as(E, value));
switch (value) {
inline else => |f| try self.serialize(allocator, f),
}
},
.@"enum" => try self.serialize(allocator, @intFromEnum(value)),
.pointer => |p| switch (p.size) {
.one => try self.serialize(allocator, value.*),
.slice => {
try self.serialize(allocator, value.len);
for (value) |e|
try self.serialize(allocator, e);
},
.many, .c => @compileError(std.fmt.comptimePrint("Unsupported type: {}", .{T})),
},
.int, .bool, .float, => try self.write(allocator, value),
.void => {},
.array => |a| if (@sizeOf(a.child) == 1) {
try self.write(allocator, @ptrCast(&value));
} else {
for (value) |e|
try self.serialize(allocator, e);
},
.optional => if (value) |_t| {
try self.serialize(allocator, true);
try self.serialize(allocator, _t);
} else {
try self.serialize(allocator, false);
},
.vector => |v| try self.serialize(allocator, @as([v.len]v.child, value)),
else => @compileError(std.fmt.comptimePrint("Unsupported type: {}", .{T})),
}
}
fn write(self: *BitWriter, allocator: std.mem.Allocator, value: anytype) !void {
const T = @TypeOf(value);
const bit_width = @bitSizeOf(T);
const UnsignedT = std.meta.Int(.unsigned, bit_width);
const bits_to_write = @as(UnsignedT, @bitCast(value));
var remaining : usize = bit_width;
while (remaining > 0) {
const byte_index = self.bit_offset / 8;
const bit_in_byte = self.bit_offset % 8;
// If we are moving into a new byte, grow the ArrayList
if (byte_index >= self.bytes.items.len) {
try self.bytes.append(allocator, 0);
}
const space_in_byte = 8 - bit_in_byte;
const chunk_size = @min(remaining, space_in_byte);
const mask : u8 = std.math.shr(u8, 0xFF, 8 - chunk_size);
const bits : u8 = @truncate(std.math.shr(UnsignedT, bits_to_write, remaining - chunk_size) & mask);
self.bytes.items[byte_index] |= std.math.shl(u8, bits, space_in_byte - chunk_size);
self.bit_offset += chunk_size;
remaining -= chunk_size;
}
}
pub fn written(self: *BitWriter) []const u8 {
const bytes_used = (self.bit_offset + 7) / 8; // round up bits → bytes
return self.bytes.items[0..bytes_used];
}
};
pub const BitReader = struct {
bytes: []const u8,
bit_offset: usize = 0,
pub fn init(bytes: []const u8) BitReader {
return .{ .bytes = bytes };
}
pub fn deserialize(self: *BitReader, allocator: std.mem.Allocator, T: type) !T {
return switch (@typeInfo(T)) {
.@"struct" => |s| b: {
var data: T = undefined;
inline for (s.fields) |f|
@field(data, f.name) = try self.deserialize(allocator, f.type);
break :b data;
},
.@"union" => |u| switch (try self.deserialize(allocator, u.tag_type.?)) {
inline else => |t| b: {
var data: T = @unionInit(T, @tagName(t), undefined);
const field = &@field(data, @tagName(t));
field.* = try self.deserialize(allocator, @TypeOf(field.*));
break :b data;
},
},
.@"enum" => |e| @enumFromInt(try self.deserialize(allocator, e.tag_type)),
.pointer => |p| switch (p.size) {
.one => b: {
const ptr = try allocator.create(p.child);
errdefer allocator.destroy(ptr);
ptr.* = try self.deserialize(allocator, p.child);
break :b ptr;
},
.slice => b: {
const slice = try allocator.alloc(p.child, try self.deserialize(allocator, usize));
errdefer allocator.free(slice);
for (slice) |*e|
e.* = try self.deserialize(allocator, p.child);
break :b slice;
},
.many, .c => @compileError(std.fmt.comptimePrint("Unsupported type: {}", .{T})),
},
.int, .bool, .float => self.read(T),
.void => {},
.array => |a| b: {
var array: T = undefined;
if (@sizeOf(a.child) == 1) {
try self.read(&array);
} else {
for (&array) |*e|
e.* = try self.deserialize(allocator, a.child);
}
break :b array;
},
.optional => |o| if (try self.deserialize(allocator, bool))
try self.deserialize(o.child, allocator)
else
null,
.vector => |v| try self.deserialize(allocator, [v.len]v.child),
else => @compileError(std.fmt.comptimePrint("Unsupported type: {}", .{T})),
};
}
pub fn read(self: *BitReader, comptime T: type) T {
// const info = @typeInfo(T);
const bit_width = @bitSizeOf(T);
const UnsignedT = std.meta.Int(.unsigned, bit_width);
var remaining: usize = bit_width;
var result: UnsignedT = 0;
while (remaining > 0) {
const byte_index = self.bit_offset / 8;
const bit_in_byte = self.bit_offset % 8;
const space_in_byte = 8 - bit_in_byte;
const chunk_size = @min(remaining, space_in_byte);
const mask: u8 = std.math.shr(u8, 0xFF, 8 - chunk_size);
// Extract chunk MSB-first from current byte
const shift_from_byte = space_in_byte - chunk_size;
const bits: u8 = std.math.shr(u8, self.bytes[byte_index], shift_from_byte) & mask;
// Shift into result (from MSB side)
result |= std.math.shl(UnsignedT, @intCast(bits), remaining - chunk_size);
self.bit_offset += chunk_size;
remaining -= chunk_size;
}
return @bitCast(result);
}
};
test "Bit Stream" {
std.debug.print("Bit Stream\n", .{});
const allocator = std.testing.allocator;
var aw = try std.ArrayList(u8).initCapacity(allocator, 128);
defer aw.deinit(allocator);
var writer = BitWriter.init(&aw);
const _a : u3 = 0x5;
const _b : bool = true;
const _c : u3 = 0x1;
const _d : u4 = 0xE;
const _e : u32 = 0xFFFFFFFA;
const _f : i32 = -3;
const _g : f32 = 6.667;
const ts = struct {
a: i32,
n: []const u8,
pub fn format(self: @This(), w: *std.io.Writer) !void {
try w.print(".{{ .a = {}, .n = \"{s}\" }}", .{ self.a, self.n });
}
};
const _h : ts = .{
.a = 44,
.n = "hello",
};
try writer.serialize(allocator, _a);
try writer.serialize(allocator, _b);
try writer.serialize(allocator, _c);
try writer.serialize(allocator, _d);
try writer.serialize(allocator, _e);
try writer.serialize(allocator, _f);
try writer.serialize(allocator, _g);
try writer.serialize(allocator, _h);
var reader = BitReader.init(writer.written());
const _1 : u3 = try reader.deserialize(allocator, u3);
const _2 : bool = try reader.deserialize(allocator, bool);
const _3 : u3 = try reader.deserialize(allocator, u3);
const _4 : u4 = try reader.deserialize(allocator, u4);
const _5 : u32 = try reader.deserialize(allocator, u32);
const _6 : i32 = try reader.deserialize(allocator, i32);
const _7 = try reader.deserialize(allocator, f32);
const _8 = try reader.deserialize(allocator, ts);
defer allocator.free(_8.n);
try std.testing.expectEqual(_a, _1);
try std.testing.expectEqual(_b, _2);
try std.testing.expectEqual(_c, _3);
try std.testing.expectEqual(_d, _4);
try std.testing.expectEqual(_e, _5);
try std.testing.expectEqual(_f, _6);
try std.testing.expectEqual(_g, _7);
try std.testing.expectEqualDeep(_h, _8);
}
+3
View File
@@ -0,0 +1,3 @@
pub const enet = @cImport({
@cInclude("enet/enet.h");
});
+106 -79
View File
@@ -2,93 +2,120 @@ const std = @import("std");
const entity = @import("entity.zig"); const entity = @import("entity.zig");
const misc = @import("misc.zig"); const misc = @import("misc.zig");
pub fn Storage(comptime T: type) type { // pub fn Storage(comptime T: type) type {
return struct { // return struct {
items: std.ArrayList(T), // items: std.ArrayList(T),
pub fn init(allocator: std.mem.Allocator) !@This() { // 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 const Chunk = _Chunk();
// fn _Chunk() type {
// const FieldCount = entity.EntityKinds.len;
// var fields: [FieldCount]std.builtin.Type.StructField = undefined;
// inline for (entity.EntityKinds, 0..) |T, i| {
// fields[i] = .{
// .name = misc.short_type_name(T),
// .type = std.ArrayList(T),
// .default_value_ptr = null,
// .is_comptime = false,
// .alignment = @alignOf(std.ArrayList(T)),
// };
// }
// return @Type(.{
// .@"struct" = .{
// .layout = .auto,
// .fields = &fields,
// .decls = &.{},
// .is_tuple = false,
// },
// });
// }
// pub fn initChunk(allocator: std.mem.Allocator) !Chunk {
// var chunk: Chunk = undefined;
// inline for (@typeInfo(Chunk).@"struct".fields) |field| {
// const ListT = field.type;
// @field(chunk, field.name) = try ListT.initCapacity(allocator, 32);
// }
// 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,
// }
// }
// pub fn updateChunk(chunk: *Chunk) void {
// inline for (@typeInfo(Chunk).@"struct".fields) |field| {
// const list = &@field(chunk, field.name);
// for (list.items, 0..) |*item, i| {
// _ = i;
// if (@hasDecl(@TypeOf(item.*), "update"))
// item.update();
// }
// }
// }
pub const Chunk = struct {
entities : std.ArrayList(entity.Ref),
pub fn init(allocator: std.mem.Allocator) !Chunk {
return .{ return .{
.items = try std.ArrayList(T).initCapacity(allocator, 32), .entities = try std.ArrayList(entity.Ref).initCapacity(allocator, 128),
}; };
} }
pub fn deinit(self: *@This(), allocator: std.mem.Allocator) void { pub fn deinit(self: *@This(), allocator: std.mem.Allocator) void {
self.items.deinit(allocator); for (self.entities.items) |ref| {
switch (ref) {
inline else => |ptr| allocator.destroy(ptr),
}
} }
pub fn update(self: *@This()) void { self.entities.deinit(allocator);
for (self.items.items, 0..) |*item, i| { }
_ = i;
if (@hasDecl(T, "update")) pub fn update(self: *@This(), dt: f32) void {
item.update(); for (self.entities.items) |e| {
switch (e) {
.Soldier => |s| {
s.update(dt);
},
.Alien => |a| {
a.update(dt);
},
}
} }
} }
}; };
}
pub const Chunk = _Chunk();
fn _Chunk() type {
const FieldCount = entity.EntityKinds.len;
var fields: [FieldCount]std.builtin.Type.StructField = undefined;
inline for (entity.EntityKinds, 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 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,
}
}
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,
}
}
+85 -25
View File
@@ -1,43 +1,103 @@
const std = @import("std"); const std = @import("std");
const zm = @import("zmath"); const zm = @import("zmath");
const protocol = @import("protocol.zig"); const misc = @import("misc.zig");
pub const id = u64; pub const id = u64;
pub const INVALID_ID: id = 0; pub const INVALID_ID: id = 0;
pub const EntityKinds = .{ pub const EntityKinds = .{
Elf, Soldier,
Monster, Alien,
Projectile,
}; };
pub const Elf = struct { const Entity = struct {
};
pub const Soldier = struct {
id: id = INVALID_ID, id: id = INVALID_ID,
pos: zm.Vec, hp: i32 = 0,
hp: i32, pos: zm.Vec = .{0, 0, 0, 0},
vel: zm.Vec = .{0, 0, 0, 0},
pub fn update(self: *Elf) void { pub fn update(self: *@This(), dt: f32) void {
self.pos += zm.f32x4(1, 1, 0, 0); self.pos = self.pos + self.vel * zm.splat(zm.Vec, dt);
}
pub fn to_message(self: *Elf) protocol.Elf_v1 {
return protocol.Elf_v1.init(self);
} }
}; };
pub const Monster = struct { pub const Alien = struct {
id: id = INVALID_ID, id: id = INVALID_ID,
pos: zm.Vec, hp: i32 = 0,
hp: i32, pos: zm.Vec = .{0, 0, 0, 0},
}; vel: zm.Vec = .{0, 0, 0, 0},
pub const Projectile = struct { pub fn update(self: *@This(), dt: f32) void {
id: id = INVALID_ID, self.pos = self.pos + self.vel * zm.splat(zm.Vec, dt);
pos: zm.Vec,
vel: zm.Vec,
pub fn update(self: *Projectile) void {
self.pos = self.pos + self.vel;
std.log.info("pos=({})", .{self.pos});
} }
}; };
fn _Ref() type {
const FieldCount = EntityKinds.len;
var tag_fields: [FieldCount]std.builtin.Type.EnumField = undefined;
inline for (EntityKinds, 0..) |T, i| {
tag_fields[i] = .{
.name = misc.short_type_name(T),
.value = i,
};
}
const Tag = @Type(.{
.@"enum" = .{
.tag_type = u8,
.fields = &tag_fields,
.decls = &.{},
.is_exhaustive = true,
},
});
var fields: [FieldCount]std.builtin.Type.UnionField = undefined;
inline for (EntityKinds, 0..) |T, i| {
fields[i] = .{
.name = misc.short_type_name(T),
.type = *T,
.alignment = @alignOf(*T),
};
}
return @Type(.{
.@"union" = .{
.layout = .auto,
.fields = &fields,
.decls = &.{},
.tag_type = Tag,
},
});
}
pub const Ref = _Ref();
pub fn setPos(self: Ref, pos: zm.Vec) void {
switch (self) {
.Soldier => |s| { s.pos = pos; },
.Alien => |a| { a.pos = pos; },
else => unreachable
}
}
pub fn makeRef(comptime T: type, ptr: *T) Ref {
inline for (EntityKinds) |U| {
if (T == U) {
return @unionInit(
Ref,
misc.short_type_name(U),
ptr,
);
}
}
@compileError("Type not in EntityKinds: " ++ @typeName(T));
}
-146
View File
@@ -1,146 +0,0 @@
const std = @import("std");
const zm = @import("zmath");
const bufzilla = @import("bufzilla");
const entity = @import("entity.zig");
pub const SERVER_PORT: u16 = 1337;
pub const Message = union(enum) {
spawn_entity: SpawnEntity,
// later: despawn_entity, update_entity, snapshot, etc.
};
pub const SpawnEntity = union(enum) {
elf_v1: Elf_v1,
monster_v1: Monster_v1,
projectile_v1: Projectile_v1,
};
pub fn makeSpawnMessage(comptime T: type, e: T) Message {
if (T == entity.Elf) {
return .{ .spawn_entity = .{ .elf_v1 = Elf_v1.init(e) } };
} else if (T == entity.Monster) {
return .{ .spawn_entity = .{ .monster_v1 = Monster_v1.init(e) } };
} else if (T == entity.Projectile) {
return .{ .spawn_entity = .{ .projectile_v1 = Projectile_v1.init(e) } };
}
}
// pub fn write_message(writer: *std.Io.Writer, msg_type: MessageType, payload: []const u8) !void {
// try writer.writeByte(@intFromEnum(msg_type));
// try writer.writeInt(u32, @intCast(payload.len), .little);
// try writer.writeAll(payload);
// }
// pub fn read_message(reader: *std.Io.Reader, allocator: std.mem.Allocator) !struct {
// msg_type: MessageType,
// payload: []u8,
// } {
// const msg_type = try reader.readByte();
// const size = try reader.readInt(u32, .little);
// const payload = try allocator.alloc(u8, size);
// errdefer allocator.free(payload);
// try reader.readNoEof(payload);
// return .{
// .msg_type = @enumFromInt(msg_type),
// .payload = payload,
// };
// }
pub const Elf_v1 = struct {
id: entity.id = entity.INVALID_ID,
pos: zm.Vec,
hp: i32,
pub fn init(elf: entity.Elf) Elf_v1 {
return .{
.id = elf.id,
.pos = elf.pos,
.hp = elf.hp,
};
}
pub fn decode(r: *bufzilla.Reader) !Elf_v1 {
_ = r;
return .{
// .id = try r.readInt(u64, .little),
// .pos = try readVec4(r),
// .vel = try readVec4(r),
};
}
};
pub const Monster_v1 = struct {
id: entity.id = entity.INVALID_ID,
pos: zm.Vec,
hp: i32,
pub fn init(monster: entity.Monster) Monster_v1 {
return .{
.id = monster.id,
.pos = monster.pos,
.hp = monster.hp,
};
}
// pub fn encode(self: Monster_v1, w: *std.Io.Writer) !void {
// try w.writeInt(u64, self.id, .little);
// try writeVec4(w, self.pos);
// try writeVec4(w, self.vel);
// }
pub fn decode(r: *std.Io.Reader) !Monster_v1 {
return .{
.id = try r.readInt(u64, .little),
.pos = try readVec4(r),
.vel = try readVec4(r),
};
}
};
pub const Projectile_v1 = struct {
id: entity.id = entity.INVALID_ID,
pos: zm.Vec,
vel: zm.Vec,
pub fn init(projectile: entity.Projectile) Projectile_v1 {
return .{
.id = projectile.id,
.pos = projectile.pos,
.vel = projectile.vel,
};
}
// pub fn encode(self: Projectile_v1, w: *std.Io.Writer) !void {
// try w.writeInt(u64, self.id, .little);
// try writeVec4(w, self.pos);
// try writeVec4(w, self.vel);
// }
pub fn decode(r: *std.Io.Reader) !Projectile_v1 {
return .{
.id = try r.readInt(u64, .little),
.pos = try readVec4(r),
.vel = try readVec4(r),
};
}
};
fn writeVec4(w: *std.Io.Writer, v: zm.Vec) !void {
const a = zm.vecToArr4(v);
inline for (a) |f| {
try w.writeFloat(f32, f, .little);
}
}
fn readVec4(r: *std.Io.Reader) !zm.Vec4 {
var a: [4]f32 = undefined;
inline for (&a) |*f| {
f.* = try r.readFloat(f32, .little);
}
return zm.loadArr4(a);
}
+109
View File
@@ -0,0 +1,109 @@
const std = @import("std");
const zm = @import("zmath");
// const bufzilla = @import("bufzilla");
const entity = @import("entity.zig");
const bits = @import("bits.zig");
pub const SERVER_PORT: u16 = 1337;
const MessageKind = enum(c_char) {
spawn_entity,
update_entity,
despawn_entity,
};
pub const Message = union(MessageKind) {
spawn_entity: EntityPayload,
update_entity: EntityPayload,
despawn_entity: EntityPayload,
};
pub fn makeMessage(kind: MessageKind, e: anytype) Message {
const payload = payloadFromEntity(e);
return switch (kind) {
.spawn_entity => .{ .spawn_entity = payload },
.update_entity => .{ .update_entity = payload },
.despawn_entity => .{ .despawn_entity = payload },
};
}
pub fn payloadFromEntity(e: entity.Ref) EntityPayload {
return switch (e) {
.Soldier => |s| .{ .soldier = Soldier.init(s.*) },
.Alien => |a| .{ .alien = Alien.init(a.*) },
};
}
const EntityKind = enum(c_char) {
soldier,
alien,
};
pub const EntityPayload = union(EntityKind) {
soldier: Soldier,
alien: Alien,
};
pub const Soldier = struct {
id: entity.id = entity.INVALID_ID,
hp: i32,
pos: zm.Vec,
vel: zm.Vec,
pub fn init(soldier: entity.Soldier) Soldier {
return .{
.id = soldier.id,
.hp = soldier.hp,
.pos = soldier.pos,
.vel = soldier.vel,
};
}
};
pub const Alien = struct {
id: entity.id = entity.INVALID_ID,
hp: i32,
pos: zm.Vec,
pub fn init(alien: entity.Alien) Alien {
return .{
.id = alien.id,
.pos = alien.pos,
.hp = alien.hp,
};
}
};
test "Protocol" {
std.debug.print("Protocol\n", .{});
const s = entity.Soldier{
.hp = 66,
.pos = .{1, 2, 3, 4},
.vel = .{5, 6, 7, 8},
};
const msg = makeMessage(.spawn_entity, s);
const allocator = std.testing.allocator;
var aw = try std.ArrayList(u8).initCapacity(allocator, 128);
defer aw.deinit(allocator);
var writer = bits.BitWriter.init(&aw);
try writer.serialize(allocator, msg);
var reader = bits.BitReader.init(writer.written());
const recv = try reader.deserialize(allocator, Message);
std.debug.print("msg: {}\n", .{msg});
std.debug.print("recv: {}\n", .{recv});
try std.testing.expectEqual(msg, recv);
}
+7 -1
View File
@@ -1,4 +1,10 @@
pub const entity = @import("entity.zig"); pub const entity = @import("entity.zig");
pub const chunk = @import("chunk.zig"); pub const chunk = @import("chunk.zig");
pub const misc = @import("misc.zig"); pub const misc = @import("misc.zig");
pub const protocol = @import("protocol.zig"); pub const protocol_v1 = @import("protocol_v1.zig");
pub const bits = @import("bits.zig");
test {
const std = @import("std");
std.testing.refAllDecls(@This());
}
+74
View File
@@ -0,0 +1,74 @@
const std = @import("std");
pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const enet_src = b.dependency("enet_src", .{});
const lib = b.addLibrary(.{
.name = "enet",
.linkage = .static,
.root_module = b.createModule(.{
.target = target,
.optimize = optimize,
}),
});
var flags = try std.ArrayList([]const u8).initCapacity(b.allocator, 0);
switch (target.result.os.tag) {
.linux, .macos => {
try flags.append(b.allocator, "-DHAS_FCNTL=1");
try flags.append(b.allocator, "-DHAS_POLL=1");
try flags.append(b.allocator, "-DHAS_GETADDRINFO=1");
try flags.append(b.allocator, "-DHAS_GETNAMEINFO=1");
try flags.append(b.allocator, "-DHAS_INET_PTON=1");
try flags.append(b.allocator, "-DHAS_INET_NTOP=1");
try flags.append(b.allocator, "-DHAS_MSGHDR_FLAGS=1");
},
else => {},
}
try flags.append(b.allocator, "-DHAS_OFFSETOF=1");
try flags.append(b.allocator, "-DHAS_SOCKLEN_T=1");
lib.root_module.addCSourceFiles(.{
.root = enet_src.path(""),
.files = &[_][]const u8{
"callbacks.c",
"compress.c",
"host.c",
"list.c",
"packet.c",
"peer.c",
"protocol.c",
"unix.c",
"win32.c",
},
.flags = &[_][]const u8{
"-DHAS_OFFSETOF=1",
"-DHAS_SOCKLEN_T=1",
"-DHAS_FCNTL=1",
"-DHAS_POLL=1",
"-DHAS_GETADDRINFO=1",
"-DHAS_GETNAMEINFO=1",
"-DHAS_INET_PTON=1",
"-DHAS_INET_NTOP=1",
"-DHAS_MSGHDR_FLAGS=1",
}
});
if (target.result.os.tag == .windows) {
lib.root_module.linkSystemLibrary("ws2_32", .{});
lib.root_module.linkSystemLibrary("winmm", .{});
}
lib.root_module.addIncludePath(enet_src.path("include"));
lib.root_module.link_libc = true;
lib.installHeadersDirectory(enet_src.path("include/enet"), "enet", .{});
b.installArtifact(lib);
}
+19
View File
@@ -0,0 +1,19 @@
.{
.name = .enet,
.fingerprint = 0x201714c0933cd1fc,
.version = "0.1.0",
.minimum_zig_version = "0.15.2",
.paths = .{
"build.zig",
"build.zig.zon",
"libs",
"src",
"README.md",
},
.dependencies = .{
.enet_src = .{
.url = "https://github.com/lsalzman/enet/archive/refs/heads/master.tar.gz",
.hash = "N-V-__8AAOfEBQDV0QE6f1lRiGiqZa9k3-ZkthJHdwGIp3Zh",
},
},
}
+145
View File
@@ -0,0 +1,145 @@
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
// const use_system_zlib = b.option(bool, "use_system_zlib", "Use system zlib") orelse false;
// const enable_brotli = b.option(bool, "enable_brotli", "Build Brotli") orelse true;
const freetype_src = b.dependency("freetype_src", .{ .target = target, .optimize = optimize });
const lib = b.addLibrary(.{
.name = "freetype",
.linkage = .static,
.root_module = b.createModule(.{
.target = target,
.optimize = optimize,
}),
});
lib.root_module.link_libc = true;
lib.addIncludePath(b.path("include"));
lib.root_module.addCMacro("FT2_BUILD_LIBRARY", "1");
// if (use_system_zlib) {
// lib.root_module.addCMacro("FT_CONFIG_OPTION_SYSTEM_ZLIB", "1");
// }
// if (enable_brotli) {
// lib.root_module.addCMacro("FT_CONFIG_OPTION_USE_BROTLI", "1");
// if (b.lazyDependency("brotli", .{
// .target = target,
// .optimize = optimize,
// })) |dep| lib.linkLibrary(dep.artifact("brotli"));
// }
lib.root_module.addCMacro("HAVE_UNISTD_H", "1");
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/autofit/autofit.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/base/ftbase.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/base/ftsystem.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/base/ftdebug.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/base/ftbbox.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/base/ftbdf.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/base/ftbitmap.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/base/ftcid.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/base/ftfstype.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/base/ftgasp.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/base/ftglyph.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/base/ftgxval.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/base/ftinit.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/base/ftmm.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/base/ftotval.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/base/ftpatent.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/base/ftpfr.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/base/ftstroke.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/base/ftsynth.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/base/fttype1.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/base/ftwinfnt.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/bdf/bdf.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/bzip2/ftbzip2.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/cache/ftcache.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/cff/cff.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/cid/type1cid.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/gzip/ftgzip.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/lzw/ftlzw.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/pcf/pcf.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/pfr/pfr.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/psaux/psaux.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/pshinter/pshinter.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/psnames/psnames.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/raster/raster.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/sdf/sdf.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/sfnt/sfnt.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/smooth/smooth.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/svg/svg.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/truetype/truetype.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/type1/type1.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/type42/type42.c") });
lib.root_module.addCSourceFile(.{ .file = freetype_src.path("src/winfonts/winfnt.c") });
lib.root_module.addIncludePath(freetype_src.path("include"));
// lib.addCSourceFiles(.{ .files = &sources, .flags = &.{} });
if (target.result.os.tag == .macos)
lib.addCSourceFile(.{
.file = freetype_src.path("src/base/ftmac.c"),
.flags = &.{},
});
lib.installHeadersDirectory(freetype_src.path("include/freetype"), "freetype", .{});
lib.installHeader(freetype_src.path("include/ft2build.h"), "ft2build.h");
b.installArtifact(lib);
const freetype = b.addModule("freetype", .{
.root_source_file = b.path("src/freetype.zig"),
.imports = &.{
},
});
freetype.linkLibrary(lib);
}
// const sources = [_][]const u8{
// "src/autofit/autofit.c",
// "src/base/ftbase.c",
// "src/base/ftsystem.c",
// "src/base/ftdebug.c",
// "src/base/ftbbox.c",
// "src/base/ftbdf.c",
// "src/base/ftbitmap.c",
// "src/base/ftcid.c",
// "src/base/ftfstype.c",
// "src/base/ftgasp.c",
// "src/base/ftglyph.c",
// "src/base/ftgxval.c",
// "src/base/ftinit.c",
// "src/base/ftmm.c",
// "src/base/ftotval.c",
// "src/base/ftpatent.c",
// "src/base/ftpfr.c",
// "src/base/ftstroke.c",
// "src/base/ftsynth.c",
// "src/base/fttype1.c",
// "src/base/ftwinfnt.c",
// "src/bdf/bdf.c",
// "src/bzip2/ftbzip2.c",
// "src/cache/ftcache.c",
// "src/cff/cff.c",
// "src/cid/type1cid.c",
// "src/gzip/ftgzip.c",
// "src/lzw/ftlzw.c",
// "src/pcf/pcf.c",
// "src/pfr/pfr.c",
// "src/psaux/psaux.c",
// "src/pshinter/pshinter.c",
// "src/psnames/psnames.c",
// "src/raster/raster.c",
// "src/sdf/sdf.c",
// "src/sfnt/sfnt.c",
// "src/smooth/smooth.c",
// "src/svg/svg.c",
// "src/truetype/truetype.c",
// "src/type1/type1.c",
// "src/type42/type42.c",
// "src/winfonts/winfnt.c",
// };
+19
View File
@@ -0,0 +1,19 @@
.{
.name = .freetype,
.fingerprint = 0xac2059b69e282536,
.version = "0.1.0",
.minimum_zig_version = "0.15.2",
.paths = .{
"build.zig",
"build.zig.zon",
"libs",
"src",
"README.md",
},
.dependencies = .{
.freetype_src = .{
.url = "https://github.com/freetype/freetype/archive/refs/heads/master.tar.gz",
.hash = "N-V-__8AAGJyqgCBGp-ibrZFNycPitwyNbU5U83UzSNGyJnT",
},
},
}
File renamed without changes.
File diff suppressed because it is too large. Load diff
+121
View File
@@ -0,0 +1,121 @@
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const options = .{
.enable_tracy = b.option(
bool,
"enable_tracy",
"Enable Tracy profile markers",
) orelse false,
.enable_fibers = b.option(
bool,
"enable_fibers",
"Enable Tracy fiber support",
) orelse false,
.on_demand = b.option(
bool,
"on_demand",
"Build tracy with TRACY_ON_DEMAND",
) orelse false,
.callstack = b.option(
u32,
"callstack",
"If > 0, Builds tracy with TRACY_USE_CALLSTACK and sets TRACY_CALLSTACK to the depth provided.",
) orelse 0,
.shared = b.option(
bool,
"shared",
"Build as shared library",
) orelse false,
};
const options_step = b.addOptions();
inline for (std.meta.fields(@TypeOf(options))) |field| {
options_step.addOption(field.type, field.name, @field(options, field.name));
}
const options_module = options_step.createModule();
const tracy_src = b.dependency("tracy_src", .{ .target = target, .optimize = optimize });
const translate_c = b.addTranslateC(.{
.root_source_file = tracy_src.path("public/tracy/TracyC.h"),
.target = target,
.optimize = optimize,
.link_libc = true,
});
translate_c.addIncludePath(tracy_src.path("public/tracy"));
translate_c.defineCMacro("TRACY_ENABLE", "");
translate_c.defineCMacro("TRACY_IMPORTS", "");
if (options.callstack > 0) {
translate_c.defineCMacro("TRACY_USE_CALLSTACK", "");
var callstack_buffer: [64]u8 = undefined;
const callstack_str_len = std.fmt.printInt(&callstack_buffer, @as(u32, options.callstack), 10, .lower, .{});
translate_c.defineCMacro("TRACY_CALLSTACK", callstack_buffer[0..callstack_str_len]);
}
const tracy_lib = b.addLibrary(.{
.name = "tracy",
.linkage = if (options.shared) .dynamic else .static,
.root_module = b.createModule(.{
.target = target,
.optimize = optimize,
}),
});
if (options.shared) tracy_lib.root_module.addCMacro("TRACY_EXPORTS", "");
if (target.result.os.tag == .windows) tracy_lib.root_module.addCMacro("_WIN32_WINNT", "0x0601");
if (options.enable_tracy) tracy_lib.root_module.addCMacro("TRACY_ENABLE", "");
if (options.enable_fibers) tracy_lib.root_module.addCMacro("TRACY_FIBERS", "");
if (options.on_demand) tracy_lib.root_module.addCMacro("TRACY_ON_DEMAND", "");
tracy_lib.root_module.addIncludePath(tracy_src.path("public"));
tracy_lib.root_module.addIncludePath(tracy_src.path("public/tracy"));
tracy_lib.root_module.addIncludePath(tracy_src.path("public/common"));
tracy_lib.root_module.addIncludePath(tracy_src.path("public/client"));
tracy_lib.root_module.addCSourceFile(.{
.file = tracy_src.path("public/TracyClient.cpp"),
.flags = &.{
"-fno-sanitize=undefined",
},
});
tracy_lib.root_module.link_libc = true;
if (target.result.abi != .msvc) {
tracy_lib.root_module.link_libcpp = true;
} else {
tracy_lib.root_module.addCMacro("fileno", "_fileno");
}
// switch (target.result.os.tag) {
// .windows => {
// tracy_lib.root_module.linkSystemLibrary("ws2_32", .{});
// tracy_lib.root_module.linkSystemLibrary("dbghelp", .{});
// tracy_lib.root_module.linkSystemLibrary("secur32", .{}); // Provides GetUserNameExA
// tracy_lib.root_module.linkSystemLibrary("user32", .{}); // Often needed for other system calls
// tracy_lib.root_module.linkSystemLibrary("advapi32", .{});
// },
// // .macos => {
// // if (b.lazyDependency("system_sdk", .{})) |system_sdk| {
// // tracy_lib.root_module.addFrameworkPath(system_sdk.path("System/Library/Frameworks"));
// // }
// // },
// else => {},
// }
b.installArtifact(tracy_lib);
const tracy = b.addModule("tracy", .{
.root_source_file = b.path("src/tracy.zig"),
.imports = &.{
.{ .name = "tracy_options", .module = options_module },
},
});
tracy.addImport("c", translate_c.createModule());
tracy.linkLibrary(tracy_lib);
}
+19
View File
@@ -0,0 +1,19 @@
.{
.name = .tracy,
.fingerprint = 0x255a89ee2e5fcfa8,
.version = "0.1.0",
.minimum_zig_version = "0.15.2",
.paths = .{
"build.zig",
"build.zig.zon",
"libs",
"src",
"README.md",
},
.dependencies = .{
.tracy_src = .{
.url = "https://github.com/wolfpld/tracy/archive/8f0c83dbf90faa982624e005ce76ff0fd5c77153.zip",
.hash = "N-V-__8AAAF7OgG5ck73SkEmLbQPExC4jddnsDCAMtBAIBXy",
},
},
}
+395
View File
@@ -0,0 +1,395 @@
const std = @import("std");
const Src = std.builtin.SourceLocation;
const c = @import("c");
const has_callstack_support = @hasDecl(c, "TRACY_HAS_CALLSTACK") and @hasDecl(c, "TRACY_CALLSTACK");
const callstack_depth: c_int = if (has_callstack_support) c.TRACY_CALLSTACK else 0;
const debug_verify_stack_order = false;
threadlocal var stack_depth: if (debug_verify_stack_order) usize else u0 = 0;
pub const ZoneCtx = struct {
_zone: c.___tracy_c_zone_context,
_token: if (debug_verify_stack_order) usize else void,
pub inline fn Text(self: ZoneCtx, text: []const u8) void {
if (debug_verify_stack_order) {
if (stack_depth != self._token) {
std.debug.panic(
"Error: expected Value() at stack depth {} but was {}\n",
.{ self._token, stack_depth },
);
}
}
c.___tracy_emit_zone_text(self._zone, text.ptr, text.len);
}
pub inline fn Name(self: ZoneCtx, name: []const u8) void {
if (debug_verify_stack_order) {
if (stack_depth != self._token) {
std.debug.panic(
"Error: expected Value() at stack depth {} but was {}\n",
.{ self._token, stack_depth },
);
}
}
c.___tracy_emit_zone_name(self._zone, name.ptr, name.len);
}
pub inline fn Value(self: ZoneCtx, val: u64) void {
if (debug_verify_stack_order) {
if (stack_depth != self._token) {
std.debug.panic(
"Error: expected Value() at stack depth {} but was {}\n",
.{ self._token, stack_depth },
);
}
}
c.___tracy_emit_zone_value(self._zone, val);
}
pub inline fn End(self: ZoneCtx) void {
if (debug_verify_stack_order) {
if (stack_depth != self._token) {
std.debug.panic(
"Error: expected End() at stack depth {} but was {}\n",
.{ self._token, stack_depth },
);
}
stack_depth -= 1;
}
c.___tracy_emit_zone_end(self._zone);
}
};
inline fn initZone(comptime src: Src, name: ?[*:0]const u8, color: u32, depth: c_int) ZoneCtx {
// Tracy uses pointer identity to identify contexts.
// The `src` parameter being comptime ensures that
// each zone gets its own unique global location for this
// struct.
const static = struct {
var loc: c.___tracy_source_location_data = undefined;
// Ensure that a unique struct type is generated for each unique `src`. See
// https://github.com/ziglang/zig/issues/18816
comptime {
// https://github.com/ziglang/zig/issues/19274
_ = @sizeOf(@TypeOf(src));
}
};
static.loc = .{
.name = name,
.function = src.fn_name.ptr,
.file = src.file.ptr,
.line = src.line,
.color = color,
};
const zone = if (has_callstack_support)
c.___tracy_emit_zone_begin_callstack(&static.loc, depth, 1)
else
c.___tracy_emit_zone_begin(&static.loc, 1);
if (debug_verify_stack_order) {
stack_depth += 1;
return ZoneCtx{ ._zone = zone, ._token = stack_depth };
} else {
return ZoneCtx{ ._zone = zone, ._token = {} };
}
}
pub inline fn SetThreadName(name: [*:0]const u8) void {
c.___tracy_set_thread_name(name);
}
pub inline fn Zone(comptime src: Src) ZoneCtx {
return initZone(src, null, 0, callstack_depth);
}
pub inline fn ZoneN(comptime src: Src, name: [*:0]const u8) ZoneCtx {
return initZone(src, name, 0, callstack_depth);
}
pub inline fn ZoneC(comptime src: Src, color: u32) ZoneCtx {
return initZone(src, null, color, callstack_depth);
}
pub inline fn ZoneNC(comptime src: Src, name: [*:0]const u8, color: u32) ZoneCtx {
return initZone(src, name, color, callstack_depth);
}
pub inline fn ZoneS(comptime src: Src, depth: i32) ZoneCtx {
return initZone(src, null, 0, depth);
}
pub inline fn ZoneNS(comptime src: Src, name: [*:0]const u8, depth: i32) ZoneCtx {
return initZone(src, name, 0, depth);
}
pub inline fn ZoneCS(comptime src: Src, color: u32, depth: i32) ZoneCtx {
return initZone(src, null, color, depth);
}
pub inline fn ZoneNCS(comptime src: Src, name: [*:0]const u8, color: u32, depth: i32) ZoneCtx {
return initZone(src, name, color, depth);
}
pub inline fn Alloc(ptr: ?*const anyopaque, size: usize) void {
if (has_callstack_support) {
c.___tracy_emit_memory_alloc_callstack(ptr, size, callstack_depth, 0);
} else {
c.___tracy_emit_memory_alloc(ptr, size, 0);
}
}
pub inline fn Free(ptr: ?*const anyopaque) void {
if (has_callstack_support) {
c.___tracy_emit_memory_free_callstack(ptr, callstack_depth, 0);
} else {
c.___tracy_emit_memory_free(ptr, 0);
}
}
pub inline fn SecureAlloc(ptr: ?*const anyopaque, size: usize) void {
if (has_callstack_support) {
c.___tracy_emit_memory_alloc_callstack(ptr, size, callstack_depth, 1);
} else {
c.___tracy_emit_memory_alloc(ptr, size, 1);
}
}
pub inline fn SecureFree(ptr: ?*const anyopaque) void {
if (has_callstack_support) {
c.___tracy_emit_memory_free_callstack(ptr, callstack_depth, 1);
} else {
c.___tracy_emit_memory_free(ptr, 1);
}
}
pub inline fn AllocS(ptr: ?*const anyopaque, size: usize, depth: c_int) void {
if (has_callstack_support) {
c.___tracy_emit_memory_alloc_callstack(ptr, size, depth, 0);
} else {
c.___tracy_emit_memory_alloc(ptr, size, 0);
}
}
pub inline fn FreeS(ptr: ?*const anyopaque, depth: c_int) void {
if (has_callstack_support) {
c.___tracy_emit_memory_free_callstack(ptr, depth, 0);
} else {
c.___tracy_emit_memory_free(ptr, 0);
}
}
pub inline fn SecureAllocS(ptr: ?*const anyopaque, size: usize, depth: c_int) void {
if (has_callstack_support) {
c.___tracy_emit_memory_alloc_callstack(ptr, size, depth, 1);
} else {
c.___tracy_emit_memory_alloc(ptr, size, 1);
}
}
pub inline fn SecureFreeS(ptr: ?*const anyopaque, depth: c_int) void {
if (has_callstack_support) {
c.___tracy_emit_memory_free_callstack(ptr, depth, 1);
} else {
c.___tracy_emit_memory_free(ptr, 1);
}
}
pub inline fn AllocN(ptr: ?*const anyopaque, size: usize, name: [*:0]const u8) void {
if (has_callstack_support) {
c.___tracy_emit_memory_alloc_callstack_named(ptr, size, callstack_depth, 0, name);
} else {
c.___tracy_emit_memory_alloc_named(ptr, size, 0, name);
}
}
pub inline fn FreeN(ptr: ?*const anyopaque, name: [*:0]const u8) void {
if (has_callstack_support) {
c.___tracy_emit_memory_free_callstack_named(ptr, callstack_depth, 0, name);
} else {
c.___tracy_emit_memory_free_named(ptr, 0, name);
}
}
pub inline fn SecureAllocN(ptr: ?*const anyopaque, size: usize, name: [*:0]const u8) void {
if (has_callstack_support) {
c.___tracy_emit_memory_alloc_callstack_named(ptr, size, callstack_depth, 1, name);
} else {
c.___tracy_emit_memory_alloc_named(ptr, size, 1, name);
}
}
pub inline fn SecureFreeN(ptr: ?*const anyopaque, name: [*:0]const u8) void {
if (has_callstack_support) {
c.___tracy_emit_memory_free_callstack_named(ptr, callstack_depth, 1, name);
} else {
c.___tracy_emit_memory_free_named(ptr, 1, name);
}
}
pub inline fn AllocNS(ptr: ?*const anyopaque, size: usize, depth: c_int, name: [*:0]const u8) void {
if (has_callstack_support) {
c.___tracy_emit_memory_alloc_callstack_named(ptr, size, depth, 0, name);
} else {
c.___tracy_emit_memory_alloc_named(ptr, size, 0, name);
}
}
pub inline fn FreeNS(ptr: ?*const anyopaque, depth: c_int, name: [*:0]const u8) void {
if (has_callstack_support) {
c.___tracy_emit_memory_free_callstack_named(ptr, depth, 0, name);
} else {
c.___tracy_emit_memory_free_named(ptr, 0, name);
}
}
pub inline fn SecureAllocNS(ptr: ?*const anyopaque, size: usize, depth: c_int, name: [*:0]const u8) void {
if (has_callstack_support) {
c.___tracy_emit_memory_alloc_callstack_named(ptr, size, depth, 1, name);
} else {
c.___tracy_emit_memory_alloc_named(ptr, size, 1, name);
}
}
pub inline fn SecureFreeNS(ptr: ?*const anyopaque, depth: c_int, name: [*:0]const u8) void {
if (has_callstack_support) {
c.___tracy_emit_memory_free_callstack_named(ptr, depth, 1, name);
} else {
c.___tracy_emit_memory_free_named(ptr, 1, name);
}
}
pub inline fn Message(text: []const u8) void {
c.___tracy_emit_message(text.ptr, text.len, callstack_depth);
}
pub inline fn MessageL(text: [*:0]const u8, color: u32) void {
c.___tracy_emit_messageL(text, color, callstack_depth);
}
pub inline fn MessageC(text: []const u8, color: u32) void {
c.___tracy_emit_messageC(text.ptr, text.len, color, callstack_depth);
}
pub inline fn MessageLC(text: [*:0]const u8, color: u32) void {
c.___tracy_emit_messageLC(text, color, callstack_depth);
}
pub inline fn MessageS(text: []const u8, depth: c_int) void {
const inner_depth: c_int = if (has_callstack_support) depth else 0;
c.___tracy_emit_message(text.ptr, text.len, inner_depth);
}
pub inline fn MessageLS(text: [*:0]const u8, depth: c_int) void {
const inner_depth: c_int = if (has_callstack_support) depth else 0;
c.___tracy_emit_messageL(text, inner_depth);
}
pub inline fn MessageCS(text: []const u8, color: u32, depth: c_int) void {
const inner_depth: c_int = if (has_callstack_support) depth else 0;
c.___tracy_emit_messageC(text.ptr, text.len, color, inner_depth);
}
pub inline fn MessageLCS(text: [*:0]const u8, color: u32, depth: c_int) void {
const inner_depth: c_int = if (has_callstack_support) depth else 0;
c.___tracy_emit_messageLC(text, color, inner_depth);
}
pub inline fn FrameMark() void {
c.___tracy_emit_frame_mark(null);
}
pub inline fn FrameMarkNamed(name: [*:0]const u8) void {
c.___tracy_emit_frame_mark(name);
}
pub inline fn FrameMarkStart(name: [*:0]const u8) void {
c.___tracy_emit_frame_mark_start(name);
}
pub inline fn FrameMarkEnd(name: [*:0]const u8) void {
c.___tracy_emit_frame_mark_end(name);
}
pub inline fn FrameImage(image: ?*const anyopaque, width: u16, height: u16, offset: u8, flip: c_int) void {
c.___tracy_emit_frame_image(image, width, height, offset, flip);
}
pub inline fn FiberEnter(name: [*:0]const u8) void {
c.___tracy_fiber_enter(name);
}
pub inline fn FiberLeave() void {
c.___tracy_fiber_leave();
}
pub inline fn PlotF(name: [*:0]const u8, val: f64) void {
c.___tracy_emit_plot(name, val);
}
pub inline fn PlotU(name: [*:0]const u8, val: u64) void {
c.___tracy_emit_plot(name, @as(f64, @floatFromInt(val)));
}
pub inline fn PlotI(name: [*:0]const u8, val: i64) void {
c.___tracy_emit_plot(name, @as(f64, @floatFromInt(val)));
}
pub inline fn AppInfo(text: []const u8) void {
c.___tracy_emit_message_appinfo(text.ptr, text.len);
}
pub const TracyAllocator = struct {
child_allocator: std.mem.Allocator,
pub fn init(child_allocator: std.mem.Allocator) TracyAllocator {
return .{
.child_allocator = child_allocator,
};
}
pub fn allocator(self: *TracyAllocator) std.mem.Allocator {
return .{
.ptr = self,
.vtable = &.{
.alloc = alloc,
.resize = resize,
.remap = remap,
.free = free,
},
};
}
fn alloc(
ctx: *anyopaque,
len: usize,
alignment: std.mem.Alignment,
ra: usize,
) ?[*]u8 {
const self: *TracyAllocator = @ptrCast(@alignCast(ctx));
const result = self.child_allocator.rawAlloc(len, alignment, ra);
if (result) |addr| {
Alloc(addr, len);
} else {
var buffer: [128]u8 = undefined;
const msg = std.fmt.bufPrint(&buffer, "alloc failed requesting {d}", .{len}) catch return result;
Message(msg);
}
return result;
}
fn resize(
ctx: *anyopaque,
buf: []u8,
alignment: std.mem.Alignment,
new_len: usize,
ra: usize,
) bool {
const self: *TracyAllocator = @ptrCast(@alignCast(ctx));
const result = self.child_allocator.rawResize(buf, alignment, new_len, ra);
if (result) {
Free(buf.ptr);
Alloc(buf.ptr, new_len);
} else {
var buffer: [128]u8 = undefined;
const msg = std.fmt.bufPrint(&buffer, "resize failed requesting {d} -> {d}", .{ buf.len, new_len }) catch return result;
Message(msg);
}
return result;
}
fn remap(
ctx: *anyopaque,
buf: []u8,
alignment: std.mem.Alignment,
new_len: usize,
ra: usize,
) ?[*]u8 {
const self: *TracyAllocator = @ptrCast(@alignCast(ctx));
const result = self.child_allocator.rawRemap(buf, alignment, new_len, ra);
if (result) |data| {
Free(buf.ptr);
Alloc(data, new_len);
} else {
var buffer: [128]u8 = undefined;
const msg = std.fmt.bufPrint(&buffer, "remap failed requesting {d} -> {d}", .{ buf.len, new_len }) catch return result;
Message(msg);
}
return result;
}
fn free(
ctx: *anyopaque,
buf: []u8,
alignment: std.mem.Alignment,
ra: usize,
) void {
const self: *TracyAllocator = @ptrCast(@alignCast(ctx));
self.child_allocator.rawFree(buf, alignment, ra);
Free(buf.ptr);
}
};
+229
View File
@@ -0,0 +1,229 @@
const std = @import("std");
const Src = std.builtin.SourceLocation;
pub const ZoneCtx = struct {
pub inline fn Text(self: ZoneCtx, text: []const u8) void {
_ = self;
_ = text;
}
pub inline fn Name(self: ZoneCtx, name: []const u8) void {
_ = self;
_ = name;
}
pub inline fn Value(self: ZoneCtx, value: u64) void {
_ = self;
_ = value;
}
pub inline fn End(self: ZoneCtx) void {
_ = self;
}
};
pub inline fn SetThreadName(name: [*:0]const u8) void {
_ = name;
}
pub inline fn Zone(comptime src: Src) ZoneCtx {
_ = src;
return .{};
}
pub inline fn ZoneN(comptime src: Src, name: [*:0]const u8) ZoneCtx {
_ = src;
_ = name;
return .{};
}
pub inline fn ZoneC(comptime src: Src, color: u32) ZoneCtx {
_ = src;
_ = color;
return .{};
}
pub inline fn ZoneNC(comptime src: Src, name: [*:0]const u8, color: u32) ZoneCtx {
_ = src;
_ = name;
_ = color;
return .{};
}
pub inline fn ZoneS(comptime src: Src, depth: i32) ZoneCtx {
_ = src;
_ = depth;
return .{};
}
pub inline fn ZoneNS(comptime src: Src, name: [*:0]const u8, depth: i32) ZoneCtx {
_ = src;
_ = name;
_ = depth;
return .{};
}
pub inline fn ZoneCS(comptime src: Src, color: u32, depth: i32) ZoneCtx {
_ = src;
_ = color;
_ = depth;
return .{};
}
pub inline fn ZoneNCS(comptime src: Src, name: [*:0]const u8, color: u32, depth: i32) ZoneCtx {
_ = src;
_ = name;
_ = color;
_ = depth;
return .{};
}
pub inline fn Alloc(ptr: ?*const anyopaque, size: usize) void {
_ = ptr;
_ = size;
}
pub inline fn Free(ptr: ?*const anyopaque) void {
_ = ptr;
}
pub inline fn SecureAlloc(ptr: ?*const anyopaque, size: usize) void {
_ = ptr;
_ = size;
}
pub inline fn SecureFree(ptr: ?*const anyopaque) void {
_ = ptr;
}
pub inline fn AllocS(ptr: ?*const anyopaque, size: usize, depth: c_int) void {
_ = ptr;
_ = size;
_ = depth;
}
pub inline fn FreeS(ptr: ?*const anyopaque, depth: c_int) void {
_ = ptr;
_ = depth;
}
pub inline fn SecureAllocS(ptr: ?*const anyopaque, size: usize, depth: c_int) void {
_ = ptr;
_ = size;
_ = depth;
}
pub inline fn SecureFreeS(ptr: ?*const anyopaque, depth: c_int) void {
_ = ptr;
_ = depth;
}
pub inline fn AllocN(ptr: ?*const anyopaque, size: usize, name: [*:0]const u8) void {
_ = ptr;
_ = size;
_ = name;
}
pub inline fn FreeN(ptr: ?*const anyopaque, name: [*:0]const u8) void {
_ = ptr;
_ = name;
}
pub inline fn SecureAllocN(ptr: ?*const anyopaque, size: usize, name: [*:0]const u8) void {
_ = ptr;
_ = size;
_ = name;
}
pub inline fn SecureFreeN(ptr: ?*const anyopaque, name: [*:0]const u8) void {
_ = ptr;
_ = name;
}
pub inline fn AllocNS(ptr: ?*const anyopaque, size: usize, depth: c_int, name: [*:0]const u8) void {
_ = ptr;
_ = size;
_ = depth;
_ = name;
}
pub inline fn FreeNS(ptr: ?*const anyopaque, depth: c_int, name: [*:0]const u8) void {
_ = ptr;
_ = depth;
_ = name;
}
pub inline fn SecureAllocNS(ptr: ?*const anyopaque, size: usize, depth: c_int, name: [*:0]const u8) void {
_ = ptr;
_ = size;
_ = depth;
_ = name;
}
pub inline fn SecureFreeNS(ptr: ?*const anyopaque, depth: c_int, name: [*:0]const u8) void {
_ = ptr;
_ = depth;
_ = name;
}
pub inline fn Message(text: []const u8) void {
_ = text;
}
pub inline fn MessageL(text: [*:0]const u8) void {
_ = text;
}
pub inline fn MessageC(text: []const u8, color: u32) void {
_ = text;
_ = color;
}
pub inline fn MessageLC(text: [*:0]const u8, color: u32) void {
_ = text;
_ = color;
}
pub inline fn MessageS(text: []const u8, depth: c_int) void {
_ = text;
_ = depth;
}
pub inline fn MessageLS(text: [*:0]const u8, depth: c_int) void {
_ = text;
_ = depth;
}
pub inline fn MessageCS(text: []const u8, color: u32, depth: c_int) void {
_ = text;
_ = color;
_ = depth;
}
pub inline fn MessageLCS(text: [*:0]const u8, color: u32, depth: c_int) void {
_ = text;
_ = color;
_ = depth;
}
pub inline fn FrameMark() void {}
pub inline fn FrameMarkNamed(name: [*:0]const u8) void {
_ = name;
}
pub inline fn FrameMarkStart(name: [*:0]const u8) void {
_ = name;
}
pub inline fn FrameMarkEnd(name: [*:0]const u8) void {
_ = name;
}
pub inline fn FrameImage(image: ?*const anyopaque, width: u16, height: u16, offset: u8, flip: c_int) void {
_ = image;
_ = width;
_ = height;
_ = offset;
_ = flip;
}
pub inline fn FiberEnter(name: [*:0]const u8) void {
_ = name;
}
pub inline fn FiberLeave() void {}
pub inline fn PlotF(name: [*:0]const u8, val: f64) void {
_ = name;
_ = val;
}
pub inline fn PlotU(name: [*:0]const u8, val: u64) void {
_ = name;
_ = val;
}
pub inline fn PlotI(name: [*:0]const u8, val: i64) void {
_ = name;
_ = val;
}
pub inline fn AppInfo(text: []const u8) void {
_ = text;
}
pub const TracyAllocator = struct {
child_allocator: std.mem.Allocator,
pub fn init(child_allocator: std.mem.Allocator) TracyAllocator {
return .{
.child_allocator = child_allocator,
};
}
pub fn allocator(self: *TracyAllocator) std.mem.Allocator {
return self.child_allocator;
}
};
+84
View File
@@ -0,0 +1,84 @@
const std = @import("std");
const builtin = @import("builtin");
// check for a decl named tracy_enabled in root or build_options
pub const enabled = blk: {
var build_enable: ?bool = null;
if (!builtin.is_test) {
// Don't try to include build_options in tests.
// Otherwise `zig test` doesn't work.
const options = @import("tracy_options");
if (@hasDecl(options, "enable_tracy")) {
build_enable = options.enable_tracy;
}
}
break :blk build_enable orelse false;
};
const stub = @import("stub.zig");
const impl = @import("impl.zig");
pub const ZoneCtx = if (enabled) impl.ZoneCtx else stub.ZoneCtx;
pub const SetThreadName = if (enabled) impl.SetThreadName else stub.SetThreadName;
pub const Zone = if (enabled) impl.Zone else stub.Zone;
pub const ZoneN = if (enabled) impl.ZoneN else stub.ZoneN;
pub const ZoneC = if (enabled) impl.ZoneC else stub.ZoneC;
pub const ZoneNC = if (enabled) impl.ZoneNC else stub.ZoneNC;
pub const ZoneS = if (enabled) impl.ZoneS else stub.ZoneS;
pub const ZoneNS = if (enabled) impl.ZoneNS else stub.ZoneNS;
pub const ZoneCS = if (enabled) impl.ZoneCS else stub.ZoneCS;
pub const ZoneNCS = if (enabled) impl.ZoneNCS else stub.ZoneNCS;
pub const Alloc = if (enabled) impl.Alloc else stub.Alloc;
pub const Free = if (enabled) impl.Free else stub.Free;
pub const SecureAlloc = if (enabled) impl.SecureAlloc else stub.SecureAlloc;
pub const SecureFree = if (enabled) impl.SecureFree else stub.SecureFree;
pub const AllocS = if (enabled) impl.AllocS else stub.AllocS;
pub const FreeS = if (enabled) impl.FreeS else stub.FreeS;
pub const SecureAllocS = if (enabled) impl.SecureAllocS else stub.SecureAllocS;
pub const SecureFreeS = if (enabled) impl.SecureFreeS else stub.SecureFreeS;
pub const AllocN = if (enabled) impl.AllocN else stub.AllocN;
pub const FreeN = if (enabled) impl.FreeN else stub.FreeN;
pub const SecureAllocN = if (enabled) impl.SecureAllocN else stub.SecureAllocN;
pub const SecureFreeN = if (enabled) impl.SecureFreeN else stub.SecureFreeN;
pub const AllocNS = if (enabled) impl.AllocNS else stub.AllocNS;
pub const FreeNS = if (enabled) impl.FreeNS else stub.FreeNS;
pub const SecureAllocNS = if (enabled) impl.SecureAllocNS else stub.SecureAllocNS;
pub const SecureFreeNS = if (enabled) impl.SecureFreeNS else stub.SecureFreeNS;
pub const Message = if (enabled) impl.Message else stub.Message;
pub const MessageL = if (enabled) impl.MessageL else stub.MessageL;
pub const MessageC = if (enabled) impl.MessageC else stub.MessageC;
pub const MessageLC = if (enabled) impl.MessageLC else stub.MessageLC;
pub const MessageS = if (enabled) impl.MessageS else stub.MessageS;
pub const MessageLS = if (enabled) impl.MessageLS else stub.MessageLS;
pub const MessageCS = if (enabled) impl.MessageCS else stub.MessageCS;
pub const MessageLCS = if (enabled) impl.MessageLCS else stub.MessageLCS;
pub const FrameMark = if (enabled) impl.FrameMark else stub.FrameMark;
pub const FrameMarkNamed = if (enabled) impl.FrameMarkNamed else stub.FrameMarkNamed;
pub const FrameMarkStart = if (enabled) impl.FrameMarkStart else stub.FrameMarkStart;
pub const FrameMarkEnd = if (enabled) impl.FrameMarkEnd else stub.FrameMarkEnd;
pub const FrameImage = if (enabled) impl.FrameImage else stub.FrameImage;
pub const FiberEnter = if (enabled) impl.FiberEnter else stub.FiberEnter;
pub const FiberLeave = if (enabled) impl.FiberLeave else stub.FiberLeave;
pub const PlotF = if (enabled) impl.PlotF else stub.PlotF;
pub const PlotU = if (enabled) impl.PlotU else stub.PlotU;
pub const PlotI = if (enabled) impl.PlotI else stub.PlotI;
pub const AppInfo = if (enabled) impl.AppInfo else stub.AppInfo;
pub const TracyAllocator = if (enabled) impl.TracyAllocator else stub.TracyAllocator;
test {
std.testing.refAllDeclsRecursive(@This());
}