Skip to content

Commit

Permalink
hopefully save the hand and also when the player leaves or server clo…
Browse files Browse the repository at this point in the history
…ses (#943)

* hopefully save the hand and also when the player leaves or server closes

* fixes

* change it to check the user id

* fix

* check pointers

* fix compilation error

* fix other bugs

* put player id in source

* fix error

* remove one line of code

* fix serialization

* revert < 22 to < 14

* change

* fix error where inventory not saved on alt f4

* change connected to a regular bool

* remove isConnected function
  • Loading branch information
OneAvargeCoder193 authored Jan 26, 2025
1 parent fabc5c1 commit 1de5efb
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 15 deletions.
33 changes: 24 additions & 9 deletions src/Inventory.zig
Original file line number Diff line number Diff line change
Expand Up @@ -310,14 +310,14 @@ pub const Sync = struct { // MARK: Sync
}
}
},
.playerInventory, .other => {},
.playerInventory, .hand, .other => {},
.alreadyFreed => unreachable,
}
const inventory = ServerInventory.init(len, typ, source);

switch (source) {
.sharedTestingInventory => {},
.playerInventory => {
.playerInventory, .hand => {
const dest: []u8 = main.stackAllocator.alloc(u8, std.base64.url_safe.Encoder.calcSize(user.name.len));
defer main.stackAllocator.free(dest);
const hashedName = std.base64.url_safe.Encoder.encode(dest, user.name);
Expand All @@ -328,7 +328,7 @@ pub const Sync = struct { // MARK: Sync
const playerData = main.files.readToZon(main.stackAllocator, path) catch .null;
defer playerData.deinit(main.stackAllocator);

const inventoryZon = playerData.getChild("inventory");
const inventoryZon = playerData.getChild(@tagName(source));

inventory.inv.loadFromZon(inventoryZon);
},
Expand All @@ -352,10 +352,10 @@ pub const Sync = struct { // MARK: Sync
return inventories.items[serverId].inv;
}

pub fn getInventoryFromSource(source: SourceType) ?Inventory {
pub fn getInventoryFromSource(source: Source) ?Inventory {
main.utils.assertLocked(&mutex);
for(inventories.items) |inv| {
if (inv.source == source) {
if (std.meta.eql(inv.source, source)) {
return inv.inv;
}
}
Expand Down Expand Up @@ -1059,8 +1059,14 @@ pub const Command = struct { // MARK: Command
std.mem.writeInt(usize, data.addMany(8)[0..8], self.inv._items.len, .big);
data.append(@intFromEnum(self.inv.type));
data.append(@intFromEnum(self.source));
switch (self.source) {
.playerInventory, .hand => |val| {
std.mem.writeInt(u32, data.addMany(4)[0..4], val, .big);
},
else => {}
}
switch(self.source) {
.playerInventory, .sharedTestingInventory, .other => {},
.playerInventory, .sharedTestingInventory, .hand, .other => {},
.alreadyFreed => unreachable,
}
}
Expand All @@ -1073,8 +1079,9 @@ pub const Command = struct { // MARK: Command
const typ: Inventory.Type = @enumFromInt(data[12]);
const sourceType: SourceType = @enumFromInt(data[13]);
const source: Source = switch(sourceType) {
.playerInventory => .{.playerInventory = {}},
.playerInventory => .{.playerInventory = std.mem.readInt(u32, data[14..18], .big)},
.sharedTestingInventory => .{.sharedTestingInventory = {}},
.hand => .{.hand = std.mem.readInt(u32, data[14..18], .big)},
.other => .{.other = {}},
.alreadyFreed => unreachable,
};
Expand Down Expand Up @@ -1647,12 +1654,14 @@ const SourceType = enum(u8) {
alreadyFreed = 0,
playerInventory = 1,
sharedTestingInventory = 2,
hand = 3,
other = 0xff, // TODO: List every type separately here.
};
const Source = union(SourceType) {
alreadyFreed: void,
playerInventory: void,
playerInventory: u32,
sharedTestingInventory: void,
hand: u32,
other: void,
};

Expand Down Expand Up @@ -1691,7 +1700,13 @@ fn _init(allocator: NeverFailingAllocator, _size: usize, _type: Type, side: Side
}

pub fn deinit(self: Inventory, allocator: NeverFailingAllocator) void {
Sync.ClientSide.executeCommand(.{.close = .{.inv = self, .allocator = allocator}});
if (main.game.world.?.connected) {
Sync.ClientSide.executeCommand(.{.close = .{.inv = self, .allocator = allocator}});
} else {
Sync.ClientSide.mutex.lock();
defer Sync.ClientSide.mutex.unlock();
self._deinit(allocator, .client);
}
}

fn _deinit(self: Inventory, allocator: NeverFailingAllocator, side: Side) void {
Expand Down
10 changes: 7 additions & 3 deletions src/game.zig
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,7 @@ pub const World = struct { // MARK: World
milliTime: i64,
gameTime: Atomic(i64) = .init(0),
spawn: Vec3f = undefined,
connected: bool = true,
blockPalette: *assets.Palette = undefined,
biomePalette: *assets.Palette = undefined,
itemDrops: ClientItemDropManager = undefined,
Expand All @@ -595,6 +596,7 @@ pub const World = struct { // MARK: World
.name = "client",
.milliTime = std.time.milliTimestamp(),
};

self.itemDrops.init(main.globalAllocator, self);
network.Protocols.handShake.clientSide(self.conn, settings.playerName);

Expand All @@ -607,15 +609,17 @@ pub const World = struct { // MARK: World
}

pub fn deinit(self: *World) void {
self.conn.deinit();

self.connected = false;

// TODO: Close all world related guis.
main.gui.inventory.deinit();
main.gui.deinit();
main.gui.init();

Player.inventory.deinit(main.globalAllocator);

main.threadPool.clear();
self.conn.deinit();
self.itemDrops.deinit();
self.blockPalette.deinit();
self.biomePalette.deinit();
Expand All @@ -642,7 +646,7 @@ pub const World = struct { // MARK: World
try assets.loadWorldAssets("serverAssets", self.blockPalette, self.biomePalette);
Player.loadFrom(zon.getChild("player"));
Player.id = zon.get(u32, "player_id", std.math.maxInt(u32));
Player.inventory = Inventory.init(main.globalAllocator, 32, .normal, .playerInventory);
Player.inventory = Inventory.init(main.globalAllocator, 32, .normal, .{.playerInventory = Player.id});
}

pub fn update(self: *World) void {
Expand Down
2 changes: 1 addition & 1 deletion src/gui/gui.zig
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ pub const inventory = struct { // MARK: inventory
var initialized: bool = false;

pub fn init() void {
carried = Inventory.init(main.globalAllocator, 1, .normal, .other);
carried = Inventory.init(main.globalAllocator, 1, .normal, .{.hand = main.game.Player.id});
leftClickSlots = .init(main.globalAllocator);
rightClickSlots = .init(main.globalAllocator);
carriedItemSlot = ItemSlot.init(.{0, 0}, carried, 0, .default, .normal);
Expand Down
6 changes: 6 additions & 0 deletions src/server/server.zig
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ pub const User = struct { // MARK: User

pub fn deinit(self: *User) void {
std.debug.assert(self.refCount.load(.monotonic) == 0);

world.?.savePlayer(self) catch |err| {
std.log.err("Failed to save player: {s}", .{@errorName(err)});
return;
};

main.items.Inventory.Sync.ServerSide.disconnectUser(self);
std.debug.assert(self.inventoryClientToServerIdMap.count() == 0); // leak
self.inventoryClientToServerIdMap.deinit();
Expand Down
8 changes: 6 additions & 2 deletions src/server/world.zig
Original file line number Diff line number Diff line change
Expand Up @@ -815,8 +815,12 @@ pub const ServerWorld = struct { // MARK: ServerWorld
{
main.items.Inventory.Sync.ServerSide.mutex.lock();
defer main.items.Inventory.Sync.ServerSide.mutex.unlock();
if (main.items.Inventory.Sync.ServerSide.getInventoryFromSource(.playerInventory)) |inv| {
playerZon.put("inventory", inv.save(main.stackAllocator));
if (main.items.Inventory.Sync.ServerSide.getInventoryFromSource(.{.playerInventory = user.id})) |inv| {
playerZon.put("playerInventory", inv.save(main.stackAllocator));
}

if (main.items.Inventory.Sync.ServerSide.getInventoryFromSource(.{.hand = user.id})) |inv| {
playerZon.put("hand", inv.save(main.stackAllocator));
}
}

Expand Down

0 comments on commit 1de5efb

Please sign in to comment.