This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
theoriginalbit's profile picture

[API] The Most Advanced Screensaver API yet!

Started by theoriginalbit, 18 December 2012 - 06:15 PM
theoriginalbit #1
Posted 18 December 2012 - 07:15 PM
Thread Closed in favour of merging to a single, easier to manage, thread and website see signature for more info
SpoilerScreensaver API

Old Version:
Spoilerv2.0

Download: [ sorry no download, pastebin deleted it and my repo became corrupted, what are the odds hey. :(/> ]

Already being used by:
  • NDF-OS by NDFJay ( He requested a custom screensaver! )
  • KREOS by kornichen ( He is calling it the Wallpaper API lol )
Usage:
SpoilerAfter loading the screensaver as an API you run it by calling the following functions.

This is the main function of the API

function run(render_mode, require_login, unlock_password, hash_func)

For more information on render modes see the section "New! And Awesome!"

Now lets give some quick examples of how to use this function

If you wish to display the screensaver without the user having to login to exit

screensaver.run(render_mode, false) -- where screensaver is the filename of my api and render_mode is one of the modes listed further down

If you wish the user to have to login and have a plain text password

screensaver.run(render_mode, true, password) -- where screensaver is the filename of my api and render_mode is one of the modes listed further down

If you wish the user to have the login and have a hashed password


screensaver.run(render_mode, true, password, hash_function_pointer) -- where screensaver is the filename of my api and render_mode is one of the modes listed further down

Valid display modes for this version are (more coming soon…)

"bouncing_ball",
"full_flash",
"dots",
"horizontal_lines",
"vertical_lines"

An example of calling with a hashed password is as follows (this uses example uses the Sha1 API by CoolisTheName007 and can be found here http://www.computerc...native-bit-api/ ) :

os.loadAPI("hashAPI")
pword = "c591b74cf8fde7125402510ff77128c957f3b36f" -- this could be loaded from file, like in my door lock program

screensaver.run("dots", true, pword, hashAPI.Sha1)

This works by passing a reference to the API's function (in example this is Sha1) to my API for use.

NEW! And Awesome!
SpoilerThe renderer has had a major overhaul. The way to call this API has not changed. However I now have some more advanced checking for errors and a more advanced system for getting the renderers and updaters.


function run(render_mode, requireLogin, unlock_password, hash_func)

This update brings 3 new functions:


function registerRenderModePrepacked( key, render_mode_packed )

function registerRenderMode( key, render_func, update_func, update_freq, display_name )

function getRenderModeTable()

The first 2 functions (more on the 3rd later) allow you to register a new render mode with the API.

"What is a render mode?" A render mode is used by the API to find which screensaver it has to draw on the screen, a render mode contains 4 values, a function pointer to the function that renders, a function pointer to the function that updates what is rendered, how long to wait before updating again, and its display name (more on these later).

The first of these two functions requires that you pass in 2 parameters. The first parameter is the 'in code' name of the render mode, this is what you use later to run it. The second parameter must be a render mode table containing all the information listed in the previous paragraph. Note: It will error if you don't give it a table.

The second of these functions requires that you pass in all the information and it will pack it up into a table for you before adding. Note: None of these values can be nil.

Note: To pass a function as a pointer to the registerRenderMode( ) function you type the name of the function in, do not put the ( ) at the end. Don't worry when your testing if it isn't a function it will error and tell you.

"Ok so these values in the render mode… can you give more detail please?"

The first value is what is called a function pointer and it must point to the function that will render what you want your mode to display.
Note: A function pointer is a reference to a memory location in RAM that the function has been loaded into. This is used a few times within this API for the render, update and hashed password checking. For how to pass a function pointer read the note in the previous section)

The second value is also a function pointer, this points to the function that is in charge of updating what is displayed, for example moving a ball around the screen.
Note: Even if you don't need to update the render you still need to pass a function pointer however just make the function empty. Example:

function updateMyRenderMod()
end

The third value is a number to represent in seconds how long you want the API to wait before calling the update function again.
Note: This can be a decimal number. To if you have an empty update you must still provide a number, just set it big, like 7680 seconds (128 minutes) or something equally as ridiculous (not too big though)

The final value while you may not use it is still required. This is where the 3rd function that has been added comes into play. This function will return the table of render modes so that in your OS, or whatever your making, if you decide to make a settings panel for them to customise the screen saver they can see a useful name. E.g. Instead of seeing "full_flash" in the list they would see "Flashing Screen"

"Why would I want to register a render mode?"

Well the answer is simple, by allowing you to specify your own render mode I open up a world of screensaver options. The way the code works is very dynamic, through a normal render loop it only clears the background and writes the minecraft time in the bottom corner, it then calls the renderer for the current 'render mode' to have the rest drawn, this means you could have it draw anything you want, even an image you have saved from NPaintPro using
paintutils.drawImage(image, x, y)
. So go to it and have fun. P.S. If you think your custom renderer is cool, I would love to see it, take a screenshot and show me, and if I agree, I'll get your code and make it an option for all! (crediting your work of course)

Note for custom render/updater writers:

Please do NOT use any sleep, read, pullEvent, pullEventRaw or anything the similar in your render or updater functions, this can cause serious problems with timing and/or break the program all together. If you wish to change what is rendered after a given time please use the update function to do this and supply that given time with the update_freq parameter as the update functions are called only after the update_freq time has passed.

Still not getting it? Read this spoiler:
SpoilerOk so explanation of the custom render modes. There are now 3 functions that you must implement in your program to allow the screensaver api to correctly render your custom images.

the first of these 3 functions is the data structure function. The data structure function must define your image, colors, coordinates, or whatever your custom screensaver will need. This data MUST be stored into a table, as the way Lua deals with tables it makes updating and rendering your data structure a dream as you can update details without actually having to return the data structure after you have modified it. Here is an example from the current "bouncing ball" render mode.



local t = {}

t["x"] = sizeX / 2
t["y"] = sizeY / 2
t["color"] = colors.red
t["moveX"] = 1
t["moveY"] = 1

return t
end


this function creates a table 't' and stores 5 variables in it. the first 3 are the x and y position and the color that the render function will use later. The last 2 variables defined in the structure is used later in the update function.

the second function that needs to be defined is the function that is in charge of rendering. this function MUST accept one parameter (which is the data structure). Please note that this is only in charge of rendering YOUR image to the screen, nothing else as the API deals with it all. An example is again using the bouncing ball render mode.



local function render_ball( data )
term.setCursorPos( data["x"], data["y"] )
term.setBackgroundColor( data["color"] )
write(" ")
end


Note that this ONLY renders our ball to the screen!

The last function to be defined is the update function. this function is in charge of modifying your data structure every time the update timer has completed. This also takes in one parameter of the data structure. an example of the ball one is provided below



local function update_ball( data )
if data["x"] >= sizeX then
data["moveX"] = -1
elseif data["x"] <= 2 then
data["moveX"] = 1
end

if data["y"] >= sizeY then
data["moveY"] = -1
elseif data["y"] <= 2 then
data["moveY"] = 1
end

data["x"] = data["x"] + data["moveX"]
data["y"] = data["y"] + data["moveY"]
end

in this function notice that we update the moveX and moveY variables if the ball has gone outside the screen bounds and then increments the x and y based on the movement variables. This gives us the effect that the ball is 'bouncing' around the screen. Note that we do not actually need to return the data structure as when we modify it actually modifies our original table.

The order these functions are called in the code are as follows:
  • Data Structure function (outside main loop)
  • Render function (in main loop)
  • Update function (in main loop after update timer has completed)
When registering a new render mode you must call one of the following 2 functions


function registerRenderModePrepacked( key, render_mode_packed )
function registerRenderMode( key, render_func, update_func, data_struct_func, update_freq, display_name )


the first function will register a pre-packed render mode this means that you have already packaged the render mode into a table for the API. The order to package into the table are as follows:
  • Render function pointer
  • Update function pointer
  • Data structure function pointer
  • How often update function is called
  • The display name of the render mode (i.e. "Bouncing Ball") (this can be used to display a GUI of available render modes to users, a table of all render modes can be retrieved by calling the function getRenderModeTable() in the API and getting index 6 of the entries in the returned table )
The other parameter is the key, this is what you use when calling the screensaver api, for example if we register the bouncing ball with the key "kbb" then you must pass "kbb" as the render mode into the run function.

the second of the functions to register a render mode will package up the functions for you, if you don't feel like doing it yourself, so just pass everything as parameters and the api will do the rest. dont forget that key though :)/>

Note: the api will notify you of conflicting keys

Note 2: when passing the function pointers to the API remember to type the function name, that is all, do not put the ( ) at the end. :)/>




