Moonlight - A powerful Luau hybrid - [Suggestions]

I am working on a modified version of Luau via. ModuleScript it is called Moonlight and currently isn’t finished yet.

It is expected to release in April no exact release date yet.

Let’s get onto the basics of how Moonlight works.

Documentation

- Properties

Screenshot 2023-04-01 084754

This function allows you to change properties of an object through a table similar to Rust, so you don’t have to constantly retype the object’s name to access its properties.

Thanks @C_Corpze for the suggestion.

- SetAttribute

Nothing really special here but the reason why this function exists is because the Properties function doesn’t have support for attributes, so SetAttribute/GetAttribute functions exists because of this.

- GetAttribute

Screenshot 2023-04-01 090209

Not going to say what it does but you most likely know by the screenshot.

Now moving on to other functions…

- Classes

Reminder: Classes have the same functionality as tables, but they aren’t entirely useless as they have a function that can be really useful as you will see later on in the documentation.

Screenshot 2023-04-01 091214

Classes are exactly the same as tables, you can name them, make variables, create functions, run those functions.

You can even create objects with them.

Screenshot 2023-04-01 091422

Thanks @C_Corpze for this suggestion.

- Borrow

Screenshot 2023-04-01 092630

The borrow function lets you transfer a classes content to another class which can be useful in cases.

(e.g., class1 (first argument) → class2 (second argument)

- Triggers

Screenshot 2023-04-01 092749

The CreateTrigger function can be extremely helpful as @C_Corpze said “This allows for creating an object and immediately initialize it with the specified values.”

- Conclusion

Moonlight is planning on having 8 functions that you can use.

If you have any suggestions for Moonlight (such as: functions) tell me them and tell me what they do as I can get easily confused a bit since Luau is the only programming language that I am used to.

1 Like

Seems like a decent start, although not sure if the attribute function is necessary unless it’s for setting multiple attributes at the same time.
I mean BasePart:SetAttribute() isn’t a lot of code to write and I think the attribute function of this module would only make it more lengthy to set/get a single attribute.

Instead this would be really useful:

Moonlight.SetAttributes(workspace.Part,
 {
  attribute1 = 3;
  attribute2 = true;
  attribute3 = "test";
 })

The class function I personally would also change up, something about the way it works or is written just feels off.
Instead, maybe provide a function to turn an existing table into an class?

local MyClass = {} -- Really just an table

MyClass.SomeNumberProperty = 5
MyClass.SomeStringProperty = "Oh no I'm a string, what am I doing here?"

function MyClass:printThing()
 print(self.SomeNumberProperty)
end

function MyClass:add(x)
 self.SomeNumberProperty += x
end



Moonlight.makeClass(MyClass, class_to_borrow_from) -- Instant borrow function, leave empty for none

local ClassInstance = MyClass:new(initial_properties_here)

ClassInstance:add(5)
ClassInstance:printThing() -- 10

Might not be 100% consistent with Roblox syntax but you kinda have to use the : operator if you want access to the self keyword which allows a table/object to access it’s own properties within itself.
It is however slightly more consistent with how other programming languages usually create objects.

What I would also consider to be an very useful function is being able to convert entire models that contain parts and objects into blueprints that can be cloned easily.
Game object classes / blueprints is what I would call them.

local Brick = {}

function Brick:setColor(color)
 self.__object.BrickColor = color
end

Moonlight.makeBlueprint(game.ReplicatedStorage.Part, Brick, optional_class_to_borrow_from) -- Sets __object to the specified object

local MyBrick = Brick:new(workspace) -- Also calls :Clone() on the part in ReplicatedStorage and makes it part of the class

MyBrick:setColor(Color3.new(255,255,255))

This would allow you to turn both a table AND a instance 9such as a part or a model) into an class.

I’ll address these issues and prepare them for the next upcoming change for Moonlight.

Thank you.

Hopefully this is a bit nicer for you! :smile:

