Skip to content

Plugin. WIP (DEFINE_BASECLASS, sent classes, NetworkVar, AccessorFunc) #74

Open
@TIMONz1535

Description

@TIMONz1535

Goal

We need a plugin that implements some game specific behavior of Lua things, like Set/Get generation, auto class naming/detection.

OnSetText implementation

An example of a simple plugin that

  1. Expands preprocessor macro DEFINE_BASECLASS.
  2. Automatically classifies scripted ents by folder/filename and solves "duplicate field" inside the sent file.
---@class gmod_hands: ENT
local ENT = {}

... original file code with ENT usage

However, I don't want to use it in this form, because it's working with text, and it's reached the edge of its possibilities. For example, you can see that the first character of sent file is displayed in green, because I am injecting a fake class there.

Implementing a NetworkVar and AccessorFunc already seems impossible with a text.

---@class diff
---@field start integer # The number of bytes at the beginning of the replacement
---@field finish integer # The number of bytes at the end of the replacement
---@field text string # What to replace

local scopeFolders = {
	{ "EFFECT", "effects" },
	{ "SWEP",   "weapons" },
	{ "ENT",    "entities" }
}

---@param uri string
---@return string?, string?
local function GetScopedClass(uri)
	for _, scope in ipairs(scopeFolders) do
		-- gamemode based uri:
		-- .../gamemodes/my_gamemode/entities/entities/ent_class_name/any.lua
		-- .../gamemodes/my_gamemode/entities/entities/ent_class_name.lua
		local class = uri:match("%Wentities/" .. scope[2] .. "/([^/]+)/?[^/]*%.lua$")
		if not class then
			-- addon or root based uri:
			-- .../addons/my_addon/lua/entities/ent_class_name/any.lua
			-- .../addons/my_addon/lua/entities/ent_class_name.lua
			class = uri:match("%Wlua/" .. scope[2] .. "/([^/]+)/?[^/]*%.lua$")
		end
		if class then
			return scope[1], class
		end
	end
end

---@param uri string # The uri of file
---@param text string # The content of file
---@return diff[]?
function OnSetText(uri, text)
	---@type diff[]
	local diffs = {}

	-- Detect "scripted" scope by folder and localize its global table to @class annotation.
	local scope, class = GetScopedClass(uri)
	if scope then
		diffs[#diffs + 1] = {
			start = 1,
			finish = 1,
			text = ([[
---@class %s: %s
local %s = {}

%s]]):format(class, scope, scope, text:sub(1, 1))
		}
	end

	-- Replace preprocessor keyword DEFINE_BASECLASS.
	for start, finish, b, c in text:gmatch("()DEFINE_BASECLASS()") do
		diffs[#diffs + 1] = {
			---@cast start integer
			start = start,
			finish = finish - 1,
			text = "local BaseClass = baseclass.Get",
		}
	end

	if #diffs == 0 then
		return nil
	end

	return diffs
end

Completed features

  • Expands preprocessor macro DEFINE_BASECLASS.
  • Automatically classifies scopes of scripted ents (ENT, SWEP, EFFECT) by folder/filename. This is necessary step to add any methods to the class, and also solves "duplicate field" inside the sent file.
  • It needs to be rewritten to OnTransformAst/VM.OnCompileFunctionParam.
  • How to distribute a plugin with an addon?
  • Implement NetworkVar/NetworkVarElement. It only works in sent file inside of ENT:SetupDataTables for self:NetworkVar(...) and self.NetworkVar(self, ...) for stack defined arguments, not localized one.
    Doesn't support BaseClass.SetupDataTables(self).

Refs

Plugin samples

OnSetText
https://github.com/goldenstein64/lualogging-definitions/blob/13aabcde86b98c3bd3d2cacc0121f288496db045/plugin.lua
https://github.com/goldenstein64/pl-definitions/blob/54bf99b9d6394f6e9bab0fb2029ecf908db9a8cc/plugin.lua
https://github.com/serg3295/nodeMCU-emmylua/blob/232b42845e2f7a32ef8837417b409f5db666ecdf/plugin.lua
https://github.com/RavenfieldCommunity/RavenscriptIDEA/blob/7525a2eb431d27199e8c17aeceb872b1d559c4aa/plugin.lua
https://github.com/ProjectTH/fivem-lls-addon/blob/c93a8d64d0b541feda6b09b86961a7d62db2ee6d/plugin.lua

ResolveRequire
https://github.com/Periapsises/Starfall-LLS/blob/de36268b6218dca73b492176e8ef013b31bf3d6c/plugin.lua

OnCompileFunctionParam, ResolveRequire
https://github.com/Wild-W/smbx2-lunalua-luacats/blob/417401f1e6ade91809067bb2afac84f90109ab08/plugin.lua

OnTransformAst
https://github.com/LuaCATS/dontstarve/blob/42a8810744bb00266d733f9ed84b56b91fe74e94/plugin/dontstave.lua
https://github.com/DeadlyBossMods/LuaLS-Config/blob/main/Plugin/Mod-Class-Plugin.lua

Custom diagnostics:
LuaLS/lua-language-server#2511
https://github.com/DeadlyBossMods/LuaLS-Config/blob/main/Plugin/Event-Diagnostic.lua

TODO

  • Implement AccessorFunc.
  • Localize Set/Get class to self: ent_myent instead of self: Entity?
  • Lookup ents.Find* functions for existing classes instead of T|Entity (cannot cast ent_notdefined|Entity to Entity).
  • PANEL table auto classification by derma.DefineControl, vgui.Register.
  • Maybe hook.Add/hook.Call/hook.Run.
  • Research support for BaseClass.SetupDataTables(self)
  • Performance check.

I haven't had time for further research yet 😪

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions