Skip to content

Commit

Permalink
Improve all namespaces and structs.
Browse files Browse the repository at this point in the history
- Base Server formatting changed.
- Base Client received more implementations.
- Add the core namespace to the main namespace.
- Implement more of the Packet struct.
- Utilize Options more in the main file and start implementing the client, cluster, and master implementations.
- Add the spawning namespace under the core namespace.
- Add the Spawnee struct.
- Add the Player struct and extend Spawnee.
- Further implement the proper Client struct.
  • Loading branch information
Makosai committed Aug 18, 2024
1 parent 75de26e commit 2ec9f3c
Show file tree
Hide file tree
Showing 10 changed files with 209 additions and 63 deletions.
49 changes: 43 additions & 6 deletions src/Clients/Client.zig
Original file line number Diff line number Diff line change
@@ -1,20 +1,57 @@
//! A standard client that connects to a server.

const std = @import("std");
const sustenet = @import("root").sustenet;
const network = @import("network");

const AutoHashMap = std.AutoHashMap;
const BaseEvent = sustenet.events.BaseEvent;
const BaseClient = @import("root").sustenet.transport.BaseClient;

const Client = @This();

pub const ConnectionType = enum { MasterServer, ClusterServer, None };
pub const Connection = struct { ip: network.Address.IPv4, port: u16 };

pub const packetHandler = *const fn (from_client: i32, packet: i32) void;
var packetHandlers: ?AutoHashMap(i32, packetHandler) = null;

active_connection: ConnectionType,
master_connection: ?Connection,
cluster_connection: ?Connection,

on_initialized: BaseEvent, // Init these early
on_cluster_server_list: BaseEvent,

super: BaseClient,

