Creating Modules - cadergator10/Opencomputers-servertine GitHub Wiki

Overview

The big thing about the Servertine system is its incredible modularity as well as the amount of power you get with it. I KNOW this is incredibly INCREDIBLY difficult to understand, which is why I am incredibly happy to provide whatever support I can with you on any project, whether it is discord messaging, voice chat, or some programming I'll happily support you! Just let me know! (discord: @cadergator10)

Server

The module that all your devices will be communicating with. Relatively simpler to program than the database module. Most variables are passed in the init function.

Passed Variables

The variables passed in the init function listed more in detail. The 3 variables passed should be set to a local variable in the module so you can change it in other functions.

function module.init(settings, doors, serverCommands)

userList

The userList is the first thing passed in the init function. It links directly to the userList on the server, so anything changed on it will change it for all modules and the server. It's labeled as settings on the module prefab.

device List

The deviceList is the list of devices which sync their information with the server using setDevice. It's labeled as doors on the module prefab.

serverCommands

The last variable passed is a table of server commands you can run. This will be explained more in the next part.

Server Functions

These are server commands you can run to perform extra commands like print to screen or crypt string.

crypt(string,reverse)

Crypt the string given or decrypt it. Uses the cryptKey set on the server Set string to the string you want to decrypt or crypt. Set reverse to true to decrypt a string. Set it to false or leave as nil to encrypt a string.

returns the encrypted/decrypted string.

copy(table)

Deep copy a table. This ensures that a table is unlinked from the table. Normally, setting a table equal to another table still means that if you change the variable in one table, the other will change as well (they are the same). This clones the table, meaning they are not linked.

set table to the table you want to copy.

returns the cloned table.

send(direct,data,data2)

Send a modemMessage to either all devices or the last device which communicated with the server. Supports the range extending system, so if you direct it to a device using the range extender, it auto routes it back to it.

set direct to true if you want to send it only to the device which sent the message to the server. If false, it sends it to all devices it can (eg: broadcast it) Set data and data2 to the two data points you want to send over the modem.

returns nothing.

advsend(address,link,port,data,data2)

Similar to send, but with more features (and more customizability) but more difficult to fully utilize. Send a modemMessages to the device of your choice. address = the end device's modem uuid. set to nil to broadcast to every device on the network. link = the address of the linking card that is in the rangeextender program. This requires getting its uuid from the doorTable (doorTable[id]["repeat"] == (false or "uuid") if false, the device doesn't use the range extender. if a string, that is the UUID of the linking card. For more info on the details please reach out to me port = port you want to send out on. If set to nil, it uses the modemPort set by the user. data and data2 is the data to be sent over the modem.

returns nothing.

modulemsg(command,data)

Send a message to all modules using the command and data format. This is how you can communicate with other modules installed on the server.

