CEngine, a nice framework

Hello. I created a Framework that I personally use. The link for downloading/viewing this framework will be here!

Rojo: Rojo Documentation

VS Code Extensions (Optional):
Material-Icons
vscode-rbxlua

First and foremost, this framework is HEAVILY inspired by AeroGameFramework. I highly suggest you check out AeroGameFramework.

Shared Modules (Authors):
Promise: evaera
Maid: Quenty
Signal: sleitnick (Stephen Leitnick): (Based off Anaminus’s Signal Class)
FastWait: CloneTrooper1019
TweenModule: Me
UnGex: Me

ProfileService: ProfileService

Here are some of them explained in rdc 2020: https://youtu.be/Db3LooLQM1Q

I do not take credit for any modules that are not made by me. I’ve only modified maid a tiny bit to work on promises, but other than that I’ve barely changed them.

Why CEngine?
CEngine allows anyone to change how CEngine runs. CEngine also allows functions to be removed, added, or changed.

This framework is best used in Visual Studio Code, however you could use this framework in Roblox Studio if you add all of them in this order:


How to Setup Framework (Visual Studio Code Version):

  1. Go to the github link provided in the top, and also Install the rojo extension in vs Code
  2. Click on “Code”, then click on “Download Zip”
  3. After you’ve downloaded the file, extract to a location (Documents is a preferred place of storage)
  4. Open up Visual Studio Code, and Roblox Studio.
  5. Get the roblox rojo plugin, and start rojo in vs Code with the current project file
  6. Open the roblox rojo plugin, click connect, and you’re synced!

How to Setup Framework(Roblox Studio Version)

  1. Open the github link provided above, and open roblox studio.
  2. Create a Folder for each corresponding folder in the repo
  3. Add all run modules into run folder in ReplicatedStorage
  4. Add All Shared Modules into Shared (Don’t need to add any Modules that are in server or client)
  5. on Github, go to the very bottom of src/run/server and src/run/client and follow the steps below.
  6. create/add 2 new Folders called “Remotes” and Storage and place them both in ReplicatedStorage
  7. and You’re all set!

Notes While Using Framework in vs Code:

Don’t touch Storage OR Remotes while using vs Code. Don’t try to change the name of Storage or Remotes, as it will break the code unless you modify it.

Functions in CEngine/What they do.

all Services, Controllers, Classes, Util, and Shared Modules have access to functions in CEngine, so while defining the said Module, you can access functions such as :RegisterFunction().

:Start() and :Init() are only run on RunTime if that said module is a Controller or a Service. However, :Start() and :Init() could be put in as functions for modules, classes, shared, etc. It’s just that it will not run on runtime.

:Start() and :Init() work pretty similarly to AeroGameFramework, however there are some differences.

the Init function is only used to register functions or events, or to define values early. This is run before Start.

the Start function will run anything that is put inside of it. You’ll probably know what I mean by that. It’s pretty hard to give a unvague description of start, seeing that it is so easy to put the pieces together on what it does.

“RegisterFunction” has only 1 argument (Which IS a string), and if not defined, then it will by default look for functions in Module.Client if RegisterFunction is being run on the server, or Module.Server if RegisterFunction is being run on the client. This means that RegisterFunction can be used from both server AND client-side. If it’s on the client, since it cannot create events or functions, it relies on the server’s input to move those said remote on ReplicatedStorage, making it accessible to the client.

ConnectEvent can also be used for both client and server, and it has two arguments. The first argument is a string, and the second is a function. This function will most likely error if it is not created by :RegisterEvent().

RegisterEvent is a function with 1 argument. This function will create a new RemoteEvent place it in Remotes. The one argument in this function is a string, which will be the name of that said RemoteEvent.

Fire (Technically FireServer), FireClient, and FireAllClients. The Fire (Server) function has 1 argument, and a seemingly infinite capacity of parameters. (…) Fire Server basically runs the parameters into arguments into running the event. This can be run on the client. FireClient is the same thing, except the (…) argument is the third argument, after the second argument which is the player. This can be run on the server. FireAllClients is the Same thing as FireClient, but it runs on all Clients.

vsCode Extra Information:
Please DO NOT remove StorageHolder and RemoteHolder. Do not touch these in vs code.

if you ever want to add a new script to vsCode, all you do is this:
image
After which, simply rename said file to “anything you want”.lua.

Finally, The Yield function is a short for Promise.new().

Remember, Controllers and Services is the go to place to run methods.

Here is an example of the Framework being used in vs Code.

.

One last thing, here is my user snippet for vs Code.

