Can you edit this code so of there is a big drop and change of height like a cliff, it creates a waterfall. Also optimize it as much as possibile without taking ANY functionality away.

Module: -- GMFluxContainer ModuleScript

local GMFluxContainer = {}
GMFluxContainer.__index = GMFluxContainer

-- FluxCell constants (Equivalent to the enum in your original code)
GMFluxContainer.FluxCell = {
	Height = 0,   -- Height.rgba
	Depth = 1,    -- Depth.rgba
	FluxLD = 2,   -- FluxLeft.rg, FluxDown.ba
	FluxRU = 3,   -- FluxRight.rg, FluxUp.ba
}

-- Constructor
function GMFluxContainer.new(texSize, position, cellSize, parameters)
	local self = setmetatable({}, GMFluxContainer)

	-- Simulation parameters
	self.fluxStrength = parameters.fluxStrength or 0.250
	self.fluxAtten = parameters.fluxAtten or 0.975
	self.fluxSpill = parameters.fluxSpill or 0.0

	self.texSize = texSize or 64 -- Adjust as needed
	self.texSubCount = 2
	self.texTotalCount = self.texSubCount * self.texSubCount
	self.cellSize = cellSize or 2 -- Default cell size in world units

	-- Position of the fluid grid in the world
	self.position = position or Vector3.new(0, 0, 0)

	-- Initialize data structures
	self.cells = {} -- 3D array: cells[x][y][component]
	for x = 1, self.texSize do
		self.cells[x] = {}
		for y = 1, self.texSize do
			self.cells[x][y] = {}
			-- Initialize components
			self.cells[x][y][GMFluxContainer.FluxCell.Height] = 0
			self.cells[x][y][GMFluxContainer.FluxCell.Depth] = 0
			self.cells[x][y][GMFluxContainer.FluxCell.FluxLD] = {left = 0, down = 0}
			self.cells[x][y][GMFluxContainer.FluxCell.FluxRU] = {right = 0, up = 0}
		end
	end

	-- Encoding parameters (included for completeness)
	self.encodeBound = 256

	-- Active cell variables (not used in this port)
	self.cellActive = -1
	self.cellActiveX = 0
	self.cellActiveY = 0

	return self
end

