Release Notes for 517

Notes for Release 517

42 Likes

Client Difference Log

API Changes

Added Property string BasePart.MaterialVariant [NotReplicated]
Added Property Font TextBox.FontFace
Added Property Font TextButton.FontFace
Added Property Font TextLabel.FontFace

Added Function void LSPService:RegisterLSPCallback(Enum.LSPMethodType methodToOverride, Function callbackFunction) {RobloxScriptSecurity}
Added Function Dictionary TextService:GetFamilyInfoAsync(Content assetId) [Yields]

Added Enum LSPMethodType
	Added EnumItem LSPMethodType.Initialize : 1
	Added EnumItem LSPMethodType.Initialized : 2
	Added EnumItem LSPMethodType.CancelRequest : 3
	Added EnumItem LSPMethodType.TextDocument_didOpen : 4
	Added EnumItem LSPMethodType.TextDocument_didChange : 5
	Added EnumItem LSPMethodType.TextDocument_didClose : 6
	Added EnumItem LSPMethodType.TextDocument_foldingRange : 7
	Added EnumItem LSPMethodType.TextDocument_onTypeFormatting : 8
	Added EnumItem LSPMethodType.TextDocument_formatting : 9
	Added EnumItem LSPMethodType.TextDocument_rangeFormatting : 10
	Added EnumItem LSPMethodType.TextDocument_hover : 11
	Added EnumItem LSPMethodType.TextDocument_signatureHelp : 12
	Added EnumItem LSPMethodType.Workspace_DidChangeConfiguration : 13
	Added EnumItem LSPMethodType.ShutdownRequest : 14
	Added EnumItem LSPMethodType.Completion : 15
	Added EnumItem LSPMethodType.Declaration : 16
	Added EnumItem LSPMethodType.DocumentSymbols : 17
	Added EnumItem LSPMethodType.TextDocument_publishDiagnostics : 18
	Added EnumItem LSPMethodType.Window_showMessage : 19
	Added EnumItem LSPMethodType.Window_showMessageRequest : 20
	Added EnumItem LSPMethodType.Roblox_registerSyntaxCategories : 21
	Added EnumItem LSPMethodType.Roblox_signalQuiescence : 22
	Added EnumItem LSPMethodType.Roblox_syntaxHighlight : 23
	Added EnumItem LSPMethodType.Roblox_suggestExtraSelections : 24
	Added EnumItem LSPMethodType.Roblox_findExecutablePosition : 25
	Added EnumItem LSPMethodType.Roblox_findColor3 : 26

Added EnumItem Font.Unknown : 100

Removed Enum PacketPriority
	Removed EnumItem PacketPriority.IMMEDIATE_PRIORITY
	Removed EnumItem PacketPriority.HIGH_PRIORITY
	Removed EnumItem PacketPriority.MEDIUM_PRIORITY
	Removed EnumItem PacketPriority.LOW_PRIORITY

(Click here for a syntax highlighted version!)

16 Likes

Screenshot 2022-03-10 at 04.43.30

Whoot! What an addition to UI customisability. I’m curious to see how this will be implemented; how will it affect game-loading times and how failures to load will be dealt with.

Screenshot 2022-03-10 at 04.45.35

Does this mean that asset permissions are automatically edited when manually adding a sound? This sounds like something I’d like to be notified about.

Screenshot 2022-03-10 at 04.47.27

Well… now you’re just pampering me.

33 Likes

Would this be the same as this generic function I did?

function Module.TableCopy(Original) -- physical table duplication
	local Copy = {}
	if Original then -- if the source table came void, return {}
		for k, v in pairs(Original) do
			if type(v) == "table" then
				v = Module.TableCopy(v)
			end
			Copy[k] = v
		end
	end
	return Copy
end
2 Likes

Different in a couple of ways:

  • table.clone is a shallow copy that doesn’t copy sub-tables, so remove the recursion.

  • It also copies the metatable if it exists, so you’d have to add a getmetatable / setmetatable pair in yours.

