local K=require(script.GenerationConfig)local V=require(script.Parent:WaitForChild("\086\111\108\117\109\101\071\114\105\100"))local S=require(script.GridCell)local e=K.worldScale local I=K.cellsPerAxis local X=K.isoLevel local W=K.terrainAmplitude local T=K.terrainFrequency local v=K.oreAmplitude local O=K.oreFrequency local w=(Random.new()):NextNumber(-100000000.0,100000000.0)local a=V.new()for K=1,I,1 do for V=1,I,1 do for e=1,I,1 do local X=math.clamp(math.noise((w+K*T)/W,(w+V*T)/W,(w+e*T)/W),-0.5,.5)local B=math.clamp(math.noise((w+V*O)/v,(w+K*O)/v,(w+e*O)/v),-0.5,.5)local o=S.new(K,V,e,X+.5)if B<.4 then o.cellType="\114\111\099\107"elseif B<.4999 then o.cellType="\108\105\103\104\116\082\111\099\107"elseif B>=.4999 then o.cellType="\100\105\097\109\111\110\100"end if K==1 or V==1 or e==1 or K==I or V==I or e==I then o.cellType="\119\111\114\108\100\066\111\114\100\101\114"end a:addCell(K,V,e,o)end end end for K=1,I,1 do for V=1,I,1 do a[K][V][1].w=1 a[K][V][I].w=1 end end for K=1,I,1 do for V=1,I,1 do a[1][V][K].w=1 a[I][V][K].w=1 end end for K=1,I,1 do for V=1,I,1 do a[K][1][V].w=1 a[K][I][V].w=1 end end for K,V in pairs(a)do for K,V in pairs(V)do for K,V in pairs(V)do V:update()end end end function explosion(K,V)local S=K/e local I=Vector3.new(math.floor(S.x+.5),math.floor(S.y+.5),math.floor(S.z+.5))local X=a[I.x][I.y][I.z]if X then local K=X:getCellsInRadius(V)for K,V in pairs(K)do V:destroy(true)end local S={}for K,V in pairs(X:getCellsInRadius(V+2))do if not S[V]then V:update()S[V]=true end end end end local B=game.Players.LocalPlayer local o=B.Character or B.CharacterAdded:wait()and B.Character local p=8 for K,V in pairs(a)do for V,S in pairs(V)do for S,I in pairs(S)do local W=true for e=1,p,1 do if not a[K][V+e][S]or a[K][V+e][S].w>=X then W=false end end if I.w>X and W then o.HumanoidRootPart.CFrame=CFrame.new(Vector3.new(I.x,I.y+4,I.z)*e)break end end end end return explosion
--Dependencies
local GenerationConfig = require(script.GenerationConfig)
local VolumeGrid = require(script.Parent:WaitForChild("VolumeGrid"))
local GridCell = require(script.GridCell)

--Config values
local WORLD_SCALE = GenerationConfig.worldScale
local CELLS_PER_AXIS = GenerationConfig.cellsPerAxis
local ISO_LEVEL = GenerationConfig.isoLevel
	
local TERRAIN_AMPLITUDE = GenerationConfig.terrainAmplitude
local TERRAIN_FREQUENCY = GenerationConfig.terrainFrequency
local ORE_AMPLITUDE = GenerationConfig.oreAmplitude
local ORE_FREQUENCY = GenerationConfig.oreFrequency

--Randomizes the perlin noise grid
local NOISE_OFFSET = Random.new():NextNumber(-(10^8), 10^8)
local grid = VolumeGrid.new()

--Generate cell grid
for x = 1, CELLS_PER_AXIS do
	for y = 1, CELLS_PER_AXIS do
		for z = 1, CELLS_PER_AXIS do
			local noise = math.clamp(math.noise(
				(NOISE_OFFSET+x*TERRAIN_FREQUENCY)/TERRAIN_AMPLITUDE,
				(NOISE_OFFSET+y*TERRAIN_FREQUENCY)/TERRAIN_AMPLITUDE,
				(NOISE_OFFSET+z*TERRAIN_FREQUENCY)/TERRAIN_AMPLITUDE
			), -0.5, 0.5)
			
			local oreNoise = math.clamp(math.noise(
				(NOISE_OFFSET+y*ORE_FREQUENCY)/ORE_AMPLITUDE,
				(NOISE_OFFSET+x*ORE_FREQUENCY)/ORE_AMPLITUDE,
				(NOISE_OFFSET+z*ORE_FREQUENCY)/ORE_AMPLITUDE
			), -0.5, 0.5)
			
			local cell = GridCell.new(x,y,z, noise + 0.5)
			
			if oreNoise < 0.4 then
				cell.cellType = "rock"
			elseif oreNoise < 0.4999 then
				cell.cellType = "lightRock"
			elseif oreNoise >= 0.4999 then
				cell.cellType = "diamond"
			end
			
			if x == 1 or y == 1 or z == 1 or x == CELLS_PER_AXIS or y == CELLS_PER_AXIS or z == CELLS_PER_AXIS then
				cell.cellType = "worldBorder"
			end
			
			grid:addCell(x,y,z, cell)
		end
	end
end

--seal the edges
for x = 1, CELLS_PER_AXIS do
	for y = 1, CELLS_PER_AXIS do
		grid[x][y][1].w = 1
		grid[x][y][CELLS_PER_AXIS].w = 1
	end
end

for z = 1, CELLS_PER_AXIS do
	for y = 1, CELLS_PER_AXIS do
		grid[1][y][z].w = 1
		grid[CELLS_PER_AXIS][y][z].w = 1
	end
end

for x = 1, CELLS_PER_AXIS do
	for z = 1, CELLS_PER_AXIS do
		grid[x][1][z].w = 1
		grid[x][CELLS_PER_AXIS][z].w = 1
	end
end

--render the grid
for x, row in pairs(grid) do
	for y, column in pairs(row) do
		for z, cell in pairs(column) do
			cell:update()
		end
	end
end

--Digging, explosions
function explosion(position, radius)
	--format position
	local position = position / WORLD_SCALE
	local roundedPos = Vector3.new(math.floor(position.x+0.5), math.floor(position.y+0.5), math.floor(position.z+0.5))
	
	local origin = grid[roundedPos.x][roundedPos.y][roundedPos.z]
	
	if origin then
		local inRadius = origin:getCellsInRadius(radius)
		
		--Set the cell to non-existent, but don't update until all cells have been destroyed to reduce duplicate checks
		for _, cell in pairs(inRadius) do
			cell:destroy(true)
		end
		
		--Check all cells surrounding the explosion once
		local alreadyUpdated = {}
		
		for _, adjacent in pairs(origin:getCellsInRadius(radius+2)) do
			if not alreadyUpdated[adjacent] then
				adjacent:update()
				alreadyUpdated[adjacent] = true
			end
		end
	end
end

--Place the player in an open area
local player = game.Players.LocalPlayer
local character = player.Character or (player.CharacterAdded:wait() and player.Character)
local emptyAbove = 8

for x, row in pairs(grid) do
	for y, column in pairs(row) do
		for z, cell in pairs(column) do
			local isEmptyAbove = true
			
			for y2 = 1, emptyAbove do
				if not grid[x][y+y2][z] or grid[x][y+y2][z].w >= ISO_LEVEL then
					isEmptyAbove = false
				end
			end
			
			if cell.w > ISO_LEVEL and isEmptyAbove then
				character.HumanoidRootPart.CFrame = CFrame.new(Vector3.new(cell.x, cell.y + 4, cell.z)*WORLD_SCALE)
				break
			end
		end
	end
end

return explosion
