Advertisement
yal_f

Untitled

May 16th, 2024 (edited)
304
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 16.93 KB | None | 0 0
  1. --!optimize 2
  2. --!native
  3.  
  4. local RepStorage = game:FindService("ReplicatedStorage")
  5.  
  6. local chunkMeshTime = {0,0}
  7. local chunkBuildTime = {0,0}
  8. local bench = table.create(4,0)
  9.  
  10. local CHUNK_REF = script.Chunk
  11. local CHUNK_FOLDER = workspace.ChunkFolder
  12.  
  13. local BLOCK_DATA = require(RepStorage.BlockData)
  14. local STRUCTURE_DATA = require(RepStorage.StructureData)
  15. local NOISE_SEED = os.clock()
  16.  
  17. local Vector3Half = Vector3.one/2
  18.  
  19. local VERT_OFFS_1 = Vector3.new(-0.5, -0.5, -0.5)
  20. local VERT_OFFS_2 = Vector3.new( 0.5, -0.5, -0.5)
  21. local VERT_OFFS_3 = Vector3.new(-0.5, -0.5,  0.5)
  22. local VERT_OFFS_4 = Vector3.new( 0.5, -0.5,  0.5)
  23.  
  24. local FRONT_FACE  = {4,2,1,1,3,4}
  25. local BACK_FACE   = {3,1,2,2,4,3}
  26. local TOP_FACE    = {1,3,4,4,2,1}
  27. local BOTTOM_FACE = {1,2,4,4,3,1}
  28. local RIGHT_FACE  = {3,1,2,2,4,3}
  29. local LEFT_FACE   = {4,2,1,1,3,4}
  30.  
  31. local module = {}
  32. local chunks = {}
  33.  
  34. --config
  35.  
  36. local CHUNK_WIDTH = 16
  37.  
  38. local OCTAVES = 5 -- how much noise maps to sum, default 4
  39. local PERSISTANCE = 0.325 -- lower = later octaves height matter less to the final result, default 0.33
  40. local LUCANARITY = 3 -- lower = later octaves get scaled smaller, default 2.74
  41.  
  42. local NOISE_WIDTH = 780 --default 150
  43. local NOISE_HEIGHT = 450 -- default 80
  44.  
  45. local OCEAN_HEIGHT = 2
  46. local TREE_CHANCE = 200
  47.  
  48. --index constants
  49.  
  50. local IDX_VOXELS = 1
  51. local IDX_EDITMESH = 2
  52. local IDX_CHUNKPOS = 3
  53.  
  54. local IDX_COLORMIN = 1
  55. local IDX_COLORMAX = 2
  56.  
  57. --
  58. local POS_LIMIT = CHUNK_WIDTH-1
  59. local CHUNK_WIDTH_SQUARED = CHUNK_WIDTH^2
  60. local CHUNK_WIDTH_CUBED = CHUNK_WIDTH^3
  61. local CHUNK_VECTOR = Vector3.new(CHUNK_WIDTH, CHUNK_WIDTH, CHUNK_WIDTH)
  62.  
  63. local function RevealChunk(chunk, color)
  64.     local part = Instance.new("Part")
  65.     part.Transparency = 1
  66.     part.Anchored = true
  67.     part.CanCollide = false
  68.     part.CanQuery = false
  69.     part.Size = CHUNK_VECTOR
  70.     part.Position = chunk[IDX_CHUNKPOS] * CHUNK_WIDTH + (CHUNK_VECTOR - Vector3.one)/2
  71.     local box = Instance.new("SelectionBox")
  72.     box.Adornee = part
  73.     box.Parent = part
  74.    
  75.     if color then
  76.         box.Color = color
  77.     end
  78.    
  79.     part.Parent = workspace
  80. end
  81.  
  82. local function Flatten(x,y,z)
  83.     return x + (y * CHUNK_WIDTH) + (z * CHUNK_WIDTH_SQUARED)
  84. end
  85.  
  86. local function IsBufferEmpty(buff)
  87.     return string.rep("\0", buffer.len(buff)) == buffer.tostring(buff)
  88. end
  89.  
  90. local function GetBufferSize(buff)
  91.     local count = 0
  92.  
  93.     for i = 0, buffer.len(buff)-1, 4 do
  94.         local data = buffer.readu32(buff, i)
  95.         if bit32.btest(data, 0xFF) then count += 1 end
  96.         if bit32.btest(data, 0xFF00) then count += 1 end
  97.         if bit32.btest(data, 0xFF0000) then count += 1 end
  98.         if bit32.btest(data, 0xFF000000) then count += 1 end
  99.     end
  100.  
  101.     return count
  102. end
  103.  
  104. local function DrawFace(editMesh, color, p1,p2,p3,p4, map)
  105.     local verts = {
  106.         editMesh:AddVertex(p1),
  107.         editMesh:AddVertex(p2),
  108.         editMesh:AddVertex(p3),
  109.         editMesh:AddVertex(p4)
  110.     }
  111.  
  112.     for i,v in verts do
  113.         editMesh:SetVertexColor(v, color)
  114.     end
  115.  
  116.     editMesh:AddTriangle(verts[map[1]], verts[map[2]], verts[map[3]])
  117.     editMesh:AddTriangle(verts[map[4]], verts[map[5]], verts[map[6]])
  118. end
  119.  
  120. local function GenerateNoise(Z,X)
  121.     local noise = 0
  122.     local amplitude = 1
  123.    
  124.     for _ = 1, OCTAVES do
  125.         noise += math.noise(X / NOISE_WIDTH, Z / NOISE_WIDTH, NOISE_SEED) * amplitude
  126.        
  127.         X *= LUCANARITY
  128.         Z *= LUCANARITY
  129.         amplitude *= PERSISTANCE
  130.     end
  131.  
  132.     return noise >= 0 and noise^1.25 or -(math.abs(noise)^0.5)
  133. end
  134.  
  135. local function GetChunkNeighbors(chunkPos)
  136.     return {
  137.         chunks[chunkPos + Vector3.xAxis],
  138.         chunks[chunkPos - Vector3.xAxis],
  139.         chunks[chunkPos + Vector3.yAxis],
  140.         chunks[chunkPos - Vector3.yAxis],
  141.         chunks[chunkPos + Vector3.zAxis],
  142.         chunks[chunkPos - Vector3.zAxis]
  143.     }
  144. end
  145.  
  146. local function RemoveChunk(pos)
  147.     local chunk = chunks[pos][IDX_EDITMESH].Parent:Destroy()
  148.     chunks[pos] = nil
  149. end
  150.  
  151. local function AddChunk(chunkPos)
  152.     local mesh = CHUNK_REF:Clone()
  153.     mesh.Position = chunkPos * CHUNK_WIDTH
  154.  
  155.     local chunk = {
  156.         buffer.create(CHUNK_WIDTH_CUBED),
  157.         Instance.new("EditableMesh", mesh),
  158.         chunkPos
  159.     }
  160.  
  161.     chunks[chunkPos] = chunk
  162.     mesh.Parent = CHUNK_FOLDER
  163.  
  164.     return chunk
  165. end
  166.  
  167. local function GetChunksInRange(centerPos, range, createChunks)
  168.     local rangeVector = Vector3.new(range, range, range)
  169.  
  170.     local minPos = (centerPos - rangeVector) // CHUNK_WIDTH
  171.     local maxPos = (centerPos + rangeVector) // CHUNK_WIDTH + Vector3.one
  172.  
  173.     local touchingChunks = {}
  174.  
  175.     for z = minPos.Z, maxPos.Z do
  176.         for y = minPos.Y, maxPos.Y do
  177.             for x = minPos.X, maxPos.X do
  178.                 local chunkPos = Vector3.new(x,y,z)
  179.  
  180.                 local chunkMin = chunkPos * CHUNK_WIDTH
  181.                 local chunkMax = chunkMin + CHUNK_VECTOR
  182.  
  183.                 local closestPoint = chunkMin:Max(centerPos:Min(chunkMax))
  184.  
  185.                 if (closestPoint - centerPos).Magnitude <= range then
  186.                     local chunk = chunks[chunkPos]
  187.  
  188.                     if not chunk then
  189.                         if not createChunks then
  190.                             continue
  191.                         end
  192.                         chunk = AddChunk(chunkPos)
  193.                     end
  194.  
  195.                     table.insert(touchingChunks, chunk)
  196.                 end
  197.             end
  198.         end
  199.     end
  200.  
  201.     return touchingChunks
  202. end
  203.  
  204. local function GetChunksInBounds(centerPos, size, createChunks)
  205.     size //= 2
  206.     local minPos = (centerPos - size) // CHUNK_WIDTH
  207.     local maxPos = (centerPos + size) // CHUNK_WIDTH + Vector3.one
  208.  
  209.     local touchingChunks = {}
  210.  
  211.     for z = minPos.Z, maxPos.Z do
  212.         for y = minPos.Y, maxPos.Y do
  213.             for x = minPos.X, maxPos.X do
  214.                 local chunkPos = Vector3.new(x,y,z)
  215.  
  216.                 local chunkMin = chunkPos * CHUNK_WIDTH
  217.                 local chunkMax = chunkMin + CHUNK_VECTOR
  218.  
  219.                 local closestPoint = chunkMin:Max(centerPos:Min(chunkMax))
  220.  
  221.                 local delta = (closestPoint - centerPos)
  222.  
  223.                 if delta.X <= size.X and delta.Y <= size.Z and delta.Z <= size.Z then
  224.                     local chunk = chunks[chunkPos]
  225.  
  226.                     if not chunk then
  227.                         if not createChunks then
  228.                             continue
  229.                         end
  230.                         chunk = AddChunk(chunkPos)
  231.                     end
  232.  
  233.                     table.insert(touchingChunks, chunk)
  234.                 end
  235.             end
  236.         end
  237.     end
  238.  
  239.     return touchingChunks
  240. end
  241.  
  242. local function UpdateChunk(chunk)
  243.     if not chunk then return end
  244.  
  245.     local clock = os.clock()
  246.  
  247.     local oldEditMesh = chunk[IDX_EDITMESH]
  248.     local replaceEditMesh = #oldEditMesh:GetVertices() ~= 0
  249.     local editMesh = replaceEditMesh and Instance.new("EditableMesh") or oldEditMesh
  250.  
  251.     local voxels = chunk[IDX_VOXELS]
  252.     local chunkPos = chunk[IDX_CHUNKPOS]
  253.     local chunkNeighbors = GetChunkNeighbors(chunkPos)
  254.     local reserved = {}
  255.  
  256.     if not IsBufferEmpty(voxels) then
  257.         for Z = 0, POS_LIMIT do
  258.             local Zindex = Z * CHUNK_WIDTH_SQUARED
  259.             for Y = 0, POS_LIMIT do
  260.                 local Yindex = Y * CHUNK_WIDTH
  261.                 local YZindex = Zindex + Yindex
  262.                 for X = 0, POS_LIMIT do
  263.                     local Xindex = X
  264.                     local gridIndex = YZindex + Xindex
  265.                     local blockID = buffer.readu8(voxels, gridIndex)
  266.  
  267.                     if blockID == 0 then continue end -- skip air
  268.  
  269.                     local centerPos = Vector3.new(X,Y,Z)
  270.                     local blockTypeData = BLOCK_DATA[blockID]
  271.                    
  272.                     local colorMin = blockTypeData[IDX_COLORMIN]
  273.                     local colorMax = blockTypeData[IDX_COLORMAX]
  274.                     math.randomseed((chunkPos.X*4.3 + chunkPos.Y*7.2 + chunkPos.Z*1.9)*CHUNK_WIDTH + gridIndex)
  275.                     local color = colorMax and colorMin:Lerp(colorMax, math.random()) or colorMin
  276.  
  277.                     local p1 = centerPos + VERT_OFFS_1
  278.                     local p2 = centerPos + VERT_OFFS_2
  279.                     local p3 = centerPos + VERT_OFFS_3
  280.                     local p4 = centerPos + VERT_OFFS_4
  281.                     local p5 = centerPos - VERT_OFFS_4
  282.                     local p6 = centerPos - VERT_OFFS_3
  283.                     local p7 = centerPos - VERT_OFFS_2
  284.                     local p8 = centerPos - VERT_OFFS_1
  285.  
  286.                     --front face
  287.                     local drawFace
  288.                     if X == POS_LIMIT then
  289.                         local chunkNeighbor = chunkNeighbors[1]
  290.                         if not chunkNeighbor or buffer.readu8(chunkNeighbor[IDX_VOXELS], YZindex) == 0 then
  291.                             drawFace = true
  292.                         end
  293.                     elseif buffer.readu8(voxels, gridIndex+1) == 0 then
  294.                         drawFace = true
  295.                     end
  296.  
  297.                     if drawFace then
  298.                         DrawFace(editMesh, color, p2,p4,p6,p8, FRONT_FACE)
  299.                     end
  300.                     --
  301.  
  302.                     --back face
  303.                     local drawFace
  304.                     if X == 0 then
  305.                         local chunkNeighbor = chunkNeighbors[2]
  306.                         if not chunkNeighbor or buffer.readu8(chunkNeighbor[IDX_VOXELS], POS_LIMIT+YZindex) == 0 then
  307.                             drawFace = true
  308.                         end
  309.                     elseif buffer.readu8(voxels, gridIndex-1) == 0 then
  310.                         drawFace = true
  311.                     end
  312.  
  313.                     if drawFace then
  314.                         DrawFace(editMesh, color, p1,p3,p5,p7, BACK_FACE)
  315.                     end
  316.                     --
  317.  
  318.                     --top face
  319.                     local drawFace
  320.                     if Y == POS_LIMIT then
  321.                         local chunkNeighbor = chunkNeighbors[3]
  322.                         if not chunkNeighbor or buffer.readu8(chunkNeighbor[IDX_VOXELS], Xindex + Zindex) == 0 then
  323.                             drawFace = true
  324.                         end
  325.                     elseif buffer.readu8(voxels, Xindex + (Yindex+CHUNK_WIDTH) + Zindex) == 0 then
  326.                         drawFace = true
  327.                     end
  328.  
  329.                     if drawFace then
  330.                         DrawFace(editMesh, color, p5,p6,p7,p8, TOP_FACE)
  331.                     end
  332.                     --
  333.  
  334.                     --bottom face
  335.                     local drawFace
  336.                     if Y == 0 then
  337.                         local chunkNeighbor = chunkNeighbors[4]
  338.                         if not chunkNeighbor or buffer.readu8(chunkNeighbor[IDX_VOXELS], Xindex + (POS_LIMIT*CHUNK_WIDTH) + Zindex) == 0 then
  339.                             drawFace = true
  340.                         end
  341.                     elseif buffer.readu8(voxels, Xindex + (Yindex-CHUNK_WIDTH) + Zindex) == 0 then
  342.                         drawFace = true
  343.                     end
  344.  
  345.                     if drawFace then
  346.                         DrawFace(editMesh, color, p1,p2,p3,p4, BOTTOM_FACE)
  347.                     end
  348.                     --
  349.  
  350.                     --right face
  351.                     local drawFace
  352.                     if Z == POS_LIMIT then
  353.                         local chunkNeighbor = chunkNeighbors[5]
  354.                         if not chunkNeighbor or buffer.readu8(chunkNeighbor[IDX_VOXELS], Xindex + Yindex) == 0 then
  355.                             drawFace = true
  356.                         end
  357.                     elseif buffer.readu8(voxels, Xindex + Yindex + (Zindex+CHUNK_WIDTH_SQUARED)) == 0 then
  358.                         drawFace = true
  359.                     end
  360.  
  361.                     if drawFace then
  362.                         DrawFace(editMesh, color, p3,p4,p7,p8, RIGHT_FACE)
  363.                     end
  364.                     --
  365.  
  366.                     --left face
  367.                     local drawFace
  368.                     if Z == 0 then
  369.                         local chunkNeighbor = chunkNeighbors[6]
  370.                         if not chunkNeighbor or buffer.readu8(chunkNeighbor[IDX_VOXELS], Xindex + Yindex + (POS_LIMIT*CHUNK_WIDTH_SQUARED)) == 0 then
  371.                             drawFace = true
  372.                         end
  373.                     elseif buffer.readu8(voxels, Xindex + Yindex + (Zindex-CHUNK_WIDTH_SQUARED)) == 0 then
  374.                         drawFace = true
  375.                     end
  376.  
  377.                     if drawFace then
  378.                         DrawFace(editMesh, color, p1,p2,p5,p6, LEFT_FACE)
  379.                     end
  380.                     --
  381.                 end
  382.             end
  383.         end
  384.     end
  385.  
  386.     if replaceEditMesh then
  387.         chunk[IDX_EDITMESH] = editMesh
  388.         editMesh.Parent = oldEditMesh.Parent
  389.         oldEditMesh:Destroy()
  390.     end
  391.  
  392.     chunkMeshTime[1] += os.clock() - clock
  393.     chunkMeshTime[2] += 1
  394. end
  395.  
  396. local function GenerateStructure(at, strucID, createChunks, writeAir)
  397.     local structure = STRUCTURE_DATA[strucID]
  398.     local size = structure[1]
  399.     local data = structure[2]
  400.  
  401.     local sizeX = size.X
  402.     local sizeY = size.Y
  403.     local sizeZ = size.Z
  404.     local sizeXY = sizeX*sizeY
  405.    
  406.     for Z = 0, sizeZ-1 do
  407.         local Zindex = Z * sizeXY
  408.         for Y = 0, sizeY-1 do
  409.             local YZindex = Zindex + (Y * sizeX)
  410.             for X = 0, sizeX-1 do
  411.                 local blockID = buffer.readu8(data, YZindex+X)
  412.  
  413.                 if blockID == 0 and not writeAir then
  414.                     continue
  415.                 end
  416.  
  417.                 local vectorPos = at+Vector3.new(X,Y,Z)
  418.                 local chunkPos = vectorPos // CHUNK_WIDTH
  419.                 local chunk = chunks[chunkPos]
  420.                
  421.                 if not chunk then
  422.                     if not createChunks then
  423.                         continue
  424.                     end
  425.                     chunk = AddChunk(chunkPos)
  426.                 end
  427.  
  428.                 local offset = vectorPos-(chunkPos*CHUNK_WIDTH)
  429.                 buffer.writeu8(chunk[IDX_VOXELS], Flatten(offset.X, offset.Y, offset.Z), blockID)
  430.             end
  431.         end
  432.     end
  433. end
  434.  
  435. local function GetVoxelType(voxelY, noiseHeight)
  436.     if voxelY < noiseHeight-55 then
  437.         return 9
  438.     elseif voxelY < noiseHeight-10 then
  439.         return 3 --stone
  440.     elseif voxelY < noiseHeight-1.5 then
  441.         return 5 --dirt
  442.     elseif noiseHeight <= OCEAN_HEIGHT then
  443.         return 2 --water
  444.     elseif noiseHeight < OCEAN_HEIGHT + 1.8 then
  445.         return 4 --sand
  446.     elseif voxelY > (NOISE_HEIGHT*0.55) and voxelY > noiseHeight-3 then
  447.         return 6 --snow
  448.     else
  449.         return 1 --grass
  450.     end
  451. end
  452.  
  453. local function GenerateChunk(x,y,z)
  454.     local clock = os.clock()
  455.    
  456.     local trueChunkX = x*CHUNK_WIDTH
  457.     local trueChunkY = y*CHUNK_WIDTH
  458.     local trueChunkZ = z*CHUNK_WIDTH
  459.    
  460.     local chunkPos = Vector3.new(x,y,z)
  461.     local maxY = trueChunkY+POS_LIMIT
  462.     local chunk = chunks[chunkPos]
  463.     local voxels = chunk and chunk[IDX_VOXELS]
  464.  
  465.     for Z = 0, POS_LIMIT do
  466.         local trueVoxelZ = trueChunkZ+Z
  467.         local indexZ = Z*CHUNK_WIDTH_SQUARED
  468.  
  469.         for X = 0, POS_LIMIT do
  470.             local trueVoxelX = trueChunkX+X
  471.            
  472.             local noise = GenerateNoise(trueVoxelZ, trueVoxelX)
  473.             local noiseHeight = math.max(noise * NOISE_HEIGHT, OCEAN_HEIGHT)
  474.  
  475.             if noiseHeight >= trueChunkY then
  476.                 if not chunk then
  477.                     chunk = AddChunk(chunkPos)
  478.                     voxels = chunk[IDX_VOXELS]
  479.                 end
  480.  
  481.                 local maxHeight = math.min(math.floor(noiseHeight), maxY) - trueChunkY
  482.                 local voxelType
  483.                
  484.                 for Y = 0, maxHeight do
  485.                     voxelType = GetVoxelType(trueChunkY + Y, noiseHeight)
  486.                     buffer.writeu8(voxels, X + (Y*CHUNK_WIDTH) + indexZ, voxelType)
  487.                 end
  488.                
  489.                 if voxelType == 1 and math.random(TREE_CHANCE) == 1 then
  490.                     GenerateStructure(Vector3.new(trueVoxelX-2, trueChunkY+maxHeight+1, trueVoxelZ-2), 2, true)
  491.                 end
  492.             end
  493.         end
  494.     end
  495.    
  496.     chunkBuildTime[1] += os.clock() - clock
  497.     chunkBuildTime[2] += 1
  498.    
  499.     return chunk
  500. end
  501.  
  502. --
  503.  
  504. module.RemoveVoxelsInRange = function(from, range)
  505.     local radius = range/2
  506.     local radiusSquared = radius^2
  507.     local radiusFloored = math.floor(radius)
  508.  
  509.     for Z = -radiusFloored, radiusFloored do
  510.         local zSquared = Z^2
  511.         local yRange = math.floor(math.sqrt(radiusSquared - zSquared))
  512.  
  513.         for Y = -yRange, yRange do
  514.             local xRange = math.floor(math.sqrt(radiusSquared - (zSquared + Y^2)))
  515.  
  516.             for X = -xRange, xRange do
  517.                 local vectorPos = from+Vector3.new(X,Y,Z)
  518.                 local chunkPos = vectorPos // CHUNK_WIDTH
  519.                 local chunk = chunks[chunkPos]
  520.  
  521.                 if chunk then
  522.                     local offset = vectorPos-(chunkPos*CHUNK_WIDTH)
  523.                     buffer.writeu8(chunk[IDX_VOXELS], Flatten(offset.X, offset.Y, offset.Z), 0)
  524.                 end
  525.             end
  526.         end
  527.     end
  528.  
  529.     for _, chunk in GetChunksInRange(from, radius+.5) do
  530.         if IsBufferEmpty(chunk[IDX_VOXELS]) then
  531.             RemoveChunk(chunk[IDX_CHUNKPOS])
  532.             continue
  533.         end
  534.         --RevealChunk(chunk)
  535.         task.defer(UpdateChunk, chunk)
  536.     end
  537. end
  538.  
  539. module.AddVoxelsInRange = function(from, range, blockID)
  540.     local radius = range/2
  541.     local radiusSquared = radius^2
  542.     local radiusFloored = math.floor(radius)
  543.  
  544.     local touchingChunks = GetChunksInRange(from, radius+.5, true)
  545.  
  546.     for Z = -radiusFloored, radiusFloored do
  547.         local zSquared = Z^2
  548.         local yRange = math.floor(math.sqrt(radiusSquared - zSquared))
  549.  
  550.         for Y = -yRange, yRange do
  551.             local xRange = math.floor(math.sqrt(radiusSquared - (zSquared + Y^2)))
  552.  
  553.             for X = -xRange, xRange do
  554.                 local vectorPos = from+Vector3.new(X,Y,Z)
  555.                 local chunkPos = vectorPos // CHUNK_WIDTH
  556.                 local chunk = chunks[chunkPos]
  557.  
  558.                 local offset = vectorPos-(chunkPos*CHUNK_WIDTH)
  559.                 buffer.writeu8(chunk[IDX_VOXELS], Flatten(offset.X, offset.Y, offset.Z), blockID)
  560.             end
  561.         end
  562.     end
  563.  
  564.     for _, chunk in touchingChunks do
  565.         --RevealChunk(chunk)
  566.         task.defer(UpdateChunk, chunk)
  567.     end
  568. end
  569.  
  570. module.GetStats = function()
  571.     local chunkCount = 0
  572.     local voxelCount = 0
  573.     for _, chunk in chunks do
  574.         chunkCount += 1
  575.     end
  576.  
  577.     return {
  578.         chunkAmount = chunkCount,
  579.         voxelAmount = voxelCount,
  580.         averageChunkMeshTime = `{math.floor((chunkMeshTime[1]/chunkMeshTime[2])*10000000)/10000} ms`,
  581.         averageChunkBuildTime = `{math.floor((chunkBuildTime[1]/chunkBuildTime[2])*10000000)/10000} ms`,
  582.         bench
  583.     }
  584. end
  585.  
  586. module.AddVoxel = function(pos, ID)
  587.     local chunkPos = pos // CHUNK_WIDTH
  588.     local chunk = chunks[chunkPos] or AddChunk(chunkPos)
  589.  
  590.     local offset = pos-(chunkPos*CHUNK_WIDTH)
  591.     buffer.writeu8(chunk[IDX_VOXELS], Flatten(offset.X, offset.Y, offset.Z), ID)
  592.     UpdateChunk(chunk)
  593. end
  594.  
  595. module.RemoveVoxel = function(pos)
  596.     local chunkPos = pos // CHUNK_WIDTH
  597.     local chunk = chunks[chunkPos]
  598.  
  599.     if chunk then
  600.         local offset = pos-(chunkPos*CHUNK_WIDTH)
  601.         buffer.writeu8(chunk[IDX_VOXELS], Flatten(offset.X, offset.Y, offset.Z), 0)
  602.         UpdateChunk(chunk)
  603.     end
  604. end
  605.  
  606. module.PlaceStructure = function(at, strucID)
  607.     local size = STRUCTURE_DATA[strucID][1]
  608.     local touchingChunks = GetChunksInBounds(at + size//2, size+Vector3.one, true)
  609.    
  610.     GenerateStructure(at, strucID)
  611.  
  612.     for _, chunk in touchingChunks do
  613.         --RevealChunk(chunk)
  614.         task.defer(UpdateChunk, chunk)
  615.     end
  616. end
  617.  
  618. module.Raycast = function(from, dir, res, inside)
  619.     local length = dir.Magnitude
  620.     local unit = dir/length
  621.     local step = unit*res
  622.  
  623.     for i = 0,length/res do
  624.         local halfFrom = from + Vector3Half
  625.         local pos = (halfFrom + (step*i)) // 1
  626.  
  627.         local chunkPos = pos // CHUNK_WIDTH
  628.         local chunk = chunks[chunkPos]
  629.  
  630.         if chunk then
  631.             local offset = pos-(chunkPos*CHUNK_WIDTH)
  632.             if buffer.readu8(chunk[IDX_VOXELS], Flatten(offset.X, offset.Y, offset.Z)) ~= 0 then
  633.                 return inside and pos or (halfFrom + (step*(i-1))) // 1
  634.             end
  635.         end
  636.     end
  637. end
  638.  
  639. module.RevealChunksInRange = function(at, range)
  640.     for _, chunk in GetChunksInRange(at, range) do
  641.         RevealChunk(chunk)
  642.     end
  643. end
  644.  
  645. module.Chunks = chunks
  646.  
  647. module.UpdateChunk = UpdateChunk
  648.  
  649. module.GenerateChunk = GenerateChunk
  650.  
  651. return module
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement