Author Topic: Plugin System Layout  (Read 3668 times)

0 Members and 2 Guests are viewing this topic.

Offline Netham45

  • LV11 Super Veteran (Next: 3000)
  • ***********
  • Posts: 2103
  • Rating: +213/-4
  • *explodes*
    • View Profile
Plugin System Layout
« on: July 12, 2011, 11:14:32 pm »
I've been toying with the idea of a plugin system for quite some time for both client and server, and eeems was asking me about it earlier, so I thought I'd document some of what I came up with.

Client-sided plugins(for the web client, javascript based):

3 return values:
PLUGIN_CONTINUE - Continue parsing through all plugins, and allow OmnomIRC to display this message normally
PLUGIN_NO_OUTPUT - Continues parsing through all plugins, but causes OmnomIRC not to display the message
PLUGIN_BREAK - stops at this plugin, does not reach any others

Message types:
OnLoad - Fired when OmnomIRC loads - No vars

OnJoin - Fired when someone joins the current channel - Name, Channel
OnPart - Fired when someone parts the current channel - Name, Reason, Channel
OnQuit - Fired when someone quits the current channel - Name, Reason
OnKick - Fired when someone is kicked from the current channel - KickedName, KickerName, Reason, Channel
OnMode - Fired when someone changes modes in the current channel - Name, Modes, Channel
OnTopic - Fired when someone changes the topic in the current channel - Name, Topic, Channel

OnMessage - Fired when someone sends a message in the current channel - Name, Message, Channel
OnMessageHighlight - Fired when someone sends a message that highlights the user in the current channel - Name, Message, Channel
OnAction - Fired when someone sends an action in the current channel - Name, Message, Channel
OnActionHighlight - Fired when someone sends an action that highlights the user in the current channel - Name, Message, Channel

The layout of the javascript plugins will be something like this:
Code: [Select]
function pluginInfo()
{
     pluginName = "OnJoin Example";
     pluginVersion = "0.01";
     minOmnomIRCVersion = "2.2";
}
function OnJoin()
{
     alert(name1 + " has joined " + channel);!
     return PLUGIN_CONTINUE;
}
function Options()
{
     document.write('<a href="#" onclick="DoThis();">Option!</a><br/>');
}
function DoThis()
{
     alert("You clicked my option!");
}
registerPlugin();
registerOnJoin();
registerOptions();


There will be an option in the options page for loading them, and they will be able to output options to the options page. The plugins themselves will be largely responsible for managing their cookies and own options.

Here's what a mockup of the OmnomIRC-side loading code will be:
Code: [Select]
function loadPlugins()
{
     for (var i=0;i<pluginList.length;i++)
     {
          //Warning: PSEUDO CODE!
          scrtag = new script;
          scrtag.src = pluginList[i];
          body.appendChild(scrtag);
     }
}
function registerPlugin()
{
     if (minOmnomIRCVersion > OmnomIRCVersion) alert("NOEP.");
     loadedPluginList[] = Array(pluginName,pluginVersion,minOmnomIRCVersion);
}

function registerOnJoin()//Replicate for all other events
{
     onJoinPlugins[] = Array(loadedPluginList.length,OnJoin);
}

function doOnJoin(name,channel)
{
     name = name;
     channel = channel;
     var output = true;
     for (var i=0;i<onJoinPlugins.length;i++)
     {
          var result = (onJoinPlugins[i][1])();
          if (result != PLUGIN_CONTINUE) output=false;
          if (result == PLUGIN_BREAK) break;
     }
     return output;
}

Server-side plugins!
They will have the same events for the time being.
Code: [Select]
//OmnomIRC v2.2 OnJoin,OnLoad
//Example Plugin
//0.01

function OnJoin()
{
     global $name,$channel;
     die("$name has joined $channel!");
     return PLUGIN_BREAK;
}

function OnLoad()
{
     echo "BLARG!!!!!!!!!!!!!!";
     return PLUGIN_CONTINUE;
}

