Class Based Lua

I was looking around at the Unreal Engine, and Natural Selection 2, and I realized that class based coding in Garry’s Mod would be a lot more nice than the current structure. Now obviously there would need to be backwards compatibility otherwise everything would just break. Yet I am suggesting phasing this in. Below is an example script illustrating how this would work inside of Garry’s Mod.
The example script shows extending the player class for an RP gamemode.

[lua]
class RPPlayer : Player // Class RPPlayer Extends Player

RPPlayer.ClassName = “rp_player” //Used for Spawning, and Hammer

//Networked Variables Table
RPPlayer.NVars = {}
RPPlayer.NVars.Money = 1000
RPPlayer.NVars.JobID = 1

function RPPlayer:AddMoney( ammount)
self.NVars.Money = self.NVars.Money + ammount
end

function RPPlayer:SetMoney( ammount)
self.NVars.Money = ammount
end

function RPPlayer:TakeMoney( ammount)
self.NVars.Money = self.NVars.Money - ammount
end

function RPPlayer:SetJob( job_name)
//Find Job By Id
local gm = CurrentGamemode()

for k, job in pairs(gm.JobTable) do
    if (job.name == job_name) then
        self.NVars.JobID = job.id
        return true
    end
end

//If no Job by that name is found notify the player
self:ChatPrint( "Invalid Job!" )
return false

end
[/lua]

This could make it easier to interface with the Source Engine’s C++ Classes as well. So players could directly change gamerules, weapon classes, etc. Also, instead of having sweps, sents, gamemodes, snpcs, etc. There would only be classes, and mod packages. Mod Packages would replace add-ons and gamemodes.

An Example Mod Package File Path would be:
/garrysmod/garrysmod/roleplay/classes/
/garrysmod/garrysmod/roleplay/models/
/garrysmod/garrysmod/roleplay/materials/
/garrysmod/garrysmod/roleplay/maps/

Servers could dictate which mod packages to load. So if a server were to load the RP mod package, it would be given access to the RP gamerules class, or gamemode.

As illustrated in the example script Networked Variables would be in a proper table instead of sent over functions, and such. Excluding those using AzuiSleet’s Binary Module.

Currently Natural Selection 2 has this built into their Lua, and it seems to work quite well.
Also the Unreal Engine has been doing this for quite some time except using Unreal Script.

Of course this is no easy task, especially with keeping backwards compatibility. Though I do think it is well worth pursuing.

you’re better off sticking with an OO approach with Lua.

Right, because classes are not object oriented at all.
I already use Lua tables, and register them like in Fretta with it’s player classes for a lot of things.

You aren’t passing an object back when you define the class, which makes no logical sense. The traditional mixture of setmetatable and defining inheritance is a much better line to go down.

Lua has no classes but allows object orientated coding using metatables. GMod already uses this. A player object has it’s metatable (call it a “class” if you want) registered in _R[“Player”] for example.

[lua]local ply = _R[“Player”];

function ply:SetJob(bla)
self.m_Job = bla;
end
[/lua]

To create your own objects do stuff like this:

[lua]
local the_class = {};

function the_class:DoSomething()
end

function the_class.New()
local object = {};
setmetatable(object,{__index = the_class});
return object;
end
[/lua]

So if you want to modify an object, you should edit it’s metatable (laying in _R). This might not be exactly the thing you want but I just was showing you that everything you request (besides the packaging) already exist in GMod but differently.

Extending on what aVon’s saying, you can do something like this:

[lua]classhandler = {}

local classes = {}

function classhandler.Create(name , inheritfrom)
classes[name] = {}

if inheritfrom and classes[inheritfrom] then
	setmetatable(classes[name] , {__index = classes[inheritfrom]})
end
return classes[name]

end

function classhandler.Get(name)
return classes[name]
end

local mammal = classhandler.Create(“Mammal”)

mammal.HasFur = true

local dog = classhandler.Create(“Dog” , “Mammal”)

dog.HasTail = true

print(dog.HasTail , dog.HasFur)[/lua]

If you want to make a subclass:
[lua]
_R.RPPlayer = setmetatable({}, {__index = _R.Player})
_R.RPPlayer.__index = _R.RPPlayer

function _R.RPPlayer:DoSomething()

end
[/lua]

Edit:

To be even slightly useful, that would require everyone using the same system;
and I see no project large enough to employ such a system for internal useage.

Edit:
Convenience function:
[lua]
function MAKE_CLASS(base)
local t = setmetatable({}, {__index = base}
t.__index = t
return t
end

– e.g:
_R.RPPlayer = MAKE_CLASS(_R.Player)

[/lua]

Did you even read up on how lua/glua works?

Did I not just say I use the built in Lua classes already? I use them in much of my coding.

In the system I am describing all the Classes are available on runtime, as compiled code.
So there there is no need to return anything. You just create an instance of said class.
This is how C++ works, Unreal Script, and the Lua inside of Natural Selection 2.

Furthermore this idea would require recoding some parts of Lua in C++.
Much like is done in Natural Selection 2 or Garry’s Mod for adding Bitwise operators, and C-Style Comments.

:smug:

-snip-

Below is the base Actor Class for Natural Selection 2. This is using Unknown Worlds modified Lua.
http://www.pasteall.org/16419/lua

If this were such a dumb idea then professional game companies would not be using it.
Such as Epic, Dice, Digital Extremes, the many Licensee’s of the Unreal Engine, etc.
Yet strangely enough, all of them do. DICE, and DE also use modified Lua.
Even Valve uses such a method except in C++ with C++ classes. Which allows for easy modification.

It’s not a dumb idea to use classes in Lua. It’s a dumb idea to rewrite Lua to do it.

I see how you could think that, why fix something that is not broken right?
Well instead of people having to learn how to code sents, sweps, gamemodes, etc
all in different structures, they would all carry one common easy-to-use structure
that has been around for ages. The Class. It would have helped me out a lot more
when coming from a C background learning Lua. Because I would have immediately
recognized the class structure, and would have not had to learn much more than
functions.

You could easily implement a class system in your own code if you wished, but rewriting all of Gmod for it is never gonna happen.

How is a sents’s structure different from a swep’s structure? Appart from the table name being different.

I guess your right Nevec.
As for Magnusson though I can not implement this type of system because it requires editing the Lua DLL.

Off the top of my head, the only thing that you can’t really implement in Lua are private members and friend classes. Anything else can easily be done using metatables.

I don’t think that’s modified Lua, I’ve done a similar interface without any modifications in vanilla Lua.

It’s basically just
[lua]function class( id )
_G[id] = {}

return function( deriv )
	setmetatable( _G[id], { __index = deriv } )
end

end[/lua]

Or something similar, I can’t think straight right now.

The way I have used the Lua “classes” is I used them as a structure for my Jobs in my RP Gamemode.
[lua]
local Job = {}

Job.Name = “Citizen”
Job.Color = Color( 0, 255, 0, 255)
Job.Salary = 35

RegisterJob( Job)
[/lua]

Like Fretta does with Player Classes.