Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 147 additions & 3 deletions src/Inventory.zig
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ pub const Sync = struct { // MARK: Sync
defer main.stackAllocator.free(users);

for (users) |user| {
if (user == source) continue;
if (user == source and op.ignoreSource()) continue;
main.network.Protocols.inventory.sendSyncOperation(user.conn, syncData);
}
}
Expand Down Expand Up @@ -410,6 +410,14 @@ pub const Sync = struct { // MARK: Sync
}
};

pub fn addHealth(health: f32, cause: main.game.DamageType, side: Side, id: u32) void {
if (side == .client) {
Sync.ClientSide.executeCommand(.{.addHealth = .{.target = id, .health = health, .cause = cause}});
} else {
Sync.ServerSide.executeCommand(.{.addHealth = .{.target = id, .health = health, .cause = cause}}, null);
}
}

pub fn getInventory(id: u32, side: Side, user: ?*main.server.User) ?Inventory {
return switch(side) {
.client => ClientSide.getInventory(id),
Expand Down Expand Up @@ -438,6 +446,7 @@ pub const Command = struct { // MARK: Command
depositOrDrop = 7,
clear = 8,
updateBlock = 9,
addHealth = 10,
};
pub const Payload = union(PayloadType) {
open: Open,
Expand All @@ -450,6 +459,7 @@ pub const Command = struct { // MARK: Command
depositOrDrop: DepositOrDrop,
clear: Clear,
updateBlock: UpdateBlock,
addHealth: AddHealth,
};

const BaseOperationType = enum(u8) {
Expand All @@ -458,6 +468,7 @@ pub const Command = struct { // MARK: Command
delete = 2,
create = 3,
useDurability = 4,
addHealth = 5,
};

const InventoryAndSlot = struct {
Expand Down Expand Up @@ -508,12 +519,20 @@ pub const Command = struct { // MARK: Command
durability: u31,
previousDurability: u32 = undefined,
},
addHealth: struct {
target: ?*main.server.User,
health: f32,
cause: main.game.DamageType,
previous: f32
}
};

const SyncOperationType = enum(u8) {
create = 0,
delete = 1,
useDurability = 2,
health = 3,
kill = 4,
};

const SyncOperation = union(SyncOperationType) { // MARK: SyncOperation
Expand All @@ -531,6 +550,13 @@ pub const Command = struct { // MARK: Command
inv: InventoryAndSlot,
durability: u32
},
health: struct {
target: ?*main.server.User,
health: f32
},
kill: struct {
target: ?*main.server.User
},

pub fn executeFromData(data: []const u8) !void {
std.debug.assert(data.len >= 1);
Expand Down Expand Up @@ -569,6 +595,12 @@ pub const Command = struct { // MARK: Command
}

durability.inv.inv.update();
},
.health => |health| {
main.game.Player.super.health = std.math.clamp(main.game.Player.super.health + health.health, 0, main.game.Player.super.maxHealth);
},
.kill => {
main.game.Player.kill();
}
}
}
Expand All @@ -577,10 +609,22 @@ pub const Command = struct { // MARK: Command
switch (self) {
inline .create, .delete, .useDurability => |data| {
return allocator.dupe(*main.server.User, Sync.ServerSide.inventories.items[data.inv.inv.id].users.items);
},
inline .health, .kill => |data| {
const out = allocator.alloc(*main.server.User, 1);
out[0] = data.target.?;
return out;
}
}
}

pub fn ignoreSource(self: SyncOperation) bool {
return switch (self) {
.create, .delete, .useDurability, .health => true,
.kill => false
};
}

fn deserialize(fullData: []const u8) !SyncOperation {
if (fullData.len == 0) {
return error.Invalid;
Expand Down Expand Up @@ -630,6 +674,25 @@ pub const Command = struct { // MARK: Command
}};

return out;
},
.health => {
if (data.len != 4) {
return error.Invalid;
}

return .{.health = .{
.target = null,
.health = @bitCast(std.mem.readInt(u32, data[0..4], .big))
}};
},
.kill => {
if (data.len != 0) {
return error.Invalid;
}

return .{.kill = .{
.target = null,
}};
}
}
}
Expand Down Expand Up @@ -657,7 +720,11 @@ pub const Command = struct { // MARK: Command
.useDurability => |durability| {
durability.inv.write(data.addMany(8)[0..8]);
std.mem.writeInt(u32, data.addMany(4)[0..4], durability.durability, .big);
}
},
.health => |health| {
std.mem.writeInt(u32, data.addMany(4)[0..4], @bitCast(health.health), .big);
},
.kill => {},
}
return data.toOwnedSlice();
}
Expand Down Expand Up @@ -729,6 +796,9 @@ pub const Command = struct { // MARK: Command
info.source.ref().item = info.item;
info.item.tool.durability = info.previousDurability;
info.source.inv.update();
},
.addHealth => |info| {
main.game.Player.super.health = info.previous;
}
}
}
Expand All @@ -737,7 +807,7 @@ pub const Command = struct { // MARK: Command
fn finalize(self: Command, allocator: NeverFailingAllocator, side: Side, data: []const u8) void {
for(self.baseOperations.items) |step| {
switch(step) {
.move, .swap, .create => {},
.move, .swap, .create, .addHealth => {},
.delete => |info| {
info.item.?.deinit();
},
Expand Down Expand Up @@ -854,6 +924,30 @@ pub const Command = struct { // MARK: Command
self.executeDurabilityUseOperation(allocator, side, info.source, info.durability);
info.source.inv.update();
},
.addHealth => |*info| {
if (side == .server) {
info.previous = info.target.?.player.health;

info.target.?.player.health = std.math.clamp(info.target.?.player.health + info.health, 0, info.target.?.player.maxHealth);

if (info.target.?.player.health <= 0) {
info.target.?.player.health = info.target.?.player.maxHealth;
info.cause.sendMessage(info.target.?.name);

self.syncOperations.append(allocator, .{.kill = .{
.target = info.target.?
}});
} else {
self.syncOperations.append(allocator, .{.health = .{
.target = info.target.?,
.health = info.health
}});
}
} else {
info.previous = main.game.Player.super.health;
main.game.Player.super.health = std.math.clamp(main.game.Player.super.health + info.health, 0, main.game.Player.super.maxHealth);
}
}
}
self.baseOperations.append(allocator, op);
}
Expand Down Expand Up @@ -1497,6 +1591,56 @@ pub const Command = struct { // MARK: Command
};
}
};