-- Encoding functions (included for completeness)
-- (These functions are not essential in this simplified port since we're working directly with numerical values.)

-- Function to perform a step of the flux simulation
function GMFluxContainer:stepFlux()
	-- Create a copy of the current cells
	local newCells = {}
	for x = 1, self.texSize do
		newCells[x] = {}
		for y = 1, self.texSize do
			newCells[x][y] = {}
			-- Copy height and depth
			newCells[x][y][GMFluxContainer.FluxCell.Height] = self.cells[x][y][GMFluxContainer.FluxCell.Height]
			newCells[x][y][GMFluxContainer.FluxCell.Depth] = self.cells[x][y][GMFluxContainer.FluxCell.Depth]
			-- Initialize fluxes
			newCells[x][y][GMFluxContainer.FluxCell.FluxLD] = {left = 0, down = 0}
			newCells[x][y][GMFluxContainer.FluxCell.FluxRU] = {right = 0, up = 0}
		end
	end

	-- Compute fluxes
	for x = 1, self.texSize do
		for y = 1, self.texSize do
			local cell = self.cells[x][y]
			local depth = cell[GMFluxContainer.FluxCell.Depth]
			local height = cell[GMFluxContainer.FluxCell.Height]
			local totalHeight = height + depth

			-- Neighbor positions
			local neighbors = {
				left = (x > 1) and self.cells[x - 1][y] or nil,
				right = (x < self.texSize) and self.cells[x + 1][y] or nil,
				down = (y > 1) and self.cells[x][y - 1] or nil,
				up = (y < self.texSize) and self.cells[x][y + 1] or nil,
			}

			-- Initialize fluxes
			local fluxes = {left = 0, right = 0, down = 0, up = 0}

			-- Compute fluxes to neighbors
			for dir, neighbor in pairs(neighbors) do
				if neighbor then
					local neighborTotalHeight = neighbor[GMFluxContainer.FluxCell.Height] + neighbor[GMFluxContainer.FluxCell.Depth]
					-- Get the appropriate flux component
					local fluxComponent
					if dir == 'left' or dir == 'down' then
						fluxComponent = cell[GMFluxContainer.FluxCell.FluxLD][dir]
					else -- 'right' or 'up'
						fluxComponent = cell[GMFluxContainer.FluxCell.FluxRU][dir]
					end
					local flux = self.fluxAtten * fluxComponent + self.fluxStrength * math.max(0, totalHeight - neighborTotalHeight)
					fluxes[dir] = flux
				end
			end

			-- Limit total flux to available depth
			local totalFluxOut = fluxes.left + fluxes.right + fluxes.down + fluxes.up
			local maxFlux = math.max(0, depth - self.fluxSpill)
			if totalFluxOut > maxFlux and totalFluxOut > 0 then
				local scale = maxFlux / totalFluxOut
				fluxes.left = fluxes.left * scale
				fluxes.right = fluxes.right * scale
				fluxes.down = fluxes.down * scale
				fluxes.up = fluxes.up * scale
			end

			-- Update fluxes in newCells
			newCells[x][y][GMFluxContainer.FluxCell.FluxLD].left = fluxes.left
			newCells[x][y][GMFluxContainer.FluxCell.FluxRU].right = fluxes.right
			newCells[x][y][GMFluxContainer.FluxCell.FluxLD].down = fluxes.down
			newCells[x][y][GMFluxContainer.FluxCell.FluxRU].up = fluxes.up
		end
	end

	-- Update cells
	self.cells = newCells
end

-- Function to perform a depth update step
function GMFluxContainer:stepDepth()
	-- Create a copy of the current cells
	local newCells = {}
	for x = 1, self.texSize do
		newCells[x] = {}
		for y = 1, self.texSize do
			newCells[x][y] = {}
			-- Copy height
			newCells[x][y][GMFluxContainer.FluxCell.Height] = self.cells[x][y][GMFluxContainer.FluxCell.Height]
			-- Depth will be updated
			newCells[x][y][GMFluxContainer.FluxCell.Depth] = 0
			-- Copy fluxes
			newCells[x][y][GMFluxContainer.FluxCell.FluxLD] = self.cells[x][y][GMFluxContainer.FluxCell.FluxLD]
			newCells[x][y][GMFluxContainer.FluxCell.FluxRU] = self.cells[x][y][GMFluxContainer.FluxCell.FluxRU]
		end
	end

	-- Update depth
	for x = 1, self.texSize do
		for y = 1, self.texSize do
			local cell = self.cells[x][y]
			local depth = cell[GMFluxContainer.FluxCell.Depth]
			local fluxOut = cell[GMFluxContainer.FluxCell.FluxLD].left + cell[GMFluxContainer.FluxCell.FluxLD].down + cell[GMFluxContainer.FluxCell.FluxRU].right + cell[GMFluxContainer.FluxCell.FluxRU].up
			local fluxIn = 0

			-- Flux in from neighbors
			if x > 1 then
				fluxIn = fluxIn + self.cells[x - 1][y][GMFluxContainer.FluxCell.FluxRU].right
			end
			if x < self.texSize then
				fluxIn = fluxIn + self.cells[x + 1][y][GMFluxContainer.FluxCell.FluxLD].left
			end
			if y > 1 then
				fluxIn = fluxIn + self.cells[x][y - 1][GMFluxContainer.FluxCell.FluxRU].up
			end
			if y < self.texSize then
				fluxIn = fluxIn + self.cells[x][y + 1][GMFluxContainer.FluxCell.FluxLD].down
			end

			-- Update depth
			local newDepth = depth - fluxOut + fluxIn
			newDepth = math.max(newDepth, 0)
			newCells[x][y][GMFluxContainer.FluxCell.Depth] = newDepth
		end
	end

	-- Update cells
	self.cells = newCells
end

-- Function to handle collisions (Advanced collisions)
function GMFluxContainer:handleCollisions(collidableObjects)
	for x = 1, self.texSize do
		for y = 1, self.texSize do
			local cellWorldPosition = self.position + Vector3.new((x - 1) * self.cellSize, 0, (y - 1) * self.cellSize)
			local cell = self.cells[x][y]
			local depth = cell[GMFluxContainer.FluxCell.Depth]
			local height = cell[GMFluxContainer.FluxCell.Height]
			local fluidSurfaceY = height + depth

			-- Check for collisions with collidable objects at this position
			for _, obj in ipairs(collidableObjects) do
				local objPos = obj.Position
				local objSize = obj.Size / 2
				if math.abs(objPos.X - cellWorldPosition.X) <= objSize.X and math.abs(objPos.Z - cellWorldPosition.Z) <= objSize.Z then
					local objTopY = objPos.Y + objSize.Y
					-- If object is higher than fluid height, adjust fluid depth
					if objTopY > height then
						local maxDepth = math.max(0, objTopY - height)
						cell[GMFluxContainer.FluxCell.Depth] = math.min(cell[GMFluxContainer.FluxCell.Depth], maxDepth)
					end
				end
			end
		end
	end
end

-- Functions to manipulate cells
-- Fill a cell with a value
function GMFluxContainer:cellEncodeFill(fluxCell, value)
	for x = 1, self.texSize do
		for y = 1, self.texSize do
			self.cells[x][y][fluxCell] = value
		end
	end
end

-- Encode terrain heightmap
function GMFluxContainer:cellEncodeHeightmap(heightmap, factor)
	for x = 1, self.texSize do
		for y = 1, self.texSize do
			local height = heightmap[x][y] * factor
			self.cells[x][y][GMFluxContainer.FluxCell.Height] = height
		end
	end
end

-- Add fluid at a specific position
function GMFluxContainer:addFluid(x, y, amount)
	if x >= 1 and x <= self.texSize and y >= 1 and y <= self.texSize then
		self.cells[x][y][GMFluxContainer.FluxCell.Depth] = self.cells[x][y][GMFluxContainer.FluxCell.Depth] + amount
	end
end

-- Get fluid depth at a position
function GMFluxContainer:getFluidDepthAt(x, y)
	if x >= 1 and x <= self.texSize and y >= 1 and y <= self.texSize then
		return self.cells[x][y][GMFluxContainer.FluxCell.Depth]
	else
		return 0
	end
end

return GMFluxContainer


Script:-- MainSimulation Script

local GMFluxContainer = require(game.ServerScriptService.GMFluxContainer)

-- Simulation parameters
local texSize = 128 -- Adjust as needed (reasonable sizes: 64, 128)
local cellSize = 2 -- Size of each cell in world units
local simPosition = Vector3.new(50, 0, 0) -- Adjust to move the fluid grid

-- Controllable simulation parameters
local simulationParameters = {
	fluxStrength = 0.25, -- Controls the fluid flow strength
	fluxAtten = 0.975,   -- Fluid attenuation
	fluxSpill = 0.0,     -- Fluid spill threshold
	simulationSpeed = 0.03, -- Controls the simulation step interval
	fluidGenerationRate = 100 -- Controls the rate at which fluid is added per source per step
}

-- Create an instance of the simulation container
local sim = GMFluxContainer.new(texSize, simPosition, cellSize, simulationParameters)

-- Function to generate the terrain heightmap using raycasts
local function generateTerrainHeightmap(sim)
	local heightmap = {}
	local raycastParams = RaycastParams.new()
	raycastParams.FilterDescendantsInstances = {} -- Add parts to ignore if any
	raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
	raycastParams.IgnoreWater = false

	local basePosition = sim.position

	-- Predefine the maximum expected terrain height
	local maxTerrainHeight = 1000 -- Adjust based on your terrain

	for x = 1, sim.texSize do
		heightmap[x] = {}
		for y = 1, sim.texSize do
			local worldX = basePosition.X + (x - 1) * sim.cellSize
			local worldZ = basePosition.Z + (y - 1) * sim.cellSize
			local origin = Vector3.new(worldX, maxTerrainHeight, worldZ)
			local direction = Vector3.new(0, -maxTerrainHeight - 100, 0)
			local raycastResult = workspace:Raycast(origin, direction, raycastParams)

			local height
			if raycastResult then
				height = raycastResult.Position.Y
			else
				height = 0 -- No hit, terrain is below minimum expected height
			end

			heightmap[x][y] = height
		end
	end

	return heightmap
end

-- Generate the terrain heightmap with raycasts
local heightmap = generateTerrainHeightmap(sim)

-- Set the terrain heightmap in the simulation
sim:cellEncodeHeightmap(heightmap, 1) -- Height factor is 1

-- Create parts to visualize the simulation
local partsGrid = {}
local basePosition = sim.position

for x = 1, sim.texSize do
	partsGrid[x] = {}
	for y = 1, sim.texSize do
		local part = Instance.new("Part")
		part.Size = Vector3.new(sim.cellSize, 0.1, sim.cellSize) -- Initial minimal size
		local height = sim.cells[x][y][GMFluxContainer.FluxCell.Height]
		part.Position = basePosition + Vector3.new((x - 1) * sim.cellSize, height + 0.05, (y - 1) * sim.cellSize)
		part.Anchored = true
		part.Material = Enum.Material.Slate -- Terrain material
		part.Color = Color3.fromRGB(139, 69, 19) -- Brown color for terrain
		part.Transparency = 0
		part.Parent = workspace
		partsGrid[x][y] = part
	end
end

-- List of collidable objects (Advanced collisions)
-- Create a Folder in Workspace named 'CollidableObjects' and add your collidable parts to it
local collidableObjectsFolder = workspace:FindFirstChild("CollidableObjects")
local collidableObjects = {}
if collidableObjectsFolder then
	collidableObjects = collidableObjectsFolder:GetChildren()
end

-- List of water sources
local waterSources = {
	{x = math.floor(sim.texSize / 2), y = math.floor(sim.texSize / 2)},
	-- Add more sources as needed
}

-- Simulation loop
while true do
	-- Add fluid at specified water sources
	for _, source in ipairs(waterSources) do
		sim:addFluid(source.x, source.y, simulationParameters.fluidGenerationRate)
	end

	-- Perform simulation steps
	sim:stepFlux()
	sim:stepDepth()

	-- Handle collisions
	sim:handleCollisions(collidableObjects)

	-- Update visualization
	for x = 1, sim.texSize do
		for y = 1, sim.texSize do
			local part = partsGrid[x][y]
			local depth = sim:getFluidDepthAt(x, y)
			local height = sim.cells[x][y][GMFluxContainer.FluxCell.Height]

			if depth > 0 then
				-- Scale the part to represent the fluid depth
				part.Size = Vector3.new(sim.cellSize, depth, sim.cellSize)
				part.Position = basePosition + Vector3.new((x - 1) * sim.cellSize, height + depth / 2, (y - 1) * sim.cellSize)
				-- Set material and color for water
				part.Material = Enum.Material.Water
				-- Color intensity based on depth
				local colorIntensity = math.clamp(depth / 10, 0, 1)
				part.Color = Color3.fromRGB(0, 0, 255 * colorIntensity)
				part.Transparency = 0.3 -- Less transparent with more depth
			else
				-- Minimal size for empty cells
				part.Size = Vector3.new(sim.cellSize, 0.1, sim.cellSize)
				part.Position = basePosition + Vector3.new((x - 1) * sim.cellSize, height + 0.05, (y - 1) * sim.cellSize)
				-- Set material and color for terrain
				part.Material = Enum.Material.Slate -- Terrain material
				part.Color = Color3.fromRGB(139, 69, 19) -- Brown color for terrain
				part.Transparency = 0
			end
		end
	end

	-- Wait for the next simulation step
	wait(simulationParameters.simulationSpeed)
end