Set command to the command you want to send to the modules (what they check to perform actions on the data and such. Set data to the data being sent to the modules to process if the command matches

Returns false if module not found, true and other data returned by the module if module was found.

print(message)

Print a message on the database. You can either just type out the text or use the format of the returns for module.message.

Set message to either a string or table: If string, it will just print it out on a new line in white text. If table, you can do more. It's a table of tables. Example: {{["text"]="first text in red",["color"]=0xFF0000,["line"]=true},{["text"]="second text in green",["color"]=0x00FF00,["line"]=true},{["text"]=" and blue",["color"]=0x0000FF,["line"]=false}}

returns nothing

configCheck(key)

Check a setting changed/set by the database (if that setting's server value is set to true) explained more in the database module's module.config info

Set key to the key of the setting you want to check.

Returns either an int, string, or a boolean depending on the type of setting specified in the database module's module.config value.

Variables

module.name

The name of the module which is displayed on the module button. string

module.commands

The commands you want to allow through the server. If a command is not shown in here, the command will not be processed by the server. Table of strings

module.skipcrypt

The commands that are in module.commands which you do not want to decrypt the data. If a command is not here, then the server will decrypt the data it receives. Put a command here only if the received data is going to be not crypted. Table of strings.

module.table

This is a keyed table used to check if the userList has it. If not, it is set to what the table equals.

module.table = {["apples"]={["worked"] = true}} --This will check if userList has apples in it. If not, then it will set apples in the userList to the default, which is {["worked"] = true}

module.debug

Will be set by the server if debug mode is enabled. Don't set this to anything but false. You can refer to this to perform certain functions if it's enabled.

functions

The functions called by the server.

module.init(settings,devices,serverCommands)

The very first function called by the server when the server is started. Passes userList as settings, deviceList as devices, and serverCommands is special server commands you can run through the server. You can then save these functions as local functions so you can interface with them.

module.setup()

Run right after init function and every time the userList is updated.

module.message(command,data)

Called when a message is received by the server and the main server doesn't have the command saved. Command == command received by the server Data = data received along with the command

If your command doesn't match at the end, you HAVE to return false.

If your command matches, you can do whatever you want, and then at the end, you can return multiple data points: return true, printdata, savetable, directmessage, modemdata1,modemdata2 first one must be true Set printData to a table of text to print out to the server log. Example pass through: {{["text"]="first text in red",["color"]=0xFF0000},{["text"]="second text in green",["color"]=0x00FF00,["line"]=true},{["text"]=" and blue",["color"]=0x0000FF,["line"]=false}} Set saveTable to true if you updated the userList and need the server to save the table. Set directmessage to nil if you aren't sending anything over the modem, false if you want it to broadcast to everyone, true if you want to send it back to the device that sent the command to the server Set modemdata1 and modemdata2 to the data you want to send over the modem. You can leave it as nil if directmessage is nil or you dont want anything sent over that variable.

module.piggyback(command,data)

Similar to module.message, except it's only run after the command is passed and/or is checked for all modules, and you don't return anything in the piggyback. It's kind of a way to check other module's

Database

Compared to server module programming, the database is quite a bit harder to make than the server. There is a prefab module located in the "database/database module prefab" folder in the github.

Passed variables

These are the variables the database gives to you when it's run. It is the line that says, "local workspace, window, loc, database, style, compat = table.unpack({...})"

local workspace, window, loc, database, style, compat = table.unpack({...})

workspace

This is the workspace that the entire database is running on. Mostly used for forced draw events used in certain circumstances. Likely won't use this much.

window

This is where you will be setting all of your GUI elements. You are given a 135 by 33 area to work in to set GUI elements.

loc

This is the localization file of the database. You can use some of these for your own modules if you want.

database

This is a table of functions you can run. They will be explained later in this wiki page.

style

This is the style table. You can use these style colors for your own modules to make them sync up with the database's color scheme.

compat

This is the Compat library configured by the database. DO NOT USE THE SYSTEM, FILESYSTEM, INTERNET, OR EVENT LIBRARIES! These libraries are meant to be saved in the compat library if I ever needed them, so if you need stuff added to this, let me know. If you try to use the MineOS or OpenOS version of these libraries or any other library, the chances are IT WILL CRASH ON THE OTHER if not careful. To view the different functions, view the Compat.lua file here https://github.com/cadergator10/Opencomputers-servertine/blob/main/database/Compat.lua

Database functions

These are proprietary functions given to you by the database you can use to perform special actions.

database.update(table,force)

Updates the server with new data. Set table to a table of the keys (strings) in the userList to update the server with, or leave it nil to update the entire userList to the server. Set force to true if you want to force the update. If this is set to false, it will only update it if autoUpdate is set to true.

doesn't return anything

database.save()

Save the userList table. This just acts as a buffer so, if the server goes offline, the userList is saved on the database itself.

doesn't return anything

database.crypt(string,reverse)

Crypt the string given or decrypt it. Uses the cryptKey saved on the database Set string to the string you want to decrypt or crypt. Set reverse to true to decrypt a string. Set it to false or leave as nil to encrypt a string.

returns the encrypted/decrypted string

database.send(wait,data1,data2)

Send a message through the database. Set wait to true if you also want to receive the data Set data1 and data2 to the 2 data points you want to send on the modem broadcast.

Returns nothing if wait is false or nil If wait is true, then the first thing returned will be true if something was received, false if nothing was, then if true, the rest that is returned is all the data returned by modem_message events.

database.checkPerms(base,data,reverse)

Checks the permissions of the currently signed in user. Set base to the base permission that all your module permissions checked will be derived from (eg: security module's base perm. is "security" Set data to a table of all the sub permissions you want to see if they have on top of that. (if base is "security" and data is {"one","two"}, perms checked would be "all", "security.*", "security.one", and "security.two".) Set reverse to true if you want the return to be the inverse of what it would be. Useful for disabling buttons.

If reverse is false or nil, then returns true if permission is found, false if no permission is found or is rejected. If reverse is true, then returns false if permission is found, true if no permission is found or is rejected.

database.dataBackup(id, data)

Save data only over the database's session (until the program is closed)

Set ID to the key of your save. string. Leave data empty (nil) to retrieve whatever is saved at that key or set it to something to set that key in the table to the new data.

If data is nil, returns whatever is set to that key If data is not nil, returns true

database.checkConfig(key)

Check a setting changed/set by the database. Explained more in the database module's module.config info

Set key to the key of the setting you want to check.

Returns either an int, string, or a boolean depending on the type of setting specified in the database module's module.config value.

Variables

module.name

The name of the module and what is shown on the button on the database.

module.name = "Example"

module.table

A table of the keys that you want to both pull from the server and update to the server.

module.table = {"exampleKey","exampleKey2"}

module.debug

Indicates if debug mode is enabled or disabled. Leave this at false, as if the database's debug mode is enabled, it will change this to true for you.

module.config

Adds buttons/inputs to the Dev module's setting module that you can use to change how your module behaves.

[key] = {["label"] = "A Label",["type"]="bool/int/string",["default"]="whatever is set first",["server"]=false/true} Set key to whatever key is used to retrieve using checkConfig(key) Set label to the label on the setting screen. Set type to what type of setting it is. bool is a button true/false, int is a number. string is a string input. Set default to whatever it is first set to upon first being installed. If bool, true or false; if int, a number; if string, a string input. Set server to true/false whether you want the server module to also have access to it (if it's a setting that the server modules use too)

Functions

module.init(userTable)

The very first function run by the database. It passes the userTable that was downloaded from the server to the database and gives out the table to all modules using this. Set a local variable in the module to the userTable.

local GUI = require("GUI") local userTable local workspace, window, loc, database, style = table.unpack({...}) module.init = function(usTable) GUI.alert("It Workies!") userTable = usTable end

module.onTouch()

Run when the module button is pressed on the database. This is when you set up the environment for the database

local GUI = require("GUI") local userTable local workspace, window, loc, database, style = table.unpack({...}) module.onTouch = function() GUI.alert("It Workies!") end

module.close()

This is the function run when the module is closed out of (eg: another module button is pressed) You can use this to perform anything necessary before closng the module and returning a table of what you want to update to the server (if autoupdate is enabled)

module.close() GUI.alert("Closing module") return {"exampleKey","exampleKey2"} end

Using the Website

Knowing how to add modules to the website is incredibly important to allowing others to use your program as well as testing your program easily on the system. I'll guide you though the simple parts on how to do this.

Website is https://cadespc.com

First time account creation

You must make an account on the website to post any modules.

  1. Click register in top right
  2. Enter your email, username, and password you would like to use.
  3. If successfully made, check your email for the email verification
  4. Click the button to verify

If you would like to change any account info, simply click on "Hello " in the top right and change your profile settings. Please ensure that your about me and avatar are completely appropriate. Anything inappropriate will not be tolerated.

Creating your module

Modules cannot be deleted by yourself once made, so if you do want it removed, you'll need to ask cadergator10 (creator) to manually do it. This is to prevent lost dependencies breaking other modules.

  1. Click "Modules" in the top left
  2. Click "Create New Module" (if you are not signed in, this will not show)
  3. Enter a Name (name of module), Brief Details (info shown on Modules page), and the Description (info shown in your module's detail page). Please note: all of this can be changed later. When finished press create
  4. Make sure your back in the Modules page and click your new module
  5. In your module page, click "Edit Module"

All good! You are now in the page to make changes to your module. Please go to "Editing the Module" for more info

Editing the module

To edit your module, you navigate to it in the modules tab on the website, click your module, then click edit module. Now we get into setting up the actual module!

Main info

Main info consists of the Name, Brief Details, Description, Requirements, and Optional Modules. You should know what the name, brief details, and description are, but not the other 2.

Requirements are modules that are absolutely required by the module. In the module installer on the database, if you were to select this module for install, it would move all modules whom you specified it required as well, as well as move this module back to the "don't install" category if that requirement was moved back. You add requirements by putting in the ID's of the modules in the text box seperated by commas (these ID's are visible in the module's details page in the top right)

Optional Modules are modules which this module can use to add extra functionality. You add modules here the same way as with requirements (id's of modules seperated by commas). only difference here is that it's purely visual on the website and does nothing else but to alert the user it has optional stuff.

File Management

This is how you add the files to be downloaded with your module. A module must have ONE Main.lua file for a database module and server module in order to function. This is the file run by the database/server. You are not required to have both a server and a database module, you can have one or the other if you want. It depends on whether you need both. To create a file, you click "Create File", input into the text boxes all the info, and press "Create File"

Path is the path it'll install. The main file would be "Main.lua". At the moment it only supports that much, I have not confirmed it supports folders (eg: folderone/file.lua) This is what it is named when installed on the server/database

URL is the URL where the file can be downloaded. If using github (which I recommend over pastebin because of branches. You'll know in a bit) this is the raw url of the file to be downloaded.

Developer URL is optional, but is SUPER HELPFUL for debugging. If you have a branch where you make all your changes for your next update, you can input the Raw URL of the development branch's file here and when the database is in development mode, it'll use this url instead. Another good thing to note is that, while the regular URL won't be used until published to the live build, the Developer URL is always used by developer mode in the edit page! That means you can use the developer url changes without having to push them to the live build! (sorry if this messed with your mind, I can't explain good lol)

Check if this is a file for the server: Just as it sounds. If this file needs to be installed on the server, check it. Otherwise, leave it empty.

Publishing to Live Build (first time)

if everything is valid, you can publish to live build. Simply click the publish to live build button. If any errors pop up, do what they say to try and remedy it. If all is good, it'll ask you to input an update description. You can leave it empty and just push it or input the update changelog. Since this is the first time of the module being published, it requires a manual review. If approved, the module will be available for download in the live branch and if this is your first ever module, you will receive the developer role (upgrade 😃). If denied, you should be alerted of it. If any foul play (meant to damage hardware or data) is found, you may receive a report on your account. You can then do any changes to your module on the edit page and try again.

Publishing new changes to Live Build

No changes in the edit page ever are reflected in normal mode on the database. You are free to perform any changes on the edit page without worry of ruining the live build. If you want to push an update, simply do the "Publish to Live Build" thing again from before.

Incrementing Version

If you don't want to modify any settings on the module and simply want to increment the version (eg: changes done to the program you want to update modules with), you can go to your module's details page and click "increment version" and input the changelog (or leave empty) and submit. Version will increase and update will be available.

⚠️ **GitHub.com Fallback** ⚠️