local RunService = game:GetService("RunService") local IS_STUDIO = RunService:IsStudio() local ENABLE_STUDIO_LOG = false local module = {} -- Prints only when running in Studio (avoids noisy live logs) function module.StudioLog(...: any) if not IS_STUDIO or not ENABLE_STUDIO_LOG then return end print(...) end function module.StudioWarn(...: any) if not IS_STUDIO or not ENABLE_STUDIO_LOG then return end warn(...) end function module.isNaN(n: number): boolean -- NaN is never equal to itself return n ~= n end function module.isInf(n: number): boolean -- Number could be -inf or +inf return math.abs(n) == math.huge end function module.BlockPosStringToCoords(s: string): Vector3 -- a,b,c local split = string.split(s,",") return Vector3.new(tonumber(split[1]), tonumber(split[2]), tonumber(split[3])) end function module.RotationStringToNormalId(s: string): Enum.NormalId if not s then return Enum.NormalId.Front end if s == "f" then return Enum.NormalId.Front end if s == "b" then return Enum.NormalId.Back end if s == "l" then return Enum.NormalId.Left end if s == "r" then return Enum.NormalId.Right end if s == "t" then return Enum.NormalId.Top end if s == "b" then return Enum.NormalId.Bottom end warn("Could not convert",s,"to Enum.NormalId") return Enum.NormalId.Front end -- chunk size 8x8x8 relative block indexs 1-8 function module.GlobalBlockPosToRelative(x: number,y:number,z:number) return x%8,y%8,z%8 end function module.ChunkPosToCFrame(chunk: Vector3, block: Vector3): CFrame return CFrame.new( CFrame.new( (32*chunk.X)+(block.X*4)-18, (32*chunk.Y)+(block.Y*4)-18, (32*chunk.Z)+(block.Z*4)-18 ).Position ) end return module