Also it’s not so much that the function is hard to write, but that it’s so ubiquitous that it makes sense to include in the standard library.

You just identified some of the very reasons it took so long to for this to arrive as a feature! It’s quite an interesting system and all of those things were accounted for.

11 Likes

Looking at the RFC, table.clone recreates the structure of the table internally and takes a lot less time over using Lua, since you’re not constantly resizing the table, and the memory is preallocated for the table.

3 Likes

Bearing in mind that a table can always have sub-tables, why create a new instruction that could cause confusion if used by someone who wants to clone a table with multiple levels?

4 Likes

Perhaps table.clone could be made to have a feature similar to FindFirstChild where the second argument, a boolean, is used to force recursive.

Basically: local tableClone = table.clone(tableToClone, true)

9 Likes

Generally shallow copy is more likely to be what you wanted. Imagine I have the following:

local customPlayerObject = MyLuaPlayer.new(...)
local players = {table of these}
table.clone(players) --> Probably 💣💥 if it did a deep copy

Basically the issue is that deep-copy is dumb and doesn’t know “where to stop”, that is, what the “atomic” copy-by-reference parts of your data structure are intended to be because everything in Lua is just tables.

Even if you’re writing functional style code, more likely than not what you want is a shallow-copy of your top-level data structure which keeps references to the same immutable contents as the original but changes one or a couple of fields of the toplevel structure.

Deep-copy is a construct which is absolutely filled with perils, and it’s better to keep it locked away behind you having to implement it yourself IMO. table.clone allows you to easily make an efficient implementation of deep-copy now if you so desire though.

15 Likes

Are there plans to add a metamethod, eg __type to allow developers to return a custom string when typeof() is called on a table with the __type metamethod? Right now I have to differentiate between tables and lua objects by checking if Object._IsObject == true

6 Likes

Additionally, with deep cloning it’s unclear what “clone” means for many things. Does it apply to instances? What about things like CFrames that you can’t clone? What about threads? Etc. These are all things that you as a developer sort of have to decide or implement, and, deep clone would just be confusing if implemented in the engine I think.

Even assuming you just restricted it to other tables, it would not really fit as a feature imo, and it’d be a lot more difficult to implement in the engine than in lua, especially because you can also implement this kind of deep cloning with the same shallow cloning behaviour pretty easily like this:

local function deepclone(data)
	local clone = table.clone(data)
	for index, value in pairs(clone) do
		if typeof(value) == "table" then
			clone[index] = deepclone(value)
		end
	end
	return clone
end

Note that this doesn’t take care of what happens if you have a circular table (E.g. a table that eventually has itself contained). Here’s a less clear version which fixes this, and also clones metatables:

local function deepclone(data, clones)
	clones = clones or {} -- A set of tables which are being cloned already in this call, so we can avoid cloning circular tables. When there's a circular table it gets kept without being cloned, but you also might not want this
	clones[data] = true

	local clone = table.clone(data)

	-- Clone metatable
	local meta = getmetatable(clone)
	if meta then
		setmetatable(clone, deepclone(meta))
	end

	for index, value in pairs(clone) do
		-- Clone, but only if not already being cloned
		if typeof(value) == "table" and not clones[value] then
			clone[index] = deepclone(value, clones)
		end
	end

	clones[data] = nil
	return clone
end

There is a feature request.

I doubt it, and, it is something that I no longer really think is a particularly good idea. I think I might’ve asked something similar a while back, and, it sort of just presents many issues. My sole use case from what I can remember was being able to effectively spoof other data types in a sandboxing environment, but, I can just do this by replacing the behaviour of typeof in managed code.

The problem is that it sort of just complicates something that doesn’t need to be complicated, and it solves a problem that doesn’t need to be solved if you manage all of the code in your game, because, well, you can just replace your typeof behaviour yourself. Albeit, this might not be ideal, but, it is still better than using a metamethod for it imo.

5 Likes

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