const AddHealth = struct { // MARK: AddHealth
target: u32,
health: f32,
cause: main.game.DamageType,

pub fn run(self: AddHealth, allocator: NeverFailingAllocator, cmd: *Command, side: Side, _: ?*main.server.User, _: Gamemode) error{serverFailure}!void {
var target: ?*main.server.User = null;

if (side == .server) {
const userList = main.server.getUserListAndIncreaseRefCount(main.stackAllocator);
defer main.server.freeUserListAndDecreaseRefCount(main.stackAllocator, userList);
for (userList) |user| {
if (user.id == self.target) {
target = user;
break;
}
}

if (target == null) return error.serverFailure;

if (target.?.gamemode.raw == .creative) return;
} else {
if (main.game.Player.gamemode.raw == .creative) return;
}

cmd.executeBaseOperation(allocator, .{.addHealth = .{
.target = target,
.health = self.health,
.cause = self.cause,
.previous = if (side == .server) target.?.player.health else main.game.Player.super.health
}}, side);
}

fn serialize(self: AddHealth, data: *main.List(u8)) void {
std.mem.writeInt(u32, data.addMany(4)[0..4], self.target, .big);
std.mem.writeInt(u32, data.addMany(4)[0..4], @bitCast(self.health), .big);
data.append(@intFromEnum(self.cause));
}

fn deserialize(data: []const u8, _: Side, _: ?*main.server.User) !AddHealth {
if(data.len != 9) return error.Invalid;

return .{
.target = std.mem.readInt(u32, data[0..4], .big),
.health = @bitCast(std.mem.readInt(u32, data[4..8], .big)),
.cause = @enumFromInt(data[8]),
};
}
};
};