Requirements:
Spoiler
  • Advanced Computer
  • ComputerCraft 1.4.1 or above


Features:
Spoilerv2.0
  • Has 5 different drawing modes (more coming soon)
  • Has optional ability to require login
  • Has option to allow hashed passwords for login
  • Times out back to the screensaver after 10 seconds of no key presses on login
  • Custom renderers!
Next Update:
  • Add more drawing modes, suggestions please!


Changelog:
Spoilerv2.0
  • NEW! Render has been overhauled! You can now make custom renderers. Read "Usage" and "New! And Awesome!" for more details
  • Code re-write
v1.0.1
  • Bug fixes and feature fix (was half done, oops): Now times out back to the screensaver after 10 seconds of inactivity
v1.0
  • Initial release


Making appearances in OS's near you soon :)/>


Don't like my screensaver renders? Think that you can do a better one? Well just put the renderer and updater in your program and then register* it with the API and your done! You can now use your custom one! I'd love to see what you can come up with! So if you think yours is awesome why don't you take a screenshot and post it here, and if I agree I'll add it into the public release (crediting you and your work!)
Edited on 24 January 2013 - 11:55 PM
anonimo182 #2
Posted 19 December 2012 - 02:54 PM
It isn't working… any mode isn't working
theoriginalbit #3
Posted 19 December 2012 - 02:59 PM
It isn't working… any mode isn't working

What is happening, can't suggest a fix unless I know whats going wrong.

EDIT: Both KREOS and NDF-OS do not have any issues, so please I need more details
Lyqyd #4
Posted 26 January 2013 - 03:44 AM
Locked by request.