709 lines
26 KiB
Zig
709 lines
26 KiB
Zig
pub export fn startup_module(p_allocator: *anyopaque, p_a: ?*anyopaque) bool {
|
|
const allocator = core.modulePreamble(p_allocator, p_a) catch return false;
|
|
_ = allocator;
|
|
imgui.setupFromModule();
|
|
platform.setupFromModule();
|
|
sys.setupFromModule();
|
|
rend.setupFromModule();
|
|
backlog.physics.setupFromModule();
|
|
// backlog.net.setupFromModule();
|
|
// TODO backlog.setupFromModule
|
|
|
|
core.engine_logs("creating externgame");
|
|
start_module(core.startup_getArgs(p_a.?)) catch return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
pub export fn add(a: i32, b: i32) i32 {
|
|
return a + b;
|
|
}
|
|
|
|
pub export fn subtract(a: i32, b: i32) i32 {
|
|
return a + b;
|
|
}
|
|
|
|
var gAllocator: std.mem.Allocator = undefined;
|
|
|
|
pub fn start_module(args: core.ModuleLoaderArgs) !void {
|
|
core.PatchOrCreateObject(extras.GameList, .{});
|
|
core.PatchOrCreateObject(extras.ModuleLoader, .{});
|
|
core.PatchOrCreateObject(extras.ObjectSystemSpawner, .{});
|
|
core.PatchOrCreateObject(net.EnetTransport, .{});
|
|
core.PatchOrCreateObject(ExternGameObject, .{});
|
|
core.PatchOrCreateObject(imgui.utils.ConsoleWindow, .{});
|
|
core.PatchOrCreateObject(@import("fpgame/fpgame.zig"), .{});
|
|
|
|
_ = args;
|
|
core.logDisplay("externGame", "accessing old object at {x} same object? {d}", .{ @intFromPtr(core.EngineObject(ExternGameObject).get()), @sizeOf(ExternGameObject) });
|
|
}
|
|
|
|
pub const BoxObject = struct {
|
|
playing: bool = false,
|
|
|
|
pub fn create(allocator: std.mem.Allocator, entity: core.Entity, params: core.SpawnParameters) !*@This() {
|
|
const position = params.posRot.position;
|
|
|
|
const box2 = entity;
|
|
const scene = box2.addComponent(core.Scene).?;
|
|
|
|
const mesh = box2.addComponent(rend.MeshComponent).?;
|
|
mesh.setMesh("m_crate");
|
|
mesh.setTexture("t_crate");
|
|
|
|
scene.setPosition(position);
|
|
scene.setScaleV(params.posRot.scale);
|
|
scene.setMobility(.moveable);
|
|
|
|
const collider = box2.addComponent(physics.PhysicsCollider).?;
|
|
try collider.setupByShapeName(core.MakeName("ph_small_box"), .{
|
|
.motion_type = .dynamic,
|
|
.object_layer = physics.ObjectLayers.moving,
|
|
.friction = 0.8,
|
|
.mass_properties_override = .{ .mass = 12 },
|
|
.override_mass_properties = .calc_inertia,
|
|
});
|
|
|
|
return try allocator.create(@This());
|
|
}
|
|
|
|
pub fn createSmoky(allocator: std.mem.Allocator, entity: core.Entity, params: core.SpawnParameters) !*@This() {
|
|
const rv = try create(allocator, entity, params);
|
|
|
|
const particle = entity.addComponent(rend.ParticleEmitter).?;
|
|
particle.start();
|
|
particle.gravity = .{ .y = 1.0 };
|
|
particle.particleVelocity = .{ .min = 0.6, .max = 1.2 };
|
|
particle.particleLife = .{ .min = 5, .max = 6 };
|
|
var name = core.MakeName("t_pixelSmoke");
|
|
particle.texture = rend.getTexture(&name).?;
|
|
|
|
return rv;
|
|
}
|
|
|
|
pub fn destroy(self: *@This(), alloc: std.mem.Allocator) void {
|
|
alloc.destroy(self);
|
|
}
|
|
};
|
|
|
|
pub const ExternGameArgs = struct {
|
|
clientTarget: []const u8 = "127.0.0.1",
|
|
clientIndex: u32 = 0,
|
|
asClient: bool = false,
|
|
};
|
|
|
|
pub const ExternGameObject = struct {
|
|
pub var NeonObjectTable = core.EngineObjectVTable.from(@This(), "game.ExternGameObject");
|
|
pub const Slack = core.SlackStruct(@This(), 1024);
|
|
|
|
allocator: std.mem.Allocator = undefined,
|
|
tbMap: ?*bsp.maploader.TBMap = null,
|
|
physicsObjectsWindow: *extras.PhysicsObjectList = undefined,
|
|
fireTraceFilter: physics.IgnoreFixedBodiesFilter = .{},
|
|
particleDebugger: extras.ParticleDebugger.ParticleDebugger = undefined,
|
|
|
|
session: ?*net.Session = null,
|
|
clientLink: ?*net.Link = null,
|
|
launchAsClient: ?[]const u8 = null,
|
|
|
|
recompiling: bool = false,
|
|
firstTick: bool = true,
|
|
|
|
fpcamera: *extras.FpCamera = undefined,
|
|
|
|
fireInput: ?*core.ActionBinding = null,
|
|
altFireInput: ?*core.ActionBinding = null,
|
|
reloadInput: ?*core.ActionBinding = null,
|
|
openSpawner: ?*core.ActionBinding = null,
|
|
reloadMapInput: ?*core.ActionBinding = null,
|
|
|
|
volume: f32 = 100.0,
|
|
volume2: f32 = 100.0,
|
|
|
|
a: core.Vector2f = .{ .x = 1, .y = 4 },
|
|
b: core.Vector2f = .{ .x = 4, .y = 1 },
|
|
|
|
Anormal: core.Vector2f = .{ .x = -1, .y = 3 },
|
|
Bnormal: core.Vector2f = .{ .x = -1, .y = -3 },
|
|
|
|
spawnedEntities: std.ArrayListUnmanaged(core.Entity) = .{},
|
|
|
|
clientIndex: u32 = 0,
|
|
autoAddClients: bool = true,
|
|
clientsToAdd: u32 = 1,
|
|
|
|
displayVectorsTest: bool = false,
|
|
|
|
pub fn beginPlay(p: *anyopaque) void {
|
|
const self = core.cast(*@This(), p);
|
|
ui.context().screenContext.drawDebug = true;
|
|
|
|
self._beginPlay() catch {
|
|
core.engine_errs("unable to beginplay");
|
|
};
|
|
}
|
|
|
|
pub fn _beginPlay(self: *@This()) !void {
|
|
try self.setupInputs();
|
|
|
|
if (self.firstTick) {
|
|
self.loadMap2() catch unreachable;
|
|
self.firstTick = false;
|
|
}
|
|
|
|
// change this into a parallel for
|
|
for (0..300) |i| {
|
|
_ = try core.get(core.GameObjectSystem).spawnObject(BoxObject, "Box", .{
|
|
.posRot = .{
|
|
.position = .{ .x = core.itof32((i % 10)) * 2, .y = 15.0, .z = core.itof32(@divFloor(i, 10) * 2) },
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
pub fn onMapReload(ctx: ?*anyopaque, _: core.ActionEvent) void {
|
|
const self = core.cast(*@This(), ctx.?);
|
|
self.loadMap2() catch {};
|
|
}
|
|
|
|
pub fn setupInputs(self: *@This()) !void {
|
|
if (self.fireInput) |fireInput| {
|
|
fireInput.deactivate();
|
|
}
|
|
if (self.altFireInput) |altFireInput| {
|
|
altFireInput.deactivate();
|
|
}
|
|
|
|
if (self.reloadInput) |input| {
|
|
input.deactivate();
|
|
}
|
|
|
|
if (self.openSpawner) |input| {
|
|
input.deactivate();
|
|
self.openSpawner = null;
|
|
}
|
|
|
|
if (self.reloadMapInput) |input| {
|
|
input.deactivate();
|
|
self.reloadMapInput = null;
|
|
}
|
|
|
|
if (self.reloadMapInput == null) {
|
|
self.reloadMapInput = try core.ActionBinding.create(core.MakeName("input"));
|
|
self.reloadMapInput.?.addKey(.@"7", .keyDown);
|
|
_ = self.reloadMapInput.?.data.addListener(@This(), "onMapReload", self);
|
|
}
|
|
self.reloadMapInput.?.activate();
|
|
|
|
if (self.reloadInput == null) {
|
|
self.reloadInput = try core.ActionBinding.create(core.MakeName("reloadInput"));
|
|
self.reloadInput.?.addKey(.@"9", .keyDown);
|
|
_ = self.reloadInput.?.data.addListener(@This(), "onRequestReload", self);
|
|
}
|
|
self.reloadInput.?.activate();
|
|
|
|
if (self.fireInput == null) {
|
|
self.fireInput = try core.ActionBinding.create(core.MakeName("fire"));
|
|
self.fireInput.?.addKey(.Mouse1, .keyDown);
|
|
_ = self.fireInput.?.data.addListener(@This(), "onFire", self);
|
|
}
|
|
self.fireInput.?.activate();
|
|
|
|
if (self.altFireInput == null) {
|
|
self.altFireInput = try core.ActionBinding.create(core.MakeName("altFire"));
|
|
self.altFireInput.?.addKey(.Mouse3, .keyDown);
|
|
_ = self.altFireInput.?.data.addListener(@This(), "onAltFire", self);
|
|
}
|
|
self.altFireInput.?.activate();
|
|
|
|
if (self.openSpawner == null) {
|
|
self.openSpawner = try core.ActionBinding.create(core.MakeName("openSpawner"));
|
|
self.openSpawner.?.addKey(.@"8", .keyDown);
|
|
_ = self.openSpawner.?.data.addListener(@This(), "onOpenSpawner", self);
|
|
}
|
|
self.openSpawner.?.activate();
|
|
|
|
core.engine_log("inputs bound for externGame", .{});
|
|
}
|
|
|
|
pub fn objectReload(self: *@This()) void {
|
|
core.engine_logs("extern game object reload");
|
|
self.setupInputs() catch {
|
|
core.engine_errs("Unable to setup inputs");
|
|
};
|
|
}
|
|
|
|
pub fn endPlay(p: *anyopaque) void {
|
|
const self = core.cast(*@This(), p);
|
|
self.fireInput.?.deactivate();
|
|
self.altFireInput.?.deactivate();
|
|
}
|
|
|
|
pub fn loadMap2(self: *@This()) !void {
|
|
if (self.tbMap) |tbMap| {
|
|
core.engine_log("killing the map", .{});
|
|
tbMap.destroy();
|
|
}
|
|
|
|
self.tbMap = try bsp.maploader.LoadTrenchbroomMap(self.allocator, .{
|
|
.rotation = core.Rotation.eulerX(core.radians(-90.0)),
|
|
.mapName = "bsp/testmap.map",
|
|
});
|
|
|
|
core.engine_log("map loaded", .{});
|
|
}
|
|
|
|
pub fn create(allocator: std.mem.Allocator) !*@This() {
|
|
const self = try Slack.create(allocator);
|
|
self.* = .{
|
|
.allocator = allocator,
|
|
.particleDebugger = extras.ParticleDebugger.ParticleDebugger.init(),
|
|
};
|
|
|
|
// core.get(imgui.utils.TopBar).addMenuObject(self, "Input Stack Viewer", extras.inputDebugger.windowOpen);
|
|
|
|
self.physicsObjectsWindow = try extras.PhysicsObjectList.create(self.allocator);
|
|
|
|
const args = try core.ParseArgs(ExternGameArgs);
|
|
|
|
if (args.asClient) {
|
|
self.launchAsClient = args.clientTarget;
|
|
self.clientIndex = args.clientIndex;
|
|
core.engine_log("starting up as client connecting to {s}", .{args.clientTarget});
|
|
platform.context().pushRequest(.{ .setWindowSize = .{ .size = .{ .x = 1000, .y = 562 } } });
|
|
platform.context().pushRequest(.{ .setWindowPosition = .{ .pos = .{ .x = 1000 * args.clientIndex, .y = 30 } } });
|
|
|
|
const ctx = ui.getScreen();
|
|
const text = try ctx.addText(.{}, "client");
|
|
ctx.get(text).pos = .{ .x = 0, .y = 10 };
|
|
ctx.get(text).size = .{ .x = 400, .y = 300 };
|
|
|
|
ui.context().screenContext.debugFontSize = 20;
|
|
self.connectClient();
|
|
}
|
|
|
|
try core.registerObject(BoxObject, "Box");
|
|
try core.registerObjectAdvanced(BoxObject, "BoxSmoky", "createSmoky");
|
|
|
|
const settings: physics.ShapeSettings = .{ .box = try physics.BoxShapeSettings.create(.{ 1.0, 1.0, 1.0 }) };
|
|
defer settings.release();
|
|
try physics.addShape("ph_small_box", settings);
|
|
|
|
if (false) {
|
|
const ctx = ui.getScreen();
|
|
const panel2 = try ctx.addPanel(.{});
|
|
ctx.drawDebug = true;
|
|
{
|
|
ctx.getPanel(panel2).hasTitle = true;
|
|
//ctx.get(panel2).anchor = .TopRight;
|
|
// ctx.get(panel2).fill = .FillY; todo, this is a bug. why.
|
|
ctx.get(panel2).pos = .{ .x = 900, .y = 200 };
|
|
ctx.get(panel2).size = .{ .x = 300, .y = 500 };
|
|
ctx.get(panel2).style.backgroundColor = ui.ModernStyle.GreyDark;
|
|
ctx.getPanel(panel2).titleColor = ui.ModernStyle.GreyDark;
|
|
ctx.getPanel(panel2).layoutMode = .Vertical;
|
|
|
|
// add some text to this panel
|
|
const text = try ctx.addText(panel2, "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.");
|
|
ctx.get(text).pos = .{ .x = 2, .y = 2 };
|
|
ctx.get(text).size = .{ .x = 296, .y = 300 };
|
|
|
|
const btn = try ctx.addButton(panel2, "select file...");
|
|
_ = btn;
|
|
}
|
|
}
|
|
|
|
try extras.addGame("ExternGame", self, @This());
|
|
extras.beginGame("ExternGame");
|
|
|
|
return self;
|
|
}
|
|
|
|
fn editVector2(comptime Name: []const u8, v: *core.Vector2f) void {
|
|
const ItemWidth = 120;
|
|
|
|
ig.textFmt(Name, .{}) catch {};
|
|
ig.sameLine(0, 10);
|
|
ig.setNextItemWidth(ItemWidth);
|
|
_ = ig.inputFloat("X##particleEd" ++ Name, &v.x, 1.0, 5.0, null, .{});
|
|
ig.sameLine(0, 10);
|
|
ig.setNextItemWidth(ItemWidth);
|
|
_ = ig.inputFloat("Y##particleEd" ++ Name, &v.y, 1.0, 5.0, null, .{});
|
|
}
|
|
|
|
fn v2ToV3(v: core.Vector2f) core.Vectorf {
|
|
return core.Vectorf{ .x = v.x, .z = v.y, .y = 0 };
|
|
}
|
|
|
|
pub fn intersectLine(p1: core.Vector2f, v1: core.Vector2f, p2: core.Vector2f, v2: core.Vector2f) ?core.Vector2f {
|
|
const denom = v1.x * v2.y - v1.y * v2.x;
|
|
|
|
if (@abs(denom) < 0.00001) {
|
|
return null;
|
|
}
|
|
const t = ((p2.x - p1.x) * v2.y - (p2.y - p1.y) * v2.x) / denom;
|
|
|
|
return .{
|
|
.x = p1.x + t * v1.x,
|
|
.y = p1.y + t * v1.y,
|
|
};
|
|
}
|
|
|
|
pub fn drawVector2Test(self: *@This()) void {
|
|
if (ig.begin("vector2Test", null, .{})) {
|
|
editVector2("a", &self.a);
|
|
editVector2("Anormal", &self.Anormal);
|
|
ig.separator();
|
|
editVector2("b", &self.b);
|
|
editVector2("Bnormal", &self.Bnormal);
|
|
}
|
|
ig.end();
|
|
|
|
const a = core.Vectorf{ .x = self.a.x, .z = self.a.y, .y = 0 };
|
|
const b = core.Vectorf{ .x = self.b.x, .z = self.b.y, .y = 0 };
|
|
|
|
const A = core.Vectorf{ .x = self.Anormal.x, .z = self.Anormal.y, .y = 0 };
|
|
const B = core.Vectorf{ .x = self.Bnormal.x, .z = self.Bnormal.y, .y = 0 };
|
|
|
|
core.debugSphere(a, 0.1, .{});
|
|
core.debugSphere(b, 0.1, .{});
|
|
|
|
core.debugLine(a, a.add(A), .{ .color = .{ .y = 0, .x = 1.0 } });
|
|
core.debugLine(b, b.add(B), .{ .color = .{ .y = 0, .x = 1.0 } });
|
|
|
|
const Vab = self.b.sub(self.a);
|
|
const Vba = Vab.negate();
|
|
|
|
core.debugLine(a, a.add(v2ToV3(Vab)), .{ .color = .{ .x = 1.0, .z = 1.0 } });
|
|
// const ADwall = Vab.dot(self.Anormal.removeComponent(Vab.normalize()).normalize());
|
|
// const BDwall = Vba.dot(self.Anormal.removeComponent(Vba.normalize()).normalize());
|
|
|
|
//const Awall = Vab.removeComponent(self.Anormal.normalize()).normalize().fmul(ADwall).normalize();
|
|
const Awall = Vab.removeComponent(self.Anormal.normalize()).normalize();
|
|
const Bwall = Vba.removeComponent(self.Bnormal.normalize()).normalize();
|
|
|
|
//ig.textFmt("Awall: {d} {d}", .{ Awall.x, Awall.y }) catch {};
|
|
core.debugLine(a.sub(v2ToV3(Awall).fmul(10)), a.add(v2ToV3(Awall).fmul(10)), .{ .color = .{ .y = 1.0, .z = 1.0 } });
|
|
|
|
// ig.textFmt("Bwall: {d} {d}", .{ Bwall.x, Bwall.y }) catch {};
|
|
core.debugLine(b.sub(v2ToV3(Bwall).fmul(10)), b.add(v2ToV3(Bwall).fmul(10)), .{ .color = .{ .y = 1.0, .z = 1.0 } });
|
|
|
|
const vp = intersectLine(self.a, Awall.normalize(), self.b, Bwall.normalize()) orelse {
|
|
return;
|
|
};
|
|
|
|
// ig.textFmt("p, y: {d} {d}", .{ vp.x, vp.y }) catch {};
|
|
core.debugSphere(v2ToV3(vp), 0.1, .{ .color = .{ .y = 1.0, .z = 1.0, .x = 1.0 } });
|
|
}
|
|
|
|
pub fn recompileComplete(ctx: ?*anyopaque) void {
|
|
const self = core.cast(*@This(), ctx.?);
|
|
self.recompiling = false;
|
|
}
|
|
|
|
pub fn onOpenSpawner(ctx: ?*anyopaque, _: core.ActionEvent) void {
|
|
core.engine_logs("spawner opened");
|
|
_ = ctx;
|
|
if (core.getEngineObject(imgui.utils.TopBar)) |topbar| {
|
|
topbar.setEntryOpen("New Object Spawner", null);
|
|
}
|
|
}
|
|
|
|
pub fn onRequestReload(ctx: ?*anyopaque, _: core.ActionEvent) void {
|
|
const self = core.cast(*@This(), ctx.?);
|
|
|
|
if (!self.recompiling) {
|
|
self.recompiling = true;
|
|
const x = core.EngineObject(sys.SystemRunner).get();
|
|
x.commandQueue.pushLocked(.{
|
|
.subprocess = .{
|
|
.context = self,
|
|
.onComplete = recompileComplete,
|
|
.task = sys.SubprocessTask.runCommand(
|
|
x.allocator,
|
|
&.{ "zig", "build", "install" },
|
|
".",
|
|
) catch {
|
|
self.recompiling = false;
|
|
return;
|
|
},
|
|
},
|
|
}) catch {
|
|
self.recompiling = false;
|
|
return;
|
|
};
|
|
}
|
|
}
|
|
|
|
pub fn onAltFire(ctx: ?*anyopaque, _: core.ActionEvent) void {
|
|
const self: *@This() = @ptrCast(@alignCast(ctx));
|
|
|
|
if (platform.context().isCursorEnabled()) {
|
|
core.engine_logs("moving light");
|
|
core.debugTextLog("moving light", 3.5, .{ .color = core.colors.Color.Green });
|
|
const ray = rend.context().activeCamera.?.getNormalRayFromScreen(platform.getCursorPosition());
|
|
if (physics.traceLine(ray.start, ray.dir.fmul(10000), .{ .bodyFilter = &self.fireTraceFilter, .getNormalsSlow = true })) |r| {
|
|
if (r.normal) |n| {
|
|
const p = r.point.add(n.fmul(0.2));
|
|
core.debugSphere(p, 0.2, .{ .color = .{ .y = 1.0 }, .duration = 10.0 });
|
|
rend.context().lightPosition = p;
|
|
}
|
|
|
|
// core.debugLine(ray.start, ray.start.add(ray.dir.fmul(1000)), .{ .duration = 2.5 });
|
|
// physics.applyForce(r.body, ray.dir.fmul(400), r.point);
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn onFire(ctx: ?*anyopaque, _: core.ActionEvent) void {
|
|
const self: *@This() = @ptrCast(@alignCast(ctx));
|
|
|
|
if (platform.context().isCursorEnabled()) {
|
|
core.engine_logs("moving light");
|
|
const ray = rend.context().activeCamera.?.getNormalRayFromScreen(platform.getCursorPosition());
|
|
if (physics.traceLine(ray.start, ray.dir.fmul(10000), .{ .bodyFilter = &self.fireTraceFilter, .getNormalsSlow = true })) |r| {
|
|
if (r.normal) |n| {
|
|
const p: core.Vectorf = r.point.add(n.fmul(0.2));
|
|
|
|
const posRot = core.ScenePosRot{
|
|
.position = p,
|
|
};
|
|
self.spawnedEntities.append(self.allocator, core.get(extras.ObjectSystemSpawner).spawnObjectAt(posRot) orelse return) catch unreachable;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn tick(self: *@This(), dt: f64) void {
|
|
const rctx = rend.context();
|
|
_ = rctx;
|
|
|
|
_ = dt;
|
|
//self.time += @floatCast(dt);
|
|
|
|
//core.debugSphere(.{ .y = 10 + std.math.sin(self.time) }, 5, .{});
|
|
|
|
if (core.getEngineObject(imgui.utils.TopBar)) |topbar| {
|
|
topbar.menuOpen = platform.context().isCursorEnabled();
|
|
}
|
|
|
|
if (self.displayVectorsTest) {
|
|
self.drawVector2Test();
|
|
}
|
|
|
|
if (self.recompiling) {
|
|
if (ig.begin("recompiling", null, .{})) {
|
|
ig.textf("recompiling...", .{});
|
|
}
|
|
ig.end();
|
|
}
|
|
|
|
if (platform.context().isCursorEnabled()) {
|
|
imgui.utils.structDebugWindow(self);
|
|
|
|
// imgui.utils.structDebugWindow(core.get(rend.renderer.Renderer));
|
|
|
|
if (ig.begin("meh", null, .{})) {
|
|
// if (ig.checkbox("move lights ", null)) {}
|
|
|
|
ig.textFmt("info: - WASD to move, mouse to look,\n- Q and E to go up and down lol", .{}) catch return;
|
|
ig.textFmt("- shift to slow down camera speed", .{}) catch return;
|
|
ig.textFmt("- T to enable/disable mouse cursor", .{}) catch return;
|
|
ig.textFmt("- f2 to route all inputs to the doom player", .{}) catch return;
|
|
ig.textFmt("- movingLight checkbox makes the light stop moving with you", .{}) catch return;
|
|
|
|
ig.textf("lmao", .{});
|
|
|
|
if (ig.smallButton("800x450")) {
|
|
platform.context().pushRequest(.{ .setWindowSize = .{ .size = .{ .x = 800, .y = 450 } } });
|
|
}
|
|
|
|
if (ig.smallButton("1600x900")) {
|
|
platform.context().pushRequest(.{ .setWindowSize = .{ .size = .{ .x = 1600, .y = 900 } } });
|
|
}
|
|
|
|
if (ig.smallButton("maximize")) {
|
|
platform.context().pushRequest(.{ .maximizeWindow = .{} });
|
|
}
|
|
|
|
if (ig.smallButton("setMousePos")) {
|
|
platform.context().pushRequest(.{ .setMousePosition = .{ .pos = .{ .x = 800, .y = 450 } } });
|
|
}
|
|
|
|
if (ig.smallButton("reload map")) {
|
|
self.loadMap2() catch unreachable;
|
|
}
|
|
|
|
if (ig.smallButton("destroy map")) {
|
|
if (self.tbMap) |tbMap| {
|
|
core.engine_log("killing the map", .{});
|
|
tbMap.destroy();
|
|
self.tbMap = null;
|
|
}
|
|
}
|
|
if (ig.smallButton("dumpTimeline")) {
|
|
core.MemoryTracker.dumpTimeline("timeline.txt") catch unreachable;
|
|
}
|
|
|
|
if (ig.checkbox("vectors test", &self.displayVectorsTest)) {}
|
|
if (ig.checkbox("showdebug", &ui.context().screenContext.drawDebug)) {}
|
|
|
|
if (ig.smallButton("click for fun")) {
|
|
// var soundname = core.MakeName("s_macintosh");
|
|
// audio.context().playSound(&soundname) catch {};
|
|
}
|
|
|
|
if (ig.sliderFloat("sliderFloat", &self.volume, 0, 100, null, .{})) {
|
|
audio.context().setVolume(self.volume / 100);
|
|
}
|
|
|
|
_ = ig.checkbox("addClients", &self.autoAddClients);
|
|
ig.sameLine(0, 10);
|
|
if (self.autoAddClients) {
|
|
_ = ig.inputInt("clientCount", @ptrCast(&self.clientsToAdd), 1, 1, .{});
|
|
}
|
|
|
|
if (ig.smallButton("host")) {
|
|
self.session = blk: {
|
|
const s = net.hostSession(&.{"7777"}) catch {
|
|
core.engine_err("host server failed", .{});
|
|
break :blk null;
|
|
};
|
|
|
|
break :blk s;
|
|
};
|
|
|
|
if (self.session) |session| {
|
|
_ = session;
|
|
|
|
var fmt: [256]u8 = undefined;
|
|
var fmt2: [256]u8 = undefined;
|
|
for (0..self.clientsToAdd) |i| {
|
|
const ci = std.fmt.bufPrint(&fmt, "--clientIndex={d}", .{i}) catch {
|
|
core.engine_err("unable to create client {d} out of memory?", .{i});
|
|
break;
|
|
};
|
|
|
|
const igIni = std.fmt.bufPrint(&fmt2, "--imguiIni=client{d}.ini", .{i}) catch {
|
|
core.engine_err("unable to create client {d} out of memory?", .{i});
|
|
break;
|
|
};
|
|
|
|
_ = sys.SubprocessTask.runCommand(
|
|
self.allocator,
|
|
&.{ "zig-out/bin/sampleGame.exe", "--asClient=True", ci, igIni },
|
|
".",
|
|
) catch {
|
|
core.engine_err("unable to create client {d}", .{i});
|
|
break;
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ig.smallButton("connect")) {
|
|
self.connectClient();
|
|
}
|
|
|
|
if (self.clientLink) |link| {
|
|
if (ig.smallButton("sendMessageToServer")) {
|
|
link.sendMessage("hello from client", true) catch {};
|
|
link.sendMessage("hello from client (unreliable)", false) catch {};
|
|
const linkData = net.EnetTransport.getLinkData(link);
|
|
linkData.sendPacketChannelDebug("debug: unreliable over channel 0", false, 0);
|
|
linkData.sendPacketChannelDebug("debug: reliable over channel 1", true, 1);
|
|
}
|
|
}
|
|
}
|
|
ig.end();
|
|
|
|
if (platform.context().isCursorEnabled()) {
|
|
if (rend.context().activeCamera) |cam| {
|
|
const ray = cam.getNormalRayFromScreen(platform.getCursorPosition());
|
|
|
|
if (physics.traceLine(ray.start, ray.dir.fmul(10000), .{ .bodyFilter = &self.fireTraceFilter, .getNormalsSlow = false })) |r| {
|
|
core.debugSphere(r.point, 0.2, .{ .color = .{ .x = 1.0 }, .duration = 0 });
|
|
}
|
|
}
|
|
}
|
|
self.particleDebugger.particleDebug();
|
|
}
|
|
if (self.session) |session| {
|
|
if (ig.begin("host session", null, .{})) {
|
|
for (session.links.items) |link| {
|
|
const linkData = net.EnetTransport.getLinkData(link);
|
|
ig.textf("{s} {d}ms", .{ link.idString, linkData.peer.*.roundTripTime });
|
|
}
|
|
}
|
|
ig.end();
|
|
|
|
for (session.links.items) |link| {
|
|
const linkData = net.EnetTransport.getLinkData(link);
|
|
if (rend.context().activeCamera) |camera| {
|
|
linkData.testLinkPosition = camera.entity.fetch(core.Scene).?.getPosition();
|
|
}
|
|
}
|
|
}
|
|
if (self.clientLink) |link| {
|
|
const linkData = net.EnetTransport.getLinkData(link);
|
|
if (self.spawnedEntities.items.len > 0) {
|
|
self.spawnedEntities.items[0].fetch(core.Scene).?.setPosition(linkData.testLinkPosition);
|
|
}
|
|
core.debugSphere(linkData.testLinkPosition, 1.0, .{ .color = .{ .x = 1.0 } });
|
|
}
|
|
}
|
|
|
|
fn connectClient(self: *@This()) void {
|
|
self.clientLink = net.connect("127.0.0.1:7777") catch unreachable;
|
|
|
|
var fmt: [256]u8 = undefined;
|
|
if (self.clientLink) |link| {
|
|
const nameMsg = std.fmt.bufPrint(&fmt, "cname:client{d}", .{self.clientIndex}) catch {
|
|
core.engine_err("unable to create client message, out of memory?", .{});
|
|
return;
|
|
};
|
|
link.sendMessage(nameMsg, true) catch {
|
|
core.engine_err("unable to send message?", .{});
|
|
};
|
|
}
|
|
}
|
|
|
|
pub fn destroy(self: *@This()) void {
|
|
if (self.clientLink) |link| {
|
|
link.destroy();
|
|
}
|
|
|
|
if (self.session) |session| {
|
|
session.destroy();
|
|
}
|
|
|
|
if (self.tbMap) |map| {
|
|
map.destroy();
|
|
}
|
|
for (self.spawnedEntities.items) |*entity| {
|
|
entity.destroy();
|
|
}
|
|
|
|
self.spawnedEntities.deinit(self.allocator);
|
|
self.physicsObjectsWindow.destroy();
|
|
self.allocator.destroy(Slack.fromPtr(self));
|
|
}
|
|
};
|
|
|
|
pub export fn shutdown_module() void {}
|
|
|
|
const std = @import("std");
|
|
const backlog = @import("backlog");
|
|
const core = backlog.core;
|
|
const imgui = backlog.imgui;
|
|
const physics = backlog.physics;
|
|
const rend = backlog.rend;
|
|
const ig = imgui.api;
|
|
const sys = backlog.sys;
|
|
const ui = backlog.ui;
|
|
const net = backlog.net;
|
|
const audio = backlog.audio;
|
|
const platform = backlog.platform;
|
|
const extras = @import("gameExtras");
|
|
const bsp = @import("bsp");
|