const SourceType = enum(u8) {
Expand Down
34 changes: 31 additions & 3 deletions src/game.zig
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,20 @@ pub const collision = struct {

pub const Gamemode = enum(u8) { survival = 0, creative = 1 };

pub const DamageType = enum(u8) {
heal = 0, // For when you are adding health
kill = 1,
fall = 2,

pub fn sendMessage(self: DamageType, name: []const u8) void {
switch (self) {
.heal => main.server.sendMessage("{s}§#ffffff was healed", .{name}),
.kill => main.server.sendMessage("{s}§#ffffff was killed", .{name}),
.fall => main.server.sendMessage("{s}§#ffffff died of fall damage", .{name}),
}
}
};

pub const Player = struct { // MARK: Player
pub var super: main.server.Entity = .{};
pub var eyePos: Vec3d = .{0, 0, 0};
Expand All @@ -341,9 +355,6 @@ pub const Player = struct { // MARK: Player
pub var inventory: Inventory = undefined;
pub var selectedSlot: u32 = 0;

pub var maxHealth: f32 = 8;
pub var health: f32 = 4.5;

pub var onGround: bool = false;
pub var jumpCooldown: f64 = 0;
const jumpCooldownConstant = 0.3;
Expand Down Expand Up @@ -442,6 +453,17 @@ pub const Player = struct { // MARK: Player
inventory.placeBlock(selectedSlot);
}

pub fn kill() void {
Player.super.pos = world.?.spawn;
Player.super.vel = .{0, 0, 0};

Player.super.health = Player.super.maxHealth;

Player.eyeVel = .{0, 0, 0};
Player.eyeCoyote = 0;
Player.eyeStep = .{false, false, false};
}

pub fn breakBlock(deltaTime: f64) void {
if(!main.Window.grabbed) return;
inventory.breakBlock(selectedSlot, deltaTime);
Expand Down Expand Up @@ -955,6 +977,12 @@ pub fn update(deltaTime: f64) void { // MARK: update()
} else {
Player.super.pos[2] = box.min[2] - hitBox.max[2];
}

const damage: f32 = @floatCast(@round(@max((Player.super.vel[2] * Player.super.vel[2]) / (2 * gravity) - 3, 0)) / 2);
if (damage > 0.01) {
Inventory.Sync.addHealth(-damage, .fall, .client, Player.id);
}

Player.super.vel[2] = 0;

// Always unstuck upwards for now
Expand Down
6 changes: 3 additions & 3 deletions src/gui/windows/healthbar.zig
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,14 @@ pub fn render() void {
var y: f32 = 0;
var x: f32 = 0;
var health: f32 = 0;
while(health < main.game.Player.maxHealth) : (health += 1) {
while(health < main.game.Player.super.maxHealth) : (health += 1) {
if(x >= window.contentSize[0]) {
x = 0;
y += 20;
}
if(health + 1 <= main.game.Player.health) {
if(health + 1 <= main.game.Player.super.health) {
heartTexture.bindTo(0);
} else if(health + 0.5 <= main.game.Player.health) {
} else if(health + 0.5 <= main.game.Player.super.health) {
halfHeartTexture.bindTo(0);
} else {
deadHeartTexture.bindTo(0);
Expand Down
7 changes: 6 additions & 1 deletion src/server/Entity.zig
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,24 @@ const NeverFailingAllocator = main.utils.NeverFailingAllocator;
pos: Vec3d = .{0, 0, 0},
vel: Vec3d = .{0, 0, 0},
rot: Vec3f = .{0, 0, 0},
// TODO: Health and hunger

health: f32 = 8,
maxHealth: f32 = 8,
// TODO: Hunger
// TODO: Name

pub fn loadFrom(self: *@This(), zon: ZonElement) void {
self.pos = zon.get(Vec3d, "position", .{0, 0, 0});
self.vel = zon.get(Vec3d, "velocity", .{0, 0, 0});
self.rot = zon.get(Vec3f, "rotation", .{0, 0, 0});
self.health = zon.get(f32, "health", self.maxHealth);
}

pub fn save(self: *@This(), allocator: NeverFailingAllocator) ZonElement {
const zon = ZonElement.initObject(allocator);
zon.put("position", self.pos);
zon.put("velocity", self.vel);
zon.put("rotation", self.rot);
zon.put("health", self.health);
return zon;
}
1 change: 1 addition & 0 deletions src/server/command/_list.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ pub const clear = @import("clear.zig");
pub const gamemode = @import("gamemode.zig");
pub const help = @import("help.zig");
pub const invite = @import("invite.zig");
pub const kill = @import("kill.zig");
pub const time = @import("time.zig");
pub const tp = @import("tp.zig");
15 changes: 15 additions & 0 deletions src/server/command/kill.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const std = @import("std");

const main = @import("root");
const User = main.server.User;

pub const description = "Kills the player";
pub const usage = "/kill";

pub fn execute(args: []const u8, source: *User) void {
if(args.len != 0) {
source.sendMessage("#ff0000Too many arguments for command /kill. Expected no arguments.", .{});
return;
}
main.items.Inventory.Sync.addHealth(-std.math.floatMax(f32), .kill, .server, source.id);
}
Loading