{
	"Controller": {
		"prefix": "controller",
		"body": [
		  "local ${0:$TM_FILENAME_BASE} = {}",
		  "",
		  "function ${0:$TM_FILENAME_BASE}:Start()",
		  "",
		  "",
		  "end",
		  "",
		  "",
		  "function ${0:$TM_FILENAME_BASE}:Init()",
		  "",
		  "end",
		  "",
		  "return ${0:$TM_FILENAME_BASE}"
		],
		"description": "Controller"
	  },

	  "Class": {
		"prefix": "class",
		"body": [
		  "local ${0:$TM_FILENAME_BASE} = {}",
		  "${0:$TM_FILENAME_BASE}.__index = ${0:$TM_FILENAME_BASE}",
		  "",
		  "function ${0:$TM_FILENAME_BASE}.new()",
		  "local self = setmetatable({",
		  "  ",
		  "}, ${0:$TM_FILENAME_BASE})",
		  "",
		  "  return self",
		  "end",
		  "",
		  "function ${0:$TM_FILENAME_BASE}:Destroy()",
		  "",
		  "",
		  "end",
		  "",
		  "return ${0:$TM_FILENAME_BASE}"
		],
		"description": "Class"
	  },

	  "Service": {
		"prefix": "service",
		"body": [
		  "local ${0:$TM_FILENAME_BASE} = {}",
		  "",
		  "function ${0:$TM_FILENAME_BASE}:Start()",
		  "",
		  "end",
		  "",
		  "function ${0:$TM_FILENAME_BASE}:Init()",
		  "",
		  "",
		  "end",
		  "",
		  "return ${0:$TM_FILENAME_BASE}"
		],
		"description": "Service"
	  },
	  "module": {
		"prefix": "module",
		"body": [
		  "local ${0:$TM_FILENAME_BASE} = {}",
		  "",
		  "return ${0:$TM_FILENAME_BASE}"
		],
		"description": "module"
	  },

	  "Create Server Event": {
		"prefix": "event server",
		"body": [
		  "self:ConnectEvent(nil, function(player, ...)",
		  "",
		  "",
		  "end)"
		],
		"description": "Create Framework Event"
	  },
	  "Create Client Event": {
		"prefix": "event client",
		"body": [
		  "self:ConnectClientEvent(nil, function(player, ...)",
		  "",
		  "",
		  "end)"
		],
		"description": "Create Framework Event"
	  },

	  "Create promise": {
		"prefix": "promise",
		"body": [
		  " local promise = self.Shared.Promise.new(function(resolve, reject, onCancel)",
		  "",
		  "",
		  "end)"
		],
		"description": "Create promise"
	  },

	  "Create signal": {
		"prefix": "signal",
		"body": [
		  "local signal = self.Shared.Signal.new();",
		  "",
		  "local connection = signal:Connect(function(arg)",
		  "",
		  "",
		  "end)"
		],
		"description": "Create signal"
	  },
	  "Tween": {
		"prefix": "tween",
		"body": [
		  "local ti = TweenInfo.new();",
		  "local Instance",
		  "local Properties = {",
		  "",
		  "}",
		  "",
		  "local Tween = self.Shared.TweenModule.GetTween(ti, Instance, Properties)",
		  "",
		  "Tween:Start()",
		  ""
		],
		"description": "Create tween"
	  },

	  "Add In Fast Wait": {
		"prefix": "wait",
		"body": [
		  "self.Shared.FastWait.Wait()"
		],
		"description": "Add In Fast Wait"
	  },
	  "in pairs loop": {
		"prefix": "pairs",
		"body": [
		  "for i, v in pairs() do",
		  "",
		  "",
		  "end"
		],
		"description": "in pairs loop"
	  }

}

2 Likes

The main branch contains a single readme md file…? Huh. Had to change to Fly to read it.

Here is what I think from first impression of reading: Like AGF, it has many of its weakpoints, being inflexible and rigid in design. It is not modular, in the sense I cannot drag and drop it in an existing codebase and easily get it all up and working.

Additionally, services’ Init and Start should run sequential. Meaning all of services’ inits should run before any Start methods. Currently it would run Init and Start on the first service, and repeat with other services. This doesn’t make any sense, lifecycle and state wise. Thirdly, you haven’t thought much about race conditions, what happens if you were to index a service that hasn’t been initalised yet. Read and write shouldn’t be allowed to occur at the same time.

1 Like

First of all, it’s actually on master. I accidentally placed in the wrong link. As of right now, the most recent version is this: GitHub - CurlyDoctor/CEngine at master. Yeah, I was just testing things 8 days ago lol. I actually found out how bad my run methods were, and I decided to wrap Init and Start methods on promises. I’m not very experienced with github, which is why I put in the wrong link (lol).

I’m going to fix this of course. Last thing to note is that I’m fully aware of some of AGF’s flaws.

Edit: I fixed this issue, changed the link to actually be on master

Edit 2: Also just wondering, should I delete the readme.md file?

Briefly looked at the aforementioned code reference, and this is arguably worse. Now you are going to have colliding asynchronous operations. Promises were made for chaining asynchronous tasks.

What you should do instead is wrap the first for loop into a promise, push the init methods into an array of promises. And then below the loop, utilise Promise.all; and finally since it is a promise, it is thenable. So after the init promises has resolved, move onto the :Start methods. I can make a pull request on your github in the morning if you want to.

2 Likes

Ok, can you please pm me your github user, so that I can invite you to collaborate? If you want credit above I can give it to you on top of the post.

Update Log 1:
Thank you for @Ukendio for helping me out, and coding the patch notes on discord.

Patch notes:

Ukendio : Fixed race conditions, and it should be running just fine now.

Me: removed README.md (as this post is telling people how to use it), ran some tests, and pushed new update to CEngine/master repo.

Once again, thanks a million @Ukendio for revising the code.

Edit: I also added Holders for Remotes and Storage, making it so that vsCode users don’t have to manually place it in. PLEASE DO NOT REMOVE THE HOLDERS, as this will remove the folders from github.

1 Like

Update Log 2:

For vs-Code users, you no longer need to touch or move anything on roblox studio. Upon syncing with rojo, Two new Scripts are made (one localscript), automatically require( running ) run modules. You can still change server and client run modules via src/shared/run.

As a tip, if you feel that there is too much folders, making it look cluttered in vs Code, you can always hide them ( unnecessary folders ) by going into settings and searching up “exclude”. It will not delete the file, only hiding it from sight.

I suggest you hide Remotes, Storage, ClientInternal, ServerInternal, and Run (if you not planning to change runtime). However, DO NOT delete them unless you are planning to remove the corresponding code relating to any of these said folders in default.project.json, and replace them in roblox studio.