Skip to content

Commit

Permalink
Update block breaking overlay to match vanilla better and render bloc…
Browse files Browse the repository at this point in the history
…k breaking overlay when other players are breaking blocks too
  • Loading branch information
stackotter committed May 31, 2024
1 parent 33c8879 commit 0123db7
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 6 deletions.
6 changes: 2 additions & 4 deletions Sources/Core/Renderer/World/WorldRenderer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -359,16 +359,14 @@ public final class WorldRenderer: Renderer {
}
}
model.textureType = .transparent
// No clue why light level 12 is the right one, vanilla seems to use light level 15 here but that
// just doesn't work for us at all (way too bright).
let lightLevel = LightLevel(
sky: 12,
sky: 15,
block: 0
)
var neighbourLightLevels: [Direction: LightLevel] = [:]
for direction in Direction.allDirections {
neighbourLightLevels[direction] = LightLevel(
sky: 12,
sky: 15,
block: 0
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,8 @@ public struct BlockBreakAnimationPacket: ClientboundPacket {
location = try packetReader.readBlockPosition()
destroyStage = try packetReader.readByte()
}

public func handle(for client: Client) throws {
client.game.world.setBlockBreakingStage(at: location, to: Int(destroyStage), for: entityId)
}
}
47 changes: 45 additions & 2 deletions Sources/Core/Sources/World/World.swift
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,14 @@ public class World {
chunk.setBlockId(at: position.relativeToChunk, to: state)
lightingEngine.updateLighting(at: position, in: self)

blockBreakingLock.acquireWriteLock()
// Use removeAll instead of filter to minimize cost in the case that the set block
// wasn't associated with a breaking block (probably the most likely case?)
breakingBlocks.removeAll { block in
block.position == position
}
blockBreakingLock.unlock()

eventBus.dispatch(Event.SingleBlockUpdate(
position: position,
newState: state
Expand All @@ -409,12 +417,13 @@ public class World {
_ updates: [Event.SingleBlockUpdate],
inChunkAt chunkPosition: ChunkPosition? = nil
) {
let positions = updates.map(\.position)
if let chunkPosition = chunkPosition {
if let chunk = chunk(at: chunkPosition) {
for update in updates {
chunk.setBlockId(at: update.position.relativeToChunk, to: update.newState)
}
lightingEngine.updateLighting(at: updates.map(\.position), in: self)
lightingEngine.updateLighting(at: positions, in: self)
} else {
log.warning("Cannot handle multi-block change in non-existent chunk, chunkPosition=\(chunkPosition)")
return
Expand All @@ -428,8 +437,16 @@ public class World {
return
}
}
lightingEngine.updateLighting(at: updates.map(\.position), in: self)
lightingEngine.updateLighting(at: positions, in: self)
}

blockBreakingLock.acquireWriteLock()
// Use removeAll instead of filter to minimize cost in the case that the set block
// wasn't associated with a breaking block (probably the most likely case?)
breakingBlocks.removeAll { block in
positions.contains(block.position)
}
blockBreakingLock.unlock()

eventBus.dispatch(Event.MultiBlockUpdate(updates: updates))
}
Expand Down Expand Up @@ -717,6 +734,32 @@ public class World {
)
}

/// Sets the block breaking progress of a given block to a value corresponding to a specific
/// stage of the block breaking animation. If the block is not already getting broken, it gets
/// added to the list of breaking blocks.
public func setBlockBreakingStage(at position: BlockPosition, to stage: Int, for entityId: Int) {
blockBreakingLock.acquireWriteLock()
defer { blockBreakingLock.unlock() }

let progress = Double(clamp(stage + 1, min: 0, max: 10)) / 10

for (i, block) in breakingBlocks.enumerated() {
if block.position == position {
breakingBlocks[i].progress = progress
breakingBlocks[i].perpetratorEntityId = entityId
return
}
}

breakingBlocks.append(
BreakingBlock(
position: position,
perpetratorEntityId: entityId,
progress: progress
)
)
}

/// Does nothing if the specified block isn't getting broken.
public func addBreakingProgress(_ progress: Double, toBlockAt position: BlockPosition) {
blockBreakingLock.acquireWriteLock()
Expand Down

0 comments on commit 0123db7

Please sign in to comment.