And, for the server to load them (this has to be done each page run, I'm not entirely sure how efficient it will be)
This is pseudocode too.
Code: [Select]
foreach ($file in $directory)
{
     include($file);
     if (doesOnLoad($file))
     {
          OnLoad();
     }
     if (doesOnJoin($file))
     {
          OnJoin();
     }
}
etc...


Thoughts/comments? :D
« Last Edit: November 02, 2011, 04:30:33 am by Netham45 »
Omnimaga Admin

Offline Eeems

  • Mr. Dictator
  • Administrator
  • LV13 Extreme Addict (Next: 9001)
  • *************
  • Posts: 6268
  • Rating: +318/-36
  • little oof
    • View Profile
    • Eeems
Re: Plugin System Layout
« Reply #1 on: July 12, 2011, 11:26:28 pm »
So thoughts for an alternative layout for the javascript plugin:
pastebin code
So basically instead of registering it, have it in a variable Plugins and just loop through the array when you want to search for stuff. So to get the onjoin event for the plugin you would do this inside the loop. ( i==the iteration in the loop )
Code: [Select]
if(Plugins[i].join!=undefined){
  Plugins[i].join();
}
This way you don't have to call functions to register them, they register themselves. They also use up less function names this way. You could do a little check after loading all the plugins to remove all the ones that don't have the right version info.
So this way a ton less registering is being done and it's all there for you to work with in the end :)

EDIT: Also, you could probably come up with a better way to do options. I'd have to think up how to do it though, but I already have a pretty good idea of what I think a better way could look like.
« Last Edit: July 12, 2011, 11:28:22 pm by Eeems »
/e

Offline Netham45

  • LV11 Super Veteran (Next: 3000)
  • ***********
  • Posts: 2103
  • Rating: +213/-4
  • *explodes*
    • View Profile
Re: Plugin System Layout
« Reply #2 on: July 12, 2011, 11:29:59 pm »
I was being lazy with the options, and yea, your method of it does look like it'll work better.
Omnimaga Admin

Offline Eeems

  • Mr. Dictator
  • Administrator
  • LV13 Extreme Addict (Next: 9001)
  • *************
  • Posts: 6268
  • Rating: +318/-36
  • little oof
    • View Profile
    • Eeems
Re: Plugin System Layout
« Reply #3 on: July 12, 2011, 11:33:04 pm »
Thanks :) Why I came up with that type of system so quickly is because of a ton of work with dynamic javascript stuff that I've done in the past, coupled with the fact that I use jQuery a lot and some of it's source it like that :P

Anywho, my options idea:
For options have it pass another variable to it in the plugin entry. So:
Code: [Select]
options: {
  optionName:{
    type: 'bool',
    default: true
  }
},
At startup it would then quickly parse all the options from the plugins into a Options variable or something for speed and then every time you open the options screen it would dynamically create it for you based on the current setting and what type of option it is. So you can have booleans, text, numbers etc

EDIT: Oh and for getting the options name, this might be useful :P http://pietschsoft.com/post/2008/02/28/JavaScript-ForEach-Equivalent.aspx just in case you don't know about it. ( I'm pretty sure it works with objects )

EDIT2: yep it works!
Code: [Select]
>>> a = {t:'adlfj',bla:'herro'}; for(var i in a){console.log(i+": "+a[i]);}
t: adlfj
bla: herro

EDIT3: oh and
Code: [Select]
>>> a = {t:'adlfj',bla:'herro'};a[0]='test';for(var i in a){console.log(i+": "+a[i]);}
t: adlfj
bla: herro
0: test

EDIT4: I decided to write up a quick example of a plugin handler. Although it's missing some of the stuff for getting settings, and for displaying the options panel, but all the core stuff is there
http://pastebin.com/CnnhEgcH

EDIT5: bug fixes/more comments http://pastebin.com/FgyG7v3p
« Last Edit: July 13, 2011, 12:28:56 am by Eeems »
/e