2024-08-18 18:16:27 -07:00
|
|
|
public struct Chunk {
|
|
|
|
public static let chunkSize: Int = 16
|
2024-08-20 03:21:55 +10:00
|
|
|
public static let blockCount = chunkSize * chunkSize * chunkSize
|
|
|
|
|
|
|
|
private static let yStride = chunkSize
|
|
|
|
private static let zStride = chunkSize * chunkSize
|
2024-08-18 18:16:27 -07:00
|
|
|
|
|
|
|
public let position: SIMD3<Int>
|
|
|
|
private var blocks: [Block]
|
|
|
|
|
|
|
|
init(position: SIMD3<Int>, blocks: [Block]) {
|
2024-08-20 03:21:55 +10:00
|
|
|
assert(blocks.count == Self.blockCount)
|
2024-08-18 18:16:27 -07:00
|
|
|
self.position = position
|
|
|
|
self.blocks = blocks
|
|
|
|
}
|
|
|
|
|
|
|
|
init(position: SIMD3<Int>) {
|
|
|
|
self.position = position
|
|
|
|
self.blocks = Array(
|
|
|
|
repeating: BlockType.air,
|
2024-08-20 03:21:55 +10:00
|
|
|
count: Self.blockCount
|
2024-08-18 18:16:27 -07:00
|
|
|
).map { type in Block(type) }
|
|
|
|
}
|
|
|
|
|
2024-08-20 03:21:55 +10:00
|
|
|
func getBlock(at position: SIMD3<Int>) -> Block {
|
|
|
|
if position.x < 0 || position.y < 0 || position.z < 0 {
|
|
|
|
Block(.air)
|
|
|
|
} else if position.x >= Self.chunkSize || position.y >= Self.chunkSize || position.z >= Self.chunkSize {
|
|
|
|
Block(.air)
|
|
|
|
} else {
|
|
|
|
blocks[position.x + position.y * Self.yStride + position.z * Self.zStride]
|
|
|
|
}
|
2024-08-18 18:16:27 -07:00
|
|
|
}
|
|
|
|
|
2024-08-20 03:21:55 +10:00
|
|
|
mutating func setBlock(at position: SIMD3<Int>, type: BlockType) {
|
|
|
|
if position.x < 0 || position.y < 0 || position.z < 0 {
|
2024-08-18 18:37:32 -07:00
|
|
|
return
|
|
|
|
}
|
2024-08-20 03:21:55 +10:00
|
|
|
if position.x >= Self.chunkSize || position.y >= Self.chunkSize || position.z >= Self.chunkSize {
|
2024-08-18 18:37:32 -07:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-08-20 03:21:55 +10:00
|
|
|
blocks[position.x + position.y * Self.yStride + position.z * Self.zStride].type = type
|
2024-08-18 18:16:27 -07:00
|
|
|
}
|
|
|
|
|
2024-08-23 16:55:59 +10:00
|
|
|
mutating func fill(allBy calculation: (_ position: SIMD3<Int>) -> BlockType) {
|
|
|
|
var i = 0
|
|
|
|
for x in 0..<Self.chunkSize {
|
|
|
|
for y in 0..<Self.chunkSize {
|
|
|
|
for z in 0..<Self.chunkSize {
|
|
|
|
blocks[i].type = calculation(SIMD3(x, y, z))
|
|
|
|
i += 1
|
|
|
|
}
|
|
|
|
}
|
2024-08-18 18:16:27 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-20 03:21:55 +10:00
|
|
|
func forEach(block perform: (Block, SIMD3<Int>) -> Void) {
|
|
|
|
for x in 0..<Self.chunkSize {
|
|
|
|
for y in 0..<Self.chunkSize {
|
|
|
|
for z in 0..<Self.chunkSize {
|
|
|
|
let idx = x + y * Self.yStride + z * Self.zStride
|
|
|
|
let position = SIMD3(x, y, z)
|
|
|
|
perform(blocks[idx], position)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public func map<T>(block transform: (Block, SIMD3<Int>) throws -> T) rethrows -> [T] {
|
|
|
|
assert(self.blocks.count == Self.blockCount)
|
|
|
|
|
|
|
|
var out = [T]()
|
|
|
|
out.reserveCapacity(Self.blockCount)
|
|
|
|
|
|
|
|
var position = SIMD3<Int>()
|
|
|
|
for i in self.blocks.indices {
|
|
|
|
out.append(try transform(blocks[i], position))
|
|
|
|
position.x += 1
|
|
|
|
if position.x == Self.chunkSize {
|
|
|
|
position.x = 0
|
|
|
|
position.y += 1
|
|
|
|
if position.y == Self.chunkSize {
|
|
|
|
position.y = 0
|
|
|
|
position.z += 1
|
2024-08-18 18:16:27 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-08-20 03:21:55 +10:00
|
|
|
|
|
|
|
return out
|
|
|
|
}
|
|
|
|
|
|
|
|
public func compactMap<T>(block transform: (Block, SIMD3<Int>) throws -> T?) rethrows -> [T] {
|
|
|
|
assert(self.blocks.count == Self.blockCount)
|
|
|
|
|
|
|
|
var out = [T]()
|
|
|
|
out.reserveCapacity(Self.blockCount >> 1)
|
|
|
|
|
|
|
|
var position = SIMD3<Int>()
|
|
|
|
for i in self.blocks.indices {
|
|
|
|
if let element = try transform(blocks[i], position) {
|
|
|
|
out.append(element)
|
|
|
|
}
|
|
|
|
position.x += 1
|
|
|
|
if position.x == Self.chunkSize {
|
|
|
|
position.x = 0
|
|
|
|
position.y += 1
|
|
|
|
if position.y == Self.chunkSize {
|
|
|
|
position.y = 0
|
|
|
|
position.z += 1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return out
|
2024-08-18 18:16:27 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public enum BlockType: Equatable {
|
|
|
|
case air
|
2024-08-22 03:49:50 +10:00
|
|
|
case solid(_ color: Color<Float16>)
|
2024-08-18 18:16:27 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
public struct Block {
|
|
|
|
public var type: BlockType
|
2024-08-20 03:21:55 +10:00
|
|
|
|
2024-08-18 18:16:27 -07:00
|
|
|
public init(_ type: BlockType) {
|
|
|
|
self.type = type
|
|
|
|
}
|
|
|
|
}
|