How do I make a table.property read-only?

  1. What do you want to achieve? I am making a module for kernelvox and I want to make some properties read only

  2. What is the issue? I don’t know how to do it

  3. What solutions have you tried so far? I looked through here and nothing is there

After that, you should include more details if you have any. Try to make your topic as descriptive as possible, so that it’s easier for people to help you!

--[[
	<SocialRainbow by VSCPlays (originally from @kernelvox (max96git))
	This rainbow module is based on @WinnersTakeAll (RyanLua)'s Shime
	I made this for @kernelvox as @bluebxrrybot and @commitblue said it's not enough for a community resource,
	I want to help @kernelvox succed

	please credit me @VSCPlays for the module and @kernelvox for the idea
]]

--// Services \\--
local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

--// Sanity Checks \\--
if not RunService:IsClient() then
	error(`Please use require({script:GetFullName()}) in the client`)
end

if not script:IsDescendantOf(ReplicatedStorage) then
	error(`Please put this in {ReplicatedStorage:GetFullName()}, where both the client and the server can access it`)
end

--// rainbow \\--
local rainbow = {}
rainbow.__index = rainbow

function rainbow.new(item:GuiObject, it:"Border" | "Text" | "Background", cooldown:number?)
	local self = setmetatable({}, rainbow)

	self.itemType = it -- should be read only
	self.item = item -- should be read only
	self.isPlaying = false
	self.isPaused = false
	self.finished = false
	self.cooldown = cooldown or 0 -- should be read only
	self.bindName = `RainbowEffect{self.item.Name}`

	return self
end

function rainbow:Play()
	self.isPlaying = true
	self.isPaused = false
	self.finished = false
	RunService:BindToRenderStep(self.bindName, Enum.RenderPriority.First.Value, function()
		local color = Color3.fromHSV((tick() * 4) % 1, 1, 1)
		if self.itemType == "Border" then
			self.item.BorderColor3 = color
		elseif self.itemType == "Text" then
			if self.item.ClassName == "TextBox" or "TextButton" or "TextLabel" then
				self.item.TextColor3 = color
			end
		elseif self.itemType == "Background" then
			self.item.BackgroundColor3 = color
		end
		task.wait(self.cooldown)
	end)
end

function rainbow:Pause(seconds:number)
	if self.finished or not self.isPlaying or self.isPaused then
		return
	end
	
	if seconds == self.cooldown then
		seconds += self.cooldown
	end
	
	seconds = math.clamp(seconds, .1, 10e4)

	self.isPlaying = false
	self.isPaused = true
	self.finished = false
	RunService:UnbindFromRenderStep(self.bindName)
	task.wait(seconds)
	self.isPlaying = true
	self.isPaused = false
	self.finished = false
	RunService:BindToRenderStep(self.bindName, self.Value, function()
		local color = Color3.fromHSV((tick() * 4) % 1, 1, 1)
		if self.itemType == "Border" then
			self.item.BorderColor3 = color
		elseif self.itemType == "Text" then
			if self.item.ClassName == "TextBox" or "TextButton" or "TextLabel" then
				self.item.TextColor3 = color
			end
		elseif self.itemType == "Background" then
			self.item.BackgroundColor3 = color
		end
		task.wait(self.cooldown)
	end)
end

function rainbow:Stop()
	self.isPlaying = false
	self.isPaused = false
	self.finished = true
	RunService:UnbindFromRenderStep(self.bindName)
end

return rainbow

Don’t say that I took the module’s code and modified it, I created the module myself for kernelvox’s <SocialRainbow (it’s codename is Pegasus)

so anyways I want to make certain properties read only so people can’t modify the properties without modifying the module’s code

There’s no way in native Lua/Luau to make read-only properties. The closest you can get to that is attaching a metatable to a table and using the __newindex metamethod:

local _t = {_readonly = 2} -- the actual internal table
local t = setmetatable({}, { -- table that would be exposed to the developer
   __newindex = function(self, property, newvalue)
       self = _t

       local value = rawget(self, `_{property}`) -- check if a property starting with an underscore exists
       if value ~= nil then
           error(`Cannot modify read-only property "{property}."`)
       elseif property:match("^_") then
           error(`Cannot modify read-only template "{property}."`)
       else
           rawset(self, `_{property}`, newvalue) -- set the property
       end
   end,

   __index = _t
})

t.readonly = 4 --> error
t._readonly = 3 --> also errors
3 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.