gamble Posted January 3, 2022 Posted January 3, 2022 Summary of Steps: Create Client Side script (Javascript) Add Client Side script to assets/js/config.js Create Client side API links (if needed) Include Client Side script and API links to index.html Create Server Side API (PHP) Create Client Side Script (Javascript): 'use strict'; class NewPage { constructor() { } generateMenuLink(button) { button.div.setAttribute('jailRestricted', 'true') button.div.classList.add('menu-button') button.icon.classList.add('menu-button-icon', 'fa', 'fa-hospital') button.text.classList.add('large') button.text.innerHTML = 'Hospital' button.div.append(button.icon) button.div.append(button.text) button.div.append(button.label) } generateContent(content) { } start(params) { params.menuLink.div.classList.add('menu-button-active') } stop(params) { params.menuLink.div.classList.remove('menu-button-active') } } Above is an example of the basic code that can be found in a Client sided script. Now lets go through each function and some notes of some thing inside constructor **OPTIONAL** - This is just a basic javascript function that is called when the class is created. Throughout the engine this class is used to initiate variables and API link classes generateMenuLink **OPTIONAL** - This will automatically create a link in the main menu...you just need to specify some things button.div - this is the entire button - we associate the menu-button class with it because it is our basic styling Notice the atttribute "jailRestricted" is set to true...this means that the menu link is hidden when in jail We also have a "hospitalRestricted" attribute that can be set button.text - this is what text appears in the button Notice the "large" class - The "large" class is only visible on desktop, it is hidden on mobile A "small" class exists to hide on desktop, and only show on mobile button.icon - this is what icon will appear on the button The engine uses Font Awesome, so take a look and find a icon you like for your page! Be smart with the icon choice...if you choose to hide the text on mobile, they will only see the icon generateContent - This is the content generate on load of the page DO NOT USE THE DATABASE IN THIS FUNCTION Trying to access the database in this section can result in an error occurring thus, making the site not work Typically in the engine we create a class variable and store the "content" parameter so we can draw the page later start - this is called whenever the menu link is clicked, or the module is loaded in any other way You can pass parameters to this by creating a link - for example if we wanted to load a profile on a link click: modules.load("profile", {id: userID}) I always use this to "activate" a button with styling stop - this is called whenever the "start" function of another module is called AKA whenever the page is stopped being used I always use this to "deactivate" a button with styling From here you are free to create whatever you want Add Client Side script to assets/js/config.js: Open assets/js.config.js You will see a object created called "config" with a list of modules stored in the "modules" key Add your new module to this list "newPage": new Page(new NewPage()), Update the key of this with an alias you would like to use This is used with modules.load() Within the new Page() add the class name you used in your client sided script Create Client Side API links (Javascript): Go to assets/js/apis Create a new file with an appropriate name to what your module is 'use strict'; /* * */ class ModuleAPI { constructor(){ this._file = 'module.php' } getSomething(){ return { url: api.buildURL(this._file+`/getSomething`), headers: api.authHeaders(), method: 'GET', } } postSomething(data){ return { url: api.buildURL(this._file+`/postSomething`), headers: api.authHeaders(), method: 'POST', body: JSON.stringify({'data': data}), } } } There are a couple things to note here: getSomething - will request {DOMAIN}/module.php/getSomething We will cover what this does on the server side later We need to pass the headers in order for the users data to be validated on the server No data can be passed with this method... postSomething - will request {DOMAIN}/module.php/postSomething Will will cover what this does on the server side later Again we need to pass headers - this is necessary for everything we want to do in game...we need to make sure you are logged in Data is passed in the body We can use this to request info about a certain user, update information, or whatever Basically this file is how the UI communicates with the server Include Client Side Script and API Links script to index.html: This is simple enough so we will not go into much detail Open index.html Add the links to the new files you just created Make sure API is before the Page script so that you can access the API script from the Page script Where you should put the links is marked in index.html Create Server Side API (PHP): Open the /api/ folder Create a new file for the module Create the API call responses <? require_once('core.php'); $getSomething = function(){ global $api; $loggedInUser = new User($api->getHeader('user')); $loggedInUser->enforceHospitalRestriction(); global $db; $db->query("SELECT * FROM users"); $allUsers = $db->fetchAll(); $api->output($allUsers); }; $postSomething = function(){ global $api; $loggedInUser = new User($api->getHeader('user')); $loggedInUser->enforceJailHospitalRestriction(); $userID = intval($api->getPostData()['data']); global $db; $db->query("SELECT * FROM users WHERE id = :userID", ['userID' => $userID]); $singleUser = $db->fetch(); $api->output($singleUser); }; $installer = function(){ $installer = new Installer(); $installer->checkTable('users'); }; $api->addRoute('/getSomething/', $getSomething); $api->addRoute('/postSomething/', $postSomething); ?> As you can see, the server side of this engine is stupid simple (as it should be!) In this example you can see how we fetch and validate the user in each API call. The User class auto validates the user. If the user appears to not be valid it will automatically terminate the script and return and error forcing a log out of the UI The User class is built into the engine and can be used to fetch ANY user. It will auto detect if the logged in user is being requested and run the appropriate checks, but any user can be fetched using new User($userID). The users database fields can be accessed using $userClassVeriable->username or whatever you are trying to fetch Example: $user = new User($userID) $user->username - would return the username of the user $user->money - would return the money of the user Another thing you can see is we enforce a restriction for jail and hospital! This functionality is built in with the following functions enforceJailHospitalRestriction - both Jail and Hospital enforceHospitalRestriction - Hospital only enforceJailRestriction - Jail only In the postSomething function you can see we fetch the "data" we passed in our API links script using: $api->getPostData()['data'] $api->output() This is what returns a message to the UI. We can return a string, array, whatever we cant. It will all be encoded into json, and auto-decoded on the UI through the QReq class When this function is called it kills the entire script using the PHP exit() function. Meaning whenever you see this the function will terminate at that point - no need to return anything after or exit afterwards. As an alternative if we run into an issue we can easily send a error message using $api->outputError(errorCodes, otherParameters) otherParameters can be sent as a string or array, this will be passed to the UI automatically and you can use it with the error handlers located in assets/js/core/errors.js - you can add your own codes here and handle them how you please Parameters will be stored in errorResponse.info in erros.js List of built in Error codes: 999 - this is a general error that will be displayed in a pop-up (can be used to say we do not have enough money or whatever) You can specify a string to be displayed in otherParameters 400 - forbidden access for when someone is trying to access something they should like staff panel This will log user out and log the event... 997 - User tried to access something they should have while in jail - redirects to jail and displays error 998 - User tried to access something they should have while in hospital - redirects to hospital and displays error $api->addRoute() This is how we tell the server what to look for. In the example above we are looking for /putSomething/ and /getSomething/ on the end of our file. For example if this is module.php these routes will be used when we try to access module.php/getSomething/ or module.php/postSomething/ The second parameter is obviously the function we are trying to call when the URL is visited The $installer function in this example is unused...this will be covered in a different post. This is for creating a module for other users to download and use 🙂 Thats pretty much all there is to it. We need a Page script, a client sided API script, and a server sided API script that tells the server what to do with information or what to fetch for us. One last quick note. In order to access an API link from the Page script use the following to make a request: QReq.request((new ModuleAPI()).postSomething(userID)).then(resp => { //what we do with what we return using the $api->output() function in the server code }) The above will call our postSomething function for the API links script we created earlier...it will pass the parameter we require as you can see. If anything is confusing or you need some assistance feel free to drop a reply below and ill gladly help clear up any confusion. I will update this as clarification is needed! Reserved for updates or other information Preparing for release so making documentation. As of writing this the engine is not released 1 Quote
Sim Posted January 4, 2022 Posted January 4, 2022 Instead of using these functions: I think an idea would be function or level. enforceRestrict(1,2,4,ect) Could add to list inside restrict code for other future restricts without adding new code / replacing in future. On another note, all looks good so far. I can't wait to create some mods myself. $loggedInUser->enforceHospitalRestriction() Quote
gamble Posted January 4, 2022 Author Posted January 4, 2022 25 minutes ago, Sim said: Instead of using these functions: I think an idea would be function or level. enforceRestrict(1,2,4,ect) Could add to list inside restrict code for other future restricts without adding new code / replacing in future. On another note, all looks good so far. I can't wait to create some mods myself. $loggedInUser->enforceHospitalRestriction() This is good input. I chose the way I did due to readability, but a function that runs parallel to these that's more dynamic isn't a bad idea at all! Easy to had too, so I may slap that in before release! Thanks for the feedback! 1 Quote
Sim Posted January 6, 2022 Posted January 6, 2022 Can I be one of the 1st people to get spade like aka now? To start creating mods 1 Quote
gamble Posted January 6, 2022 Author Posted January 6, 2022 6 hours ago, Sim said: Can I be one of the 1st people to get spade like aka now? To start creating mods Right now is a terrible time for me to release anything. I am reworking crons entirely so some key functionality will be missing...but i will let you in on a secret: I am planning to release the engine tomorrow. Not sure if it will be tomorrow morning or evening. I still have to message @Dave to try and get a SPADE Engine category in the marketplace, but im hoping to wrap up the code tonight, tomorrow morning, or tomorrow evening. Quote
rockwood Posted January 6, 2022 Posted January 6, 2022 (edited) On 1/4/2022 at 2:24 AM, gamble said: global please avoid this to use and try to use DI (Dependency Injection) Edited January 6, 2022 by rockwood Quote
gamble Posted January 6, 2022 Author Posted January 6, 2022 2 hours ago, rockwood said: please avoid this to use and try to use DI (Dependency Injection) I respect that you're trying to improve this, but for simplicity reasons I specifically chose to use globals. DI would be complicated to someone who is not too familiar with OOP. Not to mention that since this is PHP it's not that big of a deal since the server side of things is essentially recreated with every API call - it's not persistent between calls. If you could provide me an actual example why it would be beneficial in something like this I'll gladly reconsider, but it seems pretty pointless for server side code that runs for under 1 second at a time and is already self decoupled by the API calls themselves. Quote
Sim Posted January 9, 2022 Posted January 9, 2022 I really dislike the file structure for adding mods. I know its to late to change it now or it would be considered v2. But I will contribute a few mods sooner or later. Quote
gamble Posted January 9, 2022 Author Posted January 9, 2022 7 minutes ago, Sim said: I really dislike the file structure for adding mods. I know its to late to change it now or it would be considered v2. But I will contribute a few mods sooner or later. To be completely honest you could simplify it down to a PHP file and a javascript file. You could theoretical do the API calls in the same Javascript file as the page. I just do it this way to have complete seperation and uniformity. If you have an file structure idea let me know and ill see what i can do Quote
Sim Posted January 9, 2022 Posted January 9, 2022 Each mod own folder simplifys things for starters...? Quote
Uridium Posted January 10, 2022 Posted January 10, 2022 (edited) 🙂 Edited January 10, 2022 by Uridium 2 Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.