diff --git a/src/block_entity.zig b/src/block_entity.zig index 20f656cd53..8ee5a5898c 100644 --- a/src/block_entity.zig +++ b/src/block_entity.zig @@ -226,8 +226,7 @@ pub const BlockEntityTypes = struct { // MARK: BlockEntityTypes fn onInventoryUpdateCallback(source: main.items.Inventory.Source) void { const pos = source.blockInventory; - const simChunk = main.server.world.?.getSimulationChunkAndIncreaseRefCount(pos[0], pos[1], pos[2]) orelse return; - defer simChunk.decreaseRefCount(); + const simChunk = main.server.world.?.getSimulationChunk(pos[0], pos[1], pos[2]) orelse return; const ch = simChunk.getChunk() orelse return; ch.mutex.lock(); defer ch.mutex.unlock(); diff --git a/src/chunk.zig b/src/chunk.zig index 60c8473656..65a9a8b557 100644 --- a/src/chunk.zig +++ b/src/chunk.zig @@ -467,9 +467,8 @@ pub const ServerChunk = struct { // MARK: ServerChunk shouldStoreNeighbors: bool = false, mutex: main.utils.Mutex = .{}, - refCount: std.atomic.Value(u16), - pub fn initAndIncreaseRefCount(pos: ChunkPosition) *ServerChunk { + pub fn init(pos: ChunkPosition) *ServerChunk { const self = serverPool.create(); std.debug.assert((pos.voxelSize - 1 & pos.voxelSize) == 0); std.debug.assert(@mod(pos.wx, pos.voxelSize) == 0 and @mod(pos.wy, pos.voxelSize) == 0 and @mod(pos.wz, pos.voxelSize) == 0); @@ -483,14 +482,12 @@ pub const ServerChunk = struct { // MARK: ServerChunk .blockPosToEntityDataMap = .{}, .blockPosToEntityDataMapMutex = .{}, }, - .refCount = .init(1), }; self.super.data.init(); return self; } - pub fn deinit(self: *ServerChunk) void { - std.debug.assert(self.refCount.raw == 0); + pub fn privateDeinit(self: *ServerChunk) void { const oldContext = main.sync.threadContext; defer main.sync.threadContext = oldContext; main.sync.threadContext = .chunkDeiniting; @@ -502,25 +499,14 @@ pub const ServerChunk = struct { // MARK: ServerChunk serverPool.destroy(@alignCast(self)); } + pub fn deferredDeinit(self: *ServerChunk) void { + main.heap.GarbageCollection.deferredFree(.{.ptr = self, .freeFunction = main.meta.castFunctionSelfToAnyopaque(privateDeinit)}); + } pub fn setChanged(self: *ServerChunk) void { self.mutex.assertLocked(); if (!self.wasChanged) { self.wasChanged = true; - self.increaseRefCount(); - main.server.world.?.queueChunkUpdateAndDecreaseRefCount(self); - } - } - - pub fn increaseRefCount(self: *ServerChunk) void { - const prevVal = self.refCount.fetchAdd(1, .monotonic); - std.debug.assert(prevVal != 0); - } - - pub fn decreaseRefCount(self: *ServerChunk) void { - const prevVal = self.refCount.fetchSub(1, .monotonic); - std.debug.assert(prevVal != 0); - if (prevVal == 1) { - self.deinit(); + main.server.world.?.queueChunkUpdate(self); } } @@ -690,13 +676,12 @@ pub const ServerChunk = struct { // MARK: ServerChunk var dz: i32 = -@as(i32, chunkSize); while (dz <= chunkSize) : (dz += chunkSize) { if (dx == 0 and dy == 0 and dz == 0) continue; - const ch = main.server.world.?.getOrGenerateChunkAndIncreaseRefCount(.{ + const ch = main.server.world.?.getOrGenerateChunk(.{ .wx = self.super.pos.wx +% dx, .wy = self.super.pos.wy +% dy, .wz = self.super.pos.wz +% dz, .voxelSize = 1, }); - defer ch.decreaseRefCount(); ch.mutex.lock(); defer ch.mutex.unlock(); if (!ch.wasStored) { @@ -747,8 +732,7 @@ pub const ServerChunk = struct { // MARK: ServerChunk nextPos.wy &= ~@as(i32, pos.voxelSize*chunkSize); nextPos.wz &= ~@as(i32, pos.voxelSize*chunkSize); nextPos.voxelSize *= 2; - const nextHigherLod = world.getOrGenerateChunkAndIncreaseRefCount(nextPos); - defer nextHigherLod.decreaseRefCount(); + const nextHigherLod = world.getOrGenerateChunk(nextPos); nextHigherLod.updateFromLowerResolution(self); } } diff --git a/src/itemdrop.zig b/src/itemdrop.zig index 7f59f55fae..9da81b7a35 100644 --- a/src/itemdrop.zig +++ b/src/itemdrop.zig @@ -212,8 +212,7 @@ pub const ItemDropManager = struct { // MARK: ItemDropManager var ii: u32 = 0; while (ii < self.size) { const i = self.indices[ii]; - if (self.world.?.getSimulationChunkAndIncreaseRefCount(@trunc(pos[i][0]), @trunc(pos[i][1]), @trunc(pos[i][2]))) |simChunk| { - defer simChunk.decreaseRefCount(); + if (self.world.?.getSimulationChunk(@trunc(pos[i][0]), @trunc(pos[i][1]), @trunc(pos[i][2]))) |simChunk| { if (simChunk.getChunk() != null) { // Check collision with blocks: updateEnt(&pos[i], &vel[i], &onGround[i], deltaTime); diff --git a/src/network/protocols.zig b/src/network/protocols.zig index b524da87bf..8c6faa6cc4 100644 --- a/src/network/protocols.zig +++ b/src/network/protocols.zig @@ -313,7 +313,7 @@ pub const chunkRequest = struct { // MARK: chunkRequest .voxelSize = @as(u31, 1) << voxelSizeShift, }; conn.user.?.increaseRefCount(); - main.server.world.?.queueChunkAndDecreaseRefCount(request, conn.user.?); + main.server.world.?.queueChunk(request, conn.user.?); } } pub fn sendRequest(conn: *Connection, requests: []chunk.ChunkPosition, basePosition: Vec3i, renderDistance: u16) void { @@ -839,7 +839,7 @@ pub const lightMapRequest = struct { // MARK: lightMapRequest }; if (conn.user) |user| { user.increaseRefCount(); - main.server.world.?.queueLightMapAndDecreaseRefCount(request, user); + main.server.world.?.queueLightMap(request, user); } } } @@ -1006,8 +1006,7 @@ pub const blockEntityUpdate = struct { // MARK: blockEntityUpdate fn serverReceive(_: *Connection, reader: *utils.BinaryReader) !void { const pos = try reader.readVec(Vec3i); const blockType = try reader.readInt(u16); - const simChunk = main.server.world.?.getSimulationChunkAndIncreaseRefCount(pos[0], pos[1], pos[2]) orelse return; - defer simChunk.decreaseRefCount(); + const simChunk = main.server.world.?.getSimulationChunk(pos[0], pos[1], pos[2]) orelse return; const ch = simChunk.chunk.load(.monotonic) orelse return; ch.mutex.lock(); defer ch.mutex.unlock(); diff --git a/src/server/SimulationChunk.zig b/src/server/SimulationChunk.zig index 93adaea8b4..4d224cb68e 100644 --- a/src/server/SimulationChunk.zig +++ b/src/server/SimulationChunk.zig @@ -8,48 +8,32 @@ const BlockUpdateSystem = main.server.BlockUpdateSystem; const SimulationChunk = @This(); chunk: std.atomic.Value(?*ServerChunk) = .init(null), -refCount: std.atomic.Value(u32), pos: ChunkPosition, blockUpdateSystem: BlockUpdateSystem, -pub fn initAndIncreaseRefCount(pos: ChunkPosition) *SimulationChunk { +pub fn init(pos: ChunkPosition) *SimulationChunk { const self = main.globalAllocator.create(SimulationChunk); self.* = .{ - .refCount = .init(1), .pos = pos, .blockUpdateSystem = .init(), }; return self; } -fn deinit(self: *SimulationChunk) void { - std.debug.assert(self.refCount.load(.monotonic) == 0); +fn privateDeinit(self: *SimulationChunk) void { self.blockUpdateSystem.deinit(); - if (self.chunk.raw) |ch| ch.decreaseRefCount(); main.globalAllocator.destroy(self); } -pub fn increaseRefCount(self: *SimulationChunk) void { - const prevVal = self.refCount.fetchAdd(1, .monotonic); - std.debug.assert(prevVal != 0); -} - -pub fn decreaseRefCount(self: *SimulationChunk) void { - const prevVal = self.refCount.fetchSub(1, .monotonic); - std.debug.assert(prevVal != 0); - if (prevVal == 2) { - main.server.world_zig.ChunkManager.tryRemoveSimulationChunk(self); - } - if (prevVal == 1) { - self.deinit(); - } +pub fn deferredDeinit(self: *SimulationChunk) void { + main.heap.GarbageCollection.deferredFree(.{.ptr = self, .freeFunction = main.meta.castFunctionSelfToAnyopaquep(privateDeinit)}); } pub fn getChunk(self: *SimulationChunk) ?*ServerChunk { return self.chunk.load(.acquire); } -pub fn setChunkAndDecreaseRefCount(self: *SimulationChunk, ch: *ServerChunk) void { +pub fn setChunk(self: *SimulationChunk, ch: *ServerChunk) void { std.debug.assert(self.chunk.swap(ch, .release) == null); } diff --git a/src/server/server.zig b/src/server/server.zig index b47a91912c..1aa4b35f7c 100644 --- a/src/server/server.zig +++ b/src/server/server.zig @@ -331,7 +331,6 @@ pub const User = struct { // MARK: User while (z != lastBoxEnd[2]) : (z +%= chunk.chunkSize) { const inZDistance = z -% newBoxStart[2] >= 0 and z -% newBoxEnd[2] < 0; if (!inXDistance or !inYDistance or !inZDistance) { - self.loadedChunks[simArrIndex(x)][simArrIndex(y)][simArrIndex(z)].decreaseRefCount(); self.loadedChunks[simArrIndex(x)][simArrIndex(y)][simArrIndex(z)] = undefined; } } @@ -355,7 +354,7 @@ pub const User = struct { // MARK: User while (z != newBoxEnd[2]) : (z +%= chunk.chunkSize) { const inZDistance = z -% lastBoxStart[2] >= 0 and z -% lastBoxEnd[2] < 0; if (!inXDistance or !inYDistance or !inZDistance) { - self.loadedChunks[simArrIndex(x)][simArrIndex(y)][simArrIndex(z)] = world_zig.ChunkManager.getOrGenerateSimulationChunkAndIncreaseRefCount(.{.wx = x, .wy = y, .wz = z, .voxelSize = 1}); + self.loadedChunks[simArrIndex(x)][simArrIndex(y)][simArrIndex(z)] = world_zig.ChunkManager.getOrGenerateSimulationChunk(.{.wx = x, .wy = y, .wz = z, .voxelSize = 1}); } } } diff --git a/src/server/world.zig b/src/server/world.zig index 3f58ddd975..7d384fa2d2 100644 --- a/src/server/world.zig +++ b/src/server/world.zig @@ -127,7 +127,7 @@ pub const ChunkManager = struct { // MARK: ChunkManager // There will be at most 1 GiB of chunks in here. TODO: Allow configuring this in the server settings. const reducedChunkCacheMask = 2047; - var chunkCache: Cache(ServerChunk, reducedChunkCacheMask + 1, 4, chunkDeinitFunctionForCache) = .{}; + var chunkCache: Cache(ServerChunk, reducedChunkCacheMask + 1, 4, ServerChunk.deferredDeinit) = .{}; const HashContext = struct { pub fn hash(_: HashContext, a: chunk.ChunkPosition) u64 { return a.hashCode(); @@ -139,41 +139,35 @@ pub const ChunkManager = struct { // MARK: ChunkManager var simulationChunkHashMap: std.HashMap(chunk.ChunkPosition, *SimulationChunk, HashContext, 50) = undefined; var mutex: main.utils.Mutex = .{}; - fn getSimulationChunkAndIncreaseRefCount(pos: chunk.ChunkPosition) ?*SimulationChunk { + fn getSimulationChunk(pos: chunk.ChunkPosition) ?*SimulationChunk { std.debug.assert(pos.voxelSize == 1); mutex.lock(); defer mutex.unlock(); if (simulationChunkHashMap.get(pos)) |ch| { - ch.increaseRefCount(); return ch; } return null; } - pub fn getOrGenerateSimulationChunkAndIncreaseRefCount(pos: chunk.ChunkPosition) *SimulationChunk { + pub fn getOrGenerateSimulationChunk(pos: chunk.ChunkPosition) *SimulationChunk { std.debug.assert(pos.voxelSize == 1); mutex.lock(); if (simulationChunkHashMap.get(pos)) |ch| { - ch.increaseRefCount(); mutex.unlock(); return ch; } - const ch = SimulationChunk.initAndIncreaseRefCount(pos); - ch.increaseRefCount(); - ch.increaseRefCount(); + const ch = SimulationChunk.init(pos); + simulationChunkHashMap.put(pos, ch) catch unreachable; mutex.unlock(); - ChunkLoadTask.scheduleAndDecreaseRefCount(pos, .{.simulationChunk = ch}); + ChunkLoadTask.schedule(pos, .{.simulationChunk = ch}); return ch; } pub fn tryRemoveSimulationChunk(ch: *SimulationChunk) void { mutex.lock(); defer mutex.unlock(); - if (ch.refCount.load(.monotonic) == 1) { // Only we hold it. - std.debug.assert(simulationChunkHashMap.remove(ch.pos)); - ch.decreaseRefCount(); - } + std.debug.assert(simulationChunkHashMap.remove(ch.pos)); } const Source = union(enum) { @@ -193,7 +187,7 @@ pub const ChunkManager = struct { // MARK: ChunkManager .taskType = .chunkgen, }; - pub fn scheduleAndDecreaseRefCount(pos: ChunkPosition, source: Source) void { + pub fn schedule(pos: ChunkPosition, source: Source) void { const task = main.globalAllocator.create(ChunkLoadTask); task.* = ChunkLoadTask{ .pos = pos, @@ -219,7 +213,7 @@ pub const ChunkManager = struct { // MARK: ChunkManager pub fn isStillNeeded(self: *ChunkLoadTask) bool { switch (self.source) { // Remove the task if the player disconnected .user => |user| if (!user.connected.load(.monotonic)) return false, - .simulationChunk => |ch| if (ch.refCount.load(.monotonic) == 2) return false, + .simulationChunk => {}, } switch (self.source) { // Remove the task if it's far enough away from the player: .user => |user| { @@ -242,7 +236,7 @@ pub const ChunkManager = struct { // MARK: ChunkManager pub fn clean(self: *ChunkLoadTask) void { switch (self.source) { .user => |user| user.decreaseRefCount(), - .simulationChunk => |ch| ch.decreaseRefCount(), + .simulationChunk => {}, } main.globalAllocator.destroy(self); } @@ -260,7 +254,7 @@ pub const ChunkManager = struct { // MARK: ChunkManager .taskType = .misc, }; - pub fn scheduleAndDecreaseRefCount(pos: terrain.SurfaceMap.MapFragmentPosition, source: ?*User) void { + pub fn schedule(pos: terrain.SurfaceMap.MapFragmentPosition, source: ?*User) void { const task = main.globalAllocator.create(LightMapLoadTask); task.* = LightMapLoadTask{ .pos = pos, @@ -330,35 +324,32 @@ pub const ChunkManager = struct { // MARK: ChunkManager storage.deinit(); } - pub fn queueLightMapAndDecreaseRefCount(self: ChunkManager, pos: terrain.SurfaceMap.MapFragmentPosition, source: ?*User) void { + pub fn queueLightMap(self: ChunkManager, pos: terrain.SurfaceMap.MapFragmentPosition, source: ?*User) void { _ = self; - LightMapLoadTask.scheduleAndDecreaseRefCount(pos, source); + LightMapLoadTask.schedule(pos, source); } - pub fn queueChunkAndDecreaseRefCount(self: ChunkManager, pos: ChunkPosition, source: *User) void { + pub fn queueChunk(self: ChunkManager, pos: ChunkPosition, source: *User) void { _ = self; - ChunkLoadTask.scheduleAndDecreaseRefCount(pos, .{.user = source}); + ChunkLoadTask.schedule(pos, .{.user = source}); } pub fn generateChunk(pos: ChunkPosition, source: Source) void { // MARK: generateChunk() - const ch = getOrGenerateChunkAndIncreaseRefCount(pos); + const ch = getOrGenerateChunk(pos); switch (source) { .user => |user| { main.network.protocols.chunkTransmission.sendChunk(user.conn, ch); - ch.decreaseRefCount(); }, .simulationChunk => |simulationChunk| { - simulationChunk.setChunkAndDecreaseRefCount(ch); + simulationChunk.setChunk(ch); }, } } - fn chunkInitFunctionForCacheAndIncreaseRefCount(pos: ChunkPosition) *ServerChunk { + fn chunkInitFunctionForCache(pos: ChunkPosition) *ServerChunk { if (pos.voxelSize == 1) { - if (getSimulationChunkAndIncreaseRefCount(pos)) |simulationChunk| { // Check if we already have it in memory. - defer simulationChunk.decreaseRefCount(); + if (getSimulationChunk(pos)) |simulationChunk| { // Check if we already have it in memory. if (simulationChunk.getChunk()) |ch| { - ch.increaseRefCount(); return ch; } } @@ -367,7 +358,7 @@ pub const ChunkManager = struct { // MARK: ChunkManager const regionMask: i32 = regionSize - 1; const region = storage.loadRegionFileAndIncreaseRefCount(pos.wx & ~regionMask, pos.wy & ~regionMask, pos.wz & ~regionMask, pos.voxelSize); defer region.decreaseRefCount(); - const ch = ServerChunk.initAndIncreaseRefCount(pos); + const ch = ServerChunk.init(pos); ch.mutex.lock(); defer ch.mutex.unlock(); if (region.getChunk( @@ -399,22 +390,19 @@ pub const ChunkManager = struct { // MARK: ChunkManager } return ch; } - - fn chunkDeinitFunctionForCache(ch: *ServerChunk) void { - ch.decreaseRefCount(); - } + fn chunkDeinitFunctionForCache(_: *ServerChunk) void {} /// Generates a normal chunk at a given location, or if possible gets it from the cache. - pub fn getOrGenerateChunkAndIncreaseRefCount(pos: ChunkPosition) *ServerChunk { + pub fn getOrGenerateChunk(pos: ChunkPosition) *ServerChunk { const mask = pos.voxelSize*chunk.chunkSize - 1; std.debug.assert(pos.wx & mask == 0 and pos.wy & mask == 0 and pos.wz & mask == 0); - const result = chunkCache.findOrCreate(pos, chunkInitFunctionForCacheAndIncreaseRefCount, ServerChunk.increaseRefCount); + const result = chunkCache.findOrCreate(pos, chunkInitFunctionForCache, null); return result; } - pub fn getChunkFromCacheAndIncreaseRefCount(pos: ChunkPosition) ?*ServerChunk { + pub fn getChunkFromCache(pos: ChunkPosition) ?*ServerChunk { const mask = pos.voxelSize*chunk.chunkSize - 1; std.debug.assert(pos.wx & mask == 0 and pos.wy & mask == 0 and pos.wz & mask == 0); - const result = chunkCache.find(pos, ServerChunk.increaseRefCount) orelse return null; + const result = chunkCache.find(pos, null) orelse return null; return result; } }; @@ -554,7 +542,6 @@ pub const ServerWorld = struct { // MARK: ServerWorld }; while (self.chunkUpdateQueue.popFront()) |updateRequest| { updateRequest.ch.save(self); - updateRequest.ch.decreaseRefCount(); } self.chunkUpdateQueue.deinit(); while (self.regionUpdateQueue.popFront()) |updateRequest| { @@ -757,15 +744,13 @@ pub const ServerWorld = struct { // MARK: ServerWorld .wz = self.pos.wz + @as(i32, @intCast(z))*chunk.chunkSize, .voxelSize = 1, }; - const ch = ChunkManager.getOrGenerateChunkAndIncreaseRefCount(pos); - defer ch.decreaseRefCount(); + const ch = ChunkManager.getOrGenerateChunk(pos); var nextPos = pos; nextPos.wx &= ~@as(i32, self.pos.voxelSize*chunk.chunkSize); nextPos.wy &= ~@as(i32, self.pos.voxelSize*chunk.chunkSize); nextPos.wz &= ~@as(i32, self.pos.voxelSize*chunk.chunkSize); nextPos.voxelSize *= 2; - const nextHigherLod = ChunkManager.getOrGenerateChunkAndIncreaseRefCount(nextPos); - defer nextHigherLod.decreaseRefCount(); + const nextHigherLod = ChunkManager.getOrGenerateChunk(nextPos); ch.mutex.lock(); defer ch.mutex.unlock(); nextHigherLod.updateFromLowerResolution(ch); @@ -844,7 +829,6 @@ pub const ServerWorld = struct { // MARK: ServerWorld self.mutex.unlock(); defer self.mutex.lock(); updateRequest.ch.save(self); - updateRequest.ch.decreaseRefCount(); main.heap.GarbageCollection.syncPoint(); } while (self.regionUpdateQueue.popFront()) |updateRequest| { @@ -1111,13 +1095,11 @@ pub const ServerWorld = struct { // MARK: ServerWorld var currentChunks: main.List(*SimulationChunk) = .initCapacity(main.stackAllocator, iter.len); defer currentChunks.deinit(main.stackAllocator); while (iter.next()) |simulationChunk| { - simulationChunk.*.increaseRefCount(); currentChunks.append(main.stackAllocator, simulationChunk.*); } ChunkManager.mutex.unlock(); for (currentChunks.items) |simulationChunk| { - defer simulationChunk.decreaseRefCount(); simulationChunk.update(self.tickSpeed.load(.monotonic)); } } @@ -1166,7 +1148,6 @@ pub const ServerWorld = struct { // MARK: ServerWorld self.mutex.unlock(); defer self.mutex.lock(); updateRequest.ch.save(self); - updateRequest.ch.decreaseRefCount(); if (updateRequest.milliTimeStamp -% insertionTime.toMilliseconds() >= 0) break; } while (self.regionUpdateQueue.popFront()) |updateRequest| { @@ -1178,27 +1159,27 @@ pub const ServerWorld = struct { // MARK: ServerWorld } } - pub fn queueChunkAndDecreaseRefCount(self: *ServerWorld, pos: ChunkPosition, source: *User) void { - self.chunkManager.queueChunkAndDecreaseRefCount(pos, source); + pub fn queueChunk(self: *ServerWorld, pos: ChunkPosition, source: *User) void { + self.chunkManager.queueChunk(pos, source); } - pub fn queueLightMapAndDecreaseRefCount(self: *ServerWorld, pos: terrain.SurfaceMap.MapFragmentPosition, source: *User) void { - self.chunkManager.queueLightMapAndDecreaseRefCount(pos, source); + pub fn queueLightMap(self: *ServerWorld, pos: terrain.SurfaceMap.MapFragmentPosition, source: *User) void { + self.chunkManager.queueLightMap(pos, source); } - pub fn getSimulationChunkAndIncreaseRefCount(_: *ServerWorld, x: i32, y: i32, z: i32) ?*SimulationChunk { - if (ChunkManager.getSimulationChunkAndIncreaseRefCount(.{.wx = x & ~@as(i32, chunk.chunkMask), .wy = y & ~@as(i32, chunk.chunkMask), .wz = z & ~@as(i32, chunk.chunkMask), .voxelSize = 1})) |entityChunk| { + pub fn getSimulationChunk(_: *ServerWorld, x: i32, y: i32, z: i32) ?*SimulationChunk { + if (ChunkManager.getSimulationChunk(.{.wx = x & ~@as(i32, chunk.chunkMask), .wy = y & ~@as(i32, chunk.chunkMask), .wz = z & ~@as(i32, chunk.chunkMask), .voxelSize = 1})) |entityChunk| { return entityChunk; } return null; } - pub fn getOrGenerateChunkAndIncreaseRefCount(_: *ServerWorld, pos: chunk.ChunkPosition) *ServerChunk { - return ChunkManager.getOrGenerateChunkAndIncreaseRefCount(pos); + pub fn getOrGenerateChunk(_: *ServerWorld, pos: chunk.ChunkPosition) *ServerChunk { + return ChunkManager.getOrGenerateChunk(pos); } - pub fn getChunkFromCacheAndIncreaseRefCount(_: *ServerWorld, pos: chunk.ChunkPosition) ?*ServerChunk { - return ChunkManager.getChunkFromCacheAndIncreaseRefCount(pos); + pub fn getChunkFromCache(_: *ServerWorld, pos: chunk.ChunkPosition) ?*ServerChunk { + return ChunkManager.getChunkFromCache(pos); } pub fn getBiome(_: *const ServerWorld, wx: i32, wy: i32, wz: i32) *const terrain.biomes.Biome { @@ -1209,8 +1190,7 @@ pub const ServerWorld = struct { // MARK: ServerWorld pub fn getBlock(self: *ServerWorld, x: i32, y: i32, z: i32) ?Block { const chunkPos = Vec3i{x, y, z} & ~@as(Vec3i, @splat(main.chunk.chunkMask)); - const otherChunk = self.getSimulationChunkAndIncreaseRefCount(chunkPos[0], chunkPos[1], chunkPos[2]) orelse return null; - defer otherChunk.decreaseRefCount(); + const otherChunk = self.getSimulationChunk(chunkPos[0], chunkPos[1], chunkPos[2]) orelse return null; const ch = otherChunk.getChunk() orelse return null; ch.mutex.lock(); defer ch.mutex.unlock(); @@ -1219,8 +1199,7 @@ pub const ServerWorld = struct { // MARK: ServerWorld pub fn getBlockAndBlockEntityData(self: *ServerWorld, x: i32, y: i32, z: i32, blockEntityDataWriter: *utils.BinaryWriter) ?Block { const chunkPos = Vec3i{x, y, z} & ~@as(Vec3i, @splat(main.chunk.chunkMask)); - const otherChunk = self.getSimulationChunkAndIncreaseRefCount(chunkPos[0], chunkPos[1], chunkPos[2]) orelse return null; - defer otherChunk.decreaseRefCount(); + const otherChunk = self.getSimulationChunk(chunkPos[0], chunkPos[1], chunkPos[2]) orelse return null; const ch = otherChunk.getChunk() orelse return null; ch.mutex.lock(); defer ch.mutex.unlock(); @@ -1234,8 +1213,7 @@ pub const ServerWorld = struct { // MARK: ServerWorld /// Returns the actual block on failure pub fn cmpxchgBlock(self: *ServerWorld, wx: i32, wy: i32, wz: i32, oldBlock: ?Block, _newBlock: Block) ?Block { main.sync.threadContext.assertCorrectContext(.server); - const baseChunk = ChunkManager.getOrGenerateChunkAndIncreaseRefCount(.{.wx = wx & ~@as(i32, chunk.chunkMask), .wy = wy & ~@as(i32, chunk.chunkMask), .wz = wz & ~@as(i32, chunk.chunkMask), .voxelSize = 1}); - defer baseChunk.decreaseRefCount(); + const baseChunk = ChunkManager.getOrGenerateChunk(.{.wx = wx & ~@as(i32, chunk.chunkMask), .wy = wy & ~@as(i32, chunk.chunkMask), .wz = wz & ~@as(i32, chunk.chunkMask), .voxelSize = 1}); const pos: chunk.BlockPos = .fromWorldCoords(wx, wy, wz); baseChunk.mutex.lock(); const currentBlock = baseChunk.getBlock(pos.x, pos.y, pos.z); @@ -1252,16 +1230,13 @@ pub const ServerWorld = struct { // MARK: ServerWorld const neighborPos, const chunkLocation = pos.neighbor(neighbor); var ch = baseChunk; if (chunkLocation == .inNeighborChunk) { - ch = ChunkManager.getOrGenerateChunkAndIncreaseRefCount(.{ + ch = ChunkManager.getOrGenerateChunk(.{ .wx = baseChunk.super.pos.wx +% pos.x +% neighbor.relX() & ~@as(i32, chunk.chunkMask), .wy = baseChunk.super.pos.wy +% pos.y +% neighbor.relY() & ~@as(i32, chunk.chunkMask), .wz = baseChunk.super.pos.wz +% pos.z +% neighbor.relZ() & ~@as(i32, chunk.chunkMask), .voxelSize = 1, }); } - defer if (ch != baseChunk) { - ch.decreaseRefCount(); - }; ch.mutex.lock(); defer ch.mutex.unlock(); @@ -1321,8 +1296,7 @@ pub const ServerWorld = struct { // MARK: ServerWorld wz + value.relZ(), }; - var ch = self.getSimulationChunkAndIncreaseRefCount(pos[0], pos[1], pos[2]) orelse continue; - defer ch.decreaseRefCount(); + var ch = self.getSimulationChunk(pos[0], pos[1], pos[2]) orelse continue; ch.blockUpdateSystem.add(.{ .x = @truncate(@as(u32, @bitCast(pos[0]))), @@ -1336,7 +1310,7 @@ pub const ServerWorld = struct { // MARK: ServerWorld _ = self.cmpxchgBlock(wx, wy, wz, null, newBlock); } - pub fn queueChunkUpdateAndDecreaseRefCount(self: *ServerWorld, ch: *ServerChunk) void { + pub fn queueChunkUpdate(self: *ServerWorld, ch: *ServerChunk) void { self.mutex.lock(); self.chunkUpdateQueue.pushBack(.{.ch = ch, .milliTimeStamp = main.timestamp().toMilliseconds()}); self.mutex.unlock();