const Client = @This();
pub fn new(_: ?[]const u8, _: ?u16) Client {
var client = Client{
.super = BaseClient.new(-1),

pub fn new(port: u16) Client {
const client = Client{
.super = BaseClient.new(port),
.active_connection = ConnectionType.None,
.master_connection = null,
.cluster_connection = null,
.on_initialized = BaseEvent{},
.on_cluster_server_list = BaseEvent{},
};

// client.super.on_connected = BaseEvent.init();
// client.super.on_received = BaseEvent.init();
// client.super.on_initialized = BaseEvent.init();

client.initializeClientData();
return client;
}

pub fn connect(self: *Client) !void {
try self.super.connect();
pub fn connect(_: *Client) !void {
// try self.super.connect();
}

pub fn initializeClientData(_: *Client) void {}

//#region Memory Functions
pub fn deinit(self: *Client) void {
self.super.deinit();
}
//#endregion
16 changes: 16 additions & 0 deletions src/Core/Spawning/Player.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const sustenet = @import("root").sustenet;
const Vector3 = sustenet.zig_numerics.vector.Vec3(f32);

const Spawnee = sustenet.core.spawning.Spawnee;
const Player = @This();

super: Spawnee,
username: []u8,

pub fn new(id: u32, username: []const u8, spawn_position: Vector3) Player {
const player = Player{
.super = Spawnee.new(id, spawn_position),
.username = username,
};
return player;
}
18 changes: 18 additions & 0 deletions src/Core/Spawning/Spawnee.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const sustenet = @import("root").sustenet;
const zig_numerics = sustenet.zig_numerics;

const Vector3 = zig_numerics.vector.Vec3(f32);
const Quaternion = zig_numerics.quaternion.Quaternion(f32);
const Spawnee = @This();

id: u32,
position: Vector3,
rotation: Quaternion,

pub fn new(id: u32, position: Vector3, rotation: Quaternion) Spawnee {
return Spawnee{
.id = id,
.position = position,
.rotation = rotation,
};
}
4 changes: 4 additions & 0 deletions src/Core/Spawning/spawning.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
//! Spawning namespace

pub const Player = @import("Player.zig");
pub const Spawnee = @import("Spawnee.zig");
3 changes: 3 additions & 0 deletions src/Core/core.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
//! Core namespace

pub const spawning = @import("Spawning/spawning.zig");
7 changes: 5 additions & 2 deletions src/Network/Packet.zig
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ const ArrayList = std.ArrayList;
const Packet = @This();

buffer: ArrayList(u8),
readable_buffer: []u8,
readable_buffer: ?[]u8,
read_pos: i32 = 0,

/// Creates an empty packet without an ID.
pub fn new(allocator: std.mem.Allocator) Packet {
const packet = Packet{};
const packet = Packet{
.buffer = ArrayList(u8).init(allocator),
.readable_buffer = null,
};
packet.init(allocator);
return Packet{};
}
Expand Down
90 changes: 61 additions & 29 deletions src/Transport/BaseClient.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,80 @@
//! and receiving data. Also handles the core for connecting to servers.

const std = @import("std");
const network = @import("network");
const sustenet = @import("root").sustenet;

const net = std.net;
const print = std.debug.print;
const testing = std.testing; // Add import for testing package
const testing = std.testing;
const Packet = sustenet.network.Packet;
const BaseEvent = sustenet.events.BaseEvent;
const Player = sustenet.core.spawning.Player;
const BaseClient = @This();

const bufferSize = 4028;
pub const buffer_size = 4096;

id: u32 = 0,
port: u16 = 4337,
stream: ?net.Stream,
id: i32 = -1,
name: ?[]const u8 = null,

pub fn new(port: u16) BaseClient {
return BaseClient{ .id = 0, .port = port, .stream = null };
}
tcp: TcpHandler,
udp: UdpHandler,

pub fn connect(self: *BaseClient) !void {
self.id = 1;
received_data: ?Packet = null,

_ = try net.Address.parseIp4("127.0.0.1", self.port);
on_connected: BaseEvent, // Init these early
on_disconnected: BaseEvent,
on_received: BaseEvent,

// Connect to server.
// self.stream = net.tcpConnectToAddress(server) catch |err| {
// print("Unable to connect to Sustenet Server.\n", .{});
// return err;
// };
// defer self.stream.?.close();
// print("Connecting to {}\n", .{server});
player: ?Player = null,

// try self.send("hello ziggy!");
}
pub fn new(id: i32) BaseClient {
return BaseClient{
.id = id,

pub fn send(self: *BaseClient, data: []const u8) !void {
if (self.stream == null) return;
.tcp = TcpHandler{
.socket = null,
.buffer = null,
},
.udp = UdpHandler{
.socket = null,
.buffer = null,
},

var writer = self.stream.?.writer();
const size = try writer.write(data);
print("Sending '{s}' to peer, total written: {d} bytes\n", .{ data, size });
.on_connected = BaseEvent{},
.on_disconnected = BaseEvent{},
.on_received = BaseEvent{},
};
}

const TcpHandler = struct {
socket: ?network.Socket,
buffer: ?[buffer_size]u8,

fn deinit(self: *TcpHandler) void {
if (self.socket != null) {
self.socket.?.close();
}
}
};

const UdpHandler = struct {
socket: ?network.Socket,
buffer: ?[buffer_size]u8,

fn deinit(self: *UdpHandler) void {
if (self.socket != null) {
self.socket.?.close();
}
}
};

//#region Memory Functions
pub fn deinit(self: *BaseClient) void {
if (self.stream != null) {
self.stream.?.close();
self.stream = null;
self.tcp.deinit();
self.udp.deinit();

if (self.received_data != null) {
self.received_data.?.deinit();
}
}
//#endregion
7 changes: 3 additions & 4 deletions src/Transport/BaseServer.zig
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ const BaseServer = @This();

pub const ServerType = enum { MasterServer, ClusterServer };

pub const packetHandler = *const fn (from_client: i32, packet: i32) void;
var packetHandlers: ?AutoHashMap(i32, packetHandler) = null;

// UDP equivalent is in BaseClient.UdpHandler.socket
// tcp_listener: i32, // Just set as i32 to shutup the compiler

Expand All @@ -24,10 +27,6 @@ port: u16,
clients: AutoHashMap(i32, BaseClient),
released_ids: std.ArrayList(i32),

pub const packetHandler = *const fn (from_client: i32, packet: i32) void;

var packetHandlers: ?AutoHashMap(i32, packetHandler) = null;

// onConnection: BaseEvent(comptime i32),
// onDisconnection: BaseEvent(comptime i32),
// onReceived: BaseEvent(comptime []u8),
Expand Down
77 changes: 55 additions & 22 deletions src/main.zig
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
const std = @import("std");
const builtin = @import("builtin");
const Options = @import("Options.zig");
pub const sustenet = @import("sustenet.zig");

const eql = std.mem.eql;
const print = std.debug.print;
const ArrayList = std.ArrayList;
const transport = sustenet.transport;
const clients = sustenet.clients;

const Constants = sustenet.utils.Constants;
const BaseServer = transport.BaseServer;

pub var client_list: std.ArrayList(clients.Client) = undefined;

var is_running = false;

// pub var cluster = undefined;
// pub var clients: []Clients.Client;
// pub var cluster: World = undefined;
// pub var master = undefined;

fn entrypoint() !void {
pub fn main() !void {
// Get allocator
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
Expand All @@ -27,43 +32,71 @@ fn entrypoint() !void {
_ = argsIterator.next(); // Skip the first argument, which is the program name

if (argsIterator.next()) |arg| {
if (std.mem.eql(u8, arg, "server")) { // ----- Server mode
var master_server = try BaseServer.new(allocator, BaseServer.ServerType.MasterServer, 10, 4337);
defer master_server.deinit(allocator);

try master_server.start();
} else if (std.mem.eql(u8, arg, "client")) { // ----- Client mode
if (eql(u8, arg, "help")) {
Options.showHelp();
return;
} else if (eql(u8, arg, "version")) {
print("Sustenet v{s}\n", .{sustenet.utils.Constants.VERSION});
return;
} else if (eql(u8, arg, "client") or eql(u8, arg, "c")) {
// Only to be used for debugging.
client_list = ArrayList(clients.Client).init(allocator);
defer client_list.deinit();
defer {
// for (client_list.items()) |client| {
// client.deinit();
// }
client_list.deinit();
}

var max_clients: u32 = 1; // Default value

var max_clients: u32 = 10; // Default value
// Check if the user provided a number of clients to connect
print("{s}Starting client mode...{s} ", .{
Constants.TERMINAL_ORANGE,
Constants.TERMINAL_DEFAULT,
});
if (argsIterator.next()) |num_arg| {
max_clients = std.fmt.parseInt(u32, num_arg, 10) catch 10;

// Print the number of clients
print("Number of clients: {}\n", .{max_clients});
print("{s}Number of clients: {d}{s}\n", .{
Constants.TERMINAL_BLUE,
max_clients,
Constants.TERMINAL_DEFAULT,
});
} else {
print("{s}No number of clients provided. Defaulting to 1.{s}\n", .{
Constants.TERMINAL_BLUE,
Constants.TERMINAL_DEFAULT,
});
}

// Connect the clients
for (0..max_clients) |_| {
var client = clients.Client.new(4337);
var client = clients.Client.new(null, null);
defer client.deinit();
try client_list.append(client);

try client.connect();
}

print("Finished connecting {} clients to the server.\n", .{max_clients});
print("{s}Finished connecting {d} clients to the server.{s}\n", .{
Constants.TERMINAL_GREEN,
max_clients,
Constants.TERMINAL_DEFAULT,
});
return;
} else if (eql(u8, arg, "cluster") or eql(u8, arg, "cs")) {
return;
} else if (eql(u8, arg, "master") or eql(u8, arg, "ms")) {
return;
} else {
print("Unknown mode provided. Aborting.\n", .{});
print("Add 'help' to this command to get a list of options.\n", .{});
return;
}
} else {
print("No mode specified. Run `zig build run -- <client|server> [max clients|max connections]`.\n", .{});
}
}

pub fn main() !void {
try entrypoint();
}

//#region Tests
test {
std.testing.refAllDecls(@This());
Expand All @@ -76,7 +109,7 @@ test "create server(s) with gp_allocator" {
const n = 1;
const fmn = try sustenet.utils.Utilities.formatWithCommas(n);

std.debug.print("Creating {s} servers...\n", .{fmn});
print("Creating {s} servers...\n", .{fmn});

for (0..n) |_| {
var server = try BaseServer.new(allocator, BaseServer.ServerType.MasterServer, 10, 4337);
Expand All @@ -85,6 +118,6 @@ test "create server(s) with gp_allocator" {
try server.start();
}

std.debug.print("Finished creating {s} servers.\n", .{fmn});
print("Finished creating {s} servers.\n", .{fmn});
}
//#endregion
1 change: 1 addition & 0 deletions src/sustenet.zig
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub const clients = @import("Clients/clients.zig");
pub const core = @import("Core/core.zig");
pub const events = @import("Events/events.zig");
pub const network = @import("Network/network.zig");
pub const transport = @import("Transport/transport.zig");
Expand Down

0 comments on commit 2ec9f3c

Please sign in to comment.