Screenshot 2023-04-01 110643

Screenshot 2023-04-01 110722

1 Like

@C_Corpze is this better? :eyes:

Screenshot 2023-04-03 074042

Screenshot 2023-04-03 074056

Screenshot 2023-04-03 074304

Screenshot 2023-04-03 074129

1 Like

@C_Corpze The teaser above me has changed slightly where the function doesn’t need arguments anymore (e.g., you can do 1, 2 instead of having to do 3 arguments)

The issues that you have demonstrated has been fixed and done completely in your way.

  • Blueprint function will also be possibly added.
  • SetAttributes function has been removed due to possible limited use cases.
  • GetAttributes has been removed due to some issues.
  • Classes have been reworked completely.
  • Renamed Class function (originally new not to be confused with the other class function as that has been renamed to CreateTable) to ConvertToClass
  • New function has been added (new)
  • To convert a table into a on quote “class” you can call the ConvertToClass function.
  • The error message no longer displays when there is no init function.

And Moonlight is planning to have 10 functions instead not that much, but the advantage is it can be extremely lightweight and easy to use without much workload.

If you have any more suggestions, please tell me what they do, and I can most likely add them.

1 Like

Also useful if you include a description of what a function does and how you can use it btw.
Some of the examples are a bit vague or seem a bit simple.
Providing use cases or explaining why it’s a useful function can help clarify it and also get more people interested who are looking for specific functionality.

1 Like

Thank you for the feedback.

Do you have any other suggestions in mind?

If so, then feel free to post them here and explain what they do! :grin:

I would like to see an example of your class system.
Like, how would I make an entity class with it that has a health variable and a :TakeDamage() function for example?

The “tutorial” on it still feels rather abstract to me.

Say I want to make an entity/humanoid class to hold/store the amount of health point and walk speed.
Now I want to make a zombie that inherits those properties and functions, how would I do this?

Also make sure you include proper spaces / formatting so the code is readable for others. :slight_smile:
I’ve noticed some of the code feels a bit crammed together, some space and comments would really help new comers who are trying to understand your tools.

1 Like

Sorry I have been busy lately but thank you for this feedback.

Sadly, Moonlight doesn’t really support inheriting, but I will take into consideration a possible inherit function.

Thanks for your feedback.

1 Like

Inheritance is relatively easy to implement though.

function mod:makeClass(n: string, v: any)
	if not n then error("Classes must have a name.") return end
	
	v.class = n -- Set class name for type checking.
	
	v.__index = v
	self.__index = self
	setmetatable(v, self)

	print(tostring(v) .. " is now a class")
	return v
end

This is a code snippet of a module of mine that implements OOP in Roblox Lua using metatables.
This function turns a table into an “class” and allows you to create instances of it by calling class:new().

If a function with the name "init’ is found in the table, it’s executed when a new instance is made which can be used to set initial values and such.

Another code snippet.

-- Gets called when an instance of the class is created.

function mod:init(data: any)
	if not data then return end
	-- Set values if data exists (expected to be an table or list).
	for k, v in ipairs(data) do self[k] = v end
end


-- Creates an instance of the class and then calls it's init() function.

function mod:new(i: Instance, dat: any)
	if not i then error("No instance was provided upon creation.") return end
	
	self.__index = self -- Class will be used as metatable for inheritance.
	
	-- Create a new table that inherits from the class.
	local o = {}
	setmetatable(o, self)
	
	-- Call the init() function on our new object so it can execute some code from the moment of creation.
	o:init(i, dat)
	o.o = i
	
	i:SetAttribute("class", o.class)
	
	return o
end

Also as you may have noticed, my module allows you to tie objects and instances to the tables.
Also has a bunch of functions so you can read variables or call functions even when script A is completely unaware of script B’s contents.

As far as I know, metatables can work recursively so setting table A’s metatable to B and B to C, etc, you get a structure of inheritance.

1 Like