Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are
spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the
password reset link.
Due to spam on this forum, all posts now need moderator approval.
Entire forum
➜ MUSHclient
➜ Suggestions
➜ Future versions: Implementing Plugins
|
Future versions: Implementing Plugins
|
It is now over 60 days since the last post. This thread is closed.
Refresh page
Pages: 1 2
| Posted by
| Magnum
Canada (580 posts) Bio
|
| Date
| Sat 25 May 2002 02:29 AM (UTC) Amended on Wed 28 Jan 2015 09:35 PM (UTC) by Nick Gammon
|
| Message
| This conversation has been going on at length in another thread:
http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=1276&page=999999
...but since much of the conversation there is not very relevant, I am starting this new thread.
The purpose of the thread is to discuss how "Plugins" should be implemented in future versions of MUSHclient.
(continuing previous conversation):
The reason I made the distinction between default files and other "include" files, is because default files and the "core"/"mother" world files would be meshed (with the "mother" files over-riding the Default's), where as an "include"/"child" files would be completely independant of it's "mother".
Mother + Default = Default Settings/Values over-ridden
Mother + Child = Settings/Values Co-exist in different namespaces.
The advantage to keeping the "mother" and "child" worlds (namespaces) independent, is that you naturally avoid collision of names and variable or setting values.
The disadvantage, is that cross-communication between a child [sub]world and it's mother could be difficult, and may require extensive [re]programming of the client.
Suppose, for example, you keep them seperate:
You may have a script file you use for all of your worlds, that takes output created by the script for the world, and logs it when sending:
Sub LogandSend (String)
If each include file runs in it's own namespace, then a second include script would not be able to call that subroutine in the first include script.
On the other hand, if a third include script has it's own built in "LogandSend" subroutine (that could be slightly different), then you may run into a problem if the include files are NOT run in their own names space.
Similar problems arise with identical variables, or triggers, aliases, timers with identical names.
(We started calling Variables, Aliases, Triggers, Timers "VATT" for short in the other thread).
It seems the solution may be to let each run in their own space, with special formatting/arguments made to functions to allow them to cross-communicate across the multiple "namespaces". |
Get my plugins here: http://www.magnumsworld.com/muds/
Constantly proving I don't know what I am doing...
Magnum. | | Top |
|
| Posted by
| Nick Gammon
Australia (23,173 posts) Bio
Forum Administrator |
| Date
| Reply #1 on Sat 25 May 2002 04:00 AM (UTC) |
| Message
| Yes, I agree. I thought that the default of separate namespaces might be useful in most cases, but probably should be overridable where you specifically want to communicate between them. For instance, the MXP room descriptions would be outside a namespace, as they are generated by the main client and not a plugin. I was thinking of something like this:
'
' Find my namespace ...
'
world.note world.get_my_namespace ' eg. P1:
'
' Access another namespace ...
'
world.note world.getvariable ("P2:target")
'
' Access a global variable - the leading colon means
' "the global namespace"
'
word.note world.getvariable (":mxp_roomdesc")
(or maybe put mxp variables into their own namespace)
'
' Access an MXP variable (if we did that)
'
word.note world.getvariable ("mxp:roomdesc")
This leads to another interesting point. Should plugins have names? Should those names be unique? If not, conceivably more than one person will make a "wilderness walker" plugin. If that happens, then how does a script find the namespace for a plugin? Maybe based on the file name? At least, the full pathname would need to be unique, but then, how could you predict what the full pathname will be on someone else's PC?
This is the problem that the GID (Global Unique Identifier) idea tries to solve. Perhaps that could be used here.
Each plugin could have a GID and that would uniquely identify it. I could add a script function to generate them (may as well use Microsoft's method). eg.
world.note world.generate_guid ' 12340005-4980-1920-6788-123456789012
Ugly though they may be, at least you could rely upon them to give uniqueness. Then you might see if another plugin was installed, like this:
world.note world.get_namespace_for_guid ("12340005-4980-1920-6788-123456789012") ' eg. "P14:"
|
- Nick Gammon
www.gammon.com.au, www.mushclient.com | | Top |
|
| Posted by
| Magnum
Canada (580 posts) Bio
|
| Date
| Reply #2 on Sat 25 May 2002 04:58 AM (UTC) |
| Message
| Interesting (and annoying) point. :)
Hmm...
Offhand, your idea seems good, though ugly, as you said. I can't think of another method offhand that would be fool proof.
NS_ScriptTools = world.get_namespace_for_guid ("12340005-4980-1920-6788-123456789012")
NS_EQ_Script = world.get_namespace_for_guid ("12340005-4980-1920-6788-789012345678")
Sub Fix_All (TheName, TheOutput, Wildcards)
NS_ScriptTools:LogandSend "say I gotta fix my items."
NS_EQ_Script:Fix_all_items "Fix_All", TheOutput, Wildcards
Can you use variables as part of a call to a subroutine, like that example above? I don't think VBS is set up like that. Would it work if I replaced the ":" with a "." ?
The only other thing I can think of, is that each plugin identify itself (in the XML file - I guess), but that would not be foolproof. I assume you would present an error to the user when they initialized the parent world (if there was a name collision). The user would then be left to handle it on their own, perhaps editing the Plugin XML file, or notifying it's author.
Hmm... |
Get my plugins here: http://www.magnumsworld.com/muds/
Constantly proving I don't know what I am doing...
Magnum. | | Top |
|
| Posted by
| Magnum
Canada (580 posts) Bio
|
| Date
| Reply #3 on Sat 25 May 2002 05:33 AM (UTC) |
| Message
| Oh, did you understand that part about Default files?
Default files get loaded into the namespace of the main world, Plugins do not.
I think this is a handy distinction to make, and allow through the continued use of Default files, rather than dropping them and going with Plugins only (which wouldn't have access to some of the settings available for Defaults).
...or did you intend that a default file would just be a plugin, with everything set for the main world:
<world
wrap_column="125"
>
</world>
Plugins would not be allowed to set that option... but personally, I would want a default file that could set any option. |
Get my plugins here: http://www.magnumsworld.com/muds/
Constantly proving I don't know what I am doing...
Magnum. | | Top |
|
| Posted by
| Nick Gammon
Australia (23,173 posts) Bio
Forum Administrator |
| Date
| Reply #4 on Sat 25 May 2002 07:25 AM (UTC) |
| Message
| Magnum,
The more I think about it I am inclined to go down your path of virtual machines, at least to an extent. I was previously thinking that plugins would share a "global" set of VATT (variables, aliases, triggers, timers) but would avoid name collisions by using a namespace prefix, so that "target" would become "P1:target" for plugin 1.
However this gets pretty tortuous, and then I start asking myself, do you want plugins to save their variables to the world file anyway? Do you want plugins to access/change world settings (eg. world.note colour)?
I am thinking now of moving the VATT lists so that each plugin would have its own lists, thus eliminating namespace problems without specifically having to have a name for them. This could have good side-effects, at possibly the expense of some limitations. How about this for rules for plugins ...
- Plugins are installed in such a way that they are clearly identified as plugins, as opposed to include files. Include files would be for the user of MUSHclient to organise default colours etc. Plugins are for installing scripts written by other people. As such, you want to be protected a bit more from what plugins might do.
- Each plugin has its own set of VATTs (variables, aliases, triggers, timers). Thus, getvariable, setvariable automatically work on the local list.
- Plugins cannot access VATTs from other plugins, or the global set.
- Changes made to VATTs by plugins are not saved. ie. plugins are a read-only resource. eg. they can add/change/delete triggers, variables etc. but this will be a temporary thing
- Plugins are restricted from changing some global settings (eg. player name).
- Plugins are restricted from reading some global settings (eg. player password)
- Some (all?) things that plugins are allowed to change (eg. 'echo input' flag) are saved before the plugin is called and restored afterwards, so that they cannot permanently affect the environment (thus solving the problem of changing note colours etc.)
- Plugins must have a unique ID (eg. a GUID) - although I am not sure that is necessary any more.
- Because plugins would have separate trigger/alias lists, the trigger matching routine would have to "walk" each plugin. I'm not sure what order it would do this, perhaps the order the plugins were loaded. Thus, a high-priority trigger (eg. sequence 10) would only be high-priority for that plugin, not necessarily for all plugins.
|
- Nick Gammon
www.gammon.com.au, www.mushclient.com | | Top |
|
| Posted by
| Nick Gammon
Australia (23,173 posts) Bio
Forum Administrator |
| Date
| Reply #5 on Sat 25 May 2002 07:29 AM (UTC) |
| Message
|
Quote:
Sub Fix_All (TheName, TheOutput, Wildcards)
NS_ScriptTools:LogandSend "say I gotta fix my items."
NS_EQ_Script:Fix_all_items "Fix_All", TheOutput, Wildcards
Not exactly. I was expecting the namespace to be something like "p1:", not a COM reference, and you would use it for GetVariable, however see my previous post which obsoletes that idea a bit. Also, your example tends to assume that you would get a world object, which I was explaining isn't really practical.
Conceivably you might support this sort of syntax:
world.Execute ("P1", "fix_all_items")
This would find the namespace (virtual machine?) P1, and execute the command "fix_all_items" in its script engine.
However, I'm not sure about doing that. |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | | Top |
|
| Posted by
| Nick Gammon
Australia (23,173 posts) Bio
Forum Administrator |
| Date
| Reply #6 on Sat 25 May 2002 07:30 AM (UTC) |
| Message
|
Quote:
Oh, did you understand that part about Default files?
Default files get loaded into the namespace of the main world, Plugins do not.
If you restricted plugins to not allow the <world> tag, that might fix that. |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | | Top |
|
| Posted by
| Magnum
Canada (580 posts) Bio
|
| Date
| Reply #7 on Sat 25 May 2002 08:58 AM (UTC) |
| Message
| Hmm... You said this in the other thread:
Quote:
However I am now planning to implement a subset of the world for the plugins, a subset being the amount reasonably needed to execute a script (eg. its own language) but not things that you can't really have more than one of (eg. default background colour).
I'm not clear about this. Would this be an object?
Ultimately, I think it would be ideal if a scipt could run in either the global space or a plugin space. This would be the most versatile.
In order to do that, I can't help but refer back to the previous thread where we started this conversation.
If you could build a new type of object (lets call it a "plugin" object), that does essentially what I proposed, that might be ideal.
I'm really sorry and a bit frustrated that I don't understand objects perfectly, and COMs.
I wouldn't be surprised if you could build a new plugin object type (essentially cloning most of your global object code), but the tricky party would be doing the three essential things I listed before: Taking output from the global mud and calling the plugin muds code, and taking output from the plugin and sending it to the global object.
I'll put that aside, because I don't want to run in circles. From your numbered list:
2. Excellent, but would each plugin also have it's own settings? If so, you could have independent speedwalk settings, note colours, echo status, etc... (Clone as many settings as you can).
3. That's what I expected as well, though the idea listed above, about having access with an object prefix identifyer might still be a good idea, especially if you can work it to call scripts in other objects too. (We could work without this for a while, and look at it as something to add later, when the basic plugins are running)
4. This is a bit of a tough one to swallow. For example, my EQ script does not load the variables from it's file every time the client is restarted (though it could). There are plenty of other instances though, were it would be more convenient to have the values remain across sessions. My previous recommendation was to store the values back into the Plugin's XML file, though it would become "de-virginized" after doing so...
5. Hmm, I hate pointing out so many conflicts, but... I was thinking it might be nice to create a "login" script, which would probably be a GUI that lets you pick one of your player names, and then the script would log in for you using the appropriate password. Such a script would make it hard for another script to grab the player name, if there was no means to store it globally. Am I correct in that you could currently set another world's setting by doing something like "otherworld.setoption"?
7. If possible, clone and store these independantly, then each plugin could have it's own independant settings!
You said you can't create the plugin in a world object of it's own. I pretty much need to know, before I can make suggestions, can you make a new type of "plugin" object (which is almost the same as a global world object)?
Can you have nested objects? (One inside the other)?
I think you can see where I am going with this... I've already posted more than I intended... I don't want to run in circles, but I can see my own footsteps ahead of me... |
Get my plugins here: http://www.magnumsworld.com/muds/
Constantly proving I don't know what I am doing...
Magnum. | | Top |
|
| Posted by
| Magnum
Canada (580 posts) Bio
|
| Date
| Reply #8 on Sat 25 May 2002 11:55 AM (UTC) Amended on Sat 25 May 2002 12:04 PM (UTC) by Magnum
|
| Message
| Magnum lays across the mattress, staring at the wall... blankly. His eyes close but there is no rest. Suddenly, a light bulb turns on. Oh no! Not another brilliant idea.
I had this thought... I got out of bed and did a search on the internet for "nested object", and found what is probably the perfect example to look at for myself:
http://www3.sympatico.ca/gavin.mckenzie/rebol/xml-object-info.html
Perfect, if I understand it.
Global Object (Contains unique setting that can not be replicated.)
Enviro Object (Contains settings which must be established at least once, but can be replicated.)
Local Object (All other optional settings. [VATTs])
The Global Object contains information such as TCP/IP address, size of scrollback buffer, and other items unique to a connection.
The Enviro Object contains information such as Note Colour, Speedwalk Delay, Echo Status. These settings must be declared at least once, but each "Plugin" can then modify the values and have it's own independant versions. This Object is nested into the Global Object.
The Local Object are basically VATT information. Settings that are empty when a NEW world is established. This Object is nested into the Enviro Object.
OnNewWorld
Load Default settings from Default XML files. (All Objects)
OnLoadWorld
Load Global settings from main XML file. (Overwrite existing data)
Load Enviro settings from main XML file. (Overwrite existing data)
Load Local settings from main XML file. (Overwrite existing data)
Load "Plugin" (Repeat for all Plugins)
OnLoadPlugin
Load Enviro settings from Plugin XML file. (Nested into Main Global Object)
Load Local settings from Plugin XML file. (Nested into this Plugin's Enviro Object)
OnNewPlugin
Load Enviro settings from Main XML file.
Initialize Local settings. (All empty)
Each Enviro Object will only have one Local Object nested inside it.
A Global object may have multiple Enviro Objects nested inside it. One of the Enviro Objects is considered the "Core" Objects belonging to the Main XML file. This lets you use the same load/initialize routine as you do for plugins, just a special case of loading/saving from main XML file.
An Enviro Object is basically your plugin, independant from others.
You save in reverse. Plugin data is stored back in the Plugin's XML file.
Workable? Would be nice. Too bad it probably would practically require a complete re-write of the client, and would not likely be backwards compatable. On the bright side, it would be a good time to do that name change to MUclient you've been thinking about. :) |
Get my plugins here: http://www.magnumsworld.com/muds/
Constantly proving I don't know what I am doing...
Magnum. | | Top |
|
| Posted by
| Shadowfyr
USA (1,792 posts) Bio
|
| Date
| Reply #9 on Sat 25 May 2002 09:39 PM (UTC) |
| Message
| Hmm.. Thinking about it there are also potential problems if a script expects that note color has a certain value but is reset when you leave that script.. If you employed something like Magnum's nesting idea then my main script wouldn't care what the 'current' state of the note color or similar settings are any more than the plugins would. That way there couldn't be any direct interference in either direction. However I do agree that some sort of 'save state' needs to exists for plugins or at least some way to tranfer values to or set root variables so that you can have persistance from one session to another. Without this you can end up with some major problems trying to 'plugin' many existing scripts or even use them properly. A nested system could even have different definitions for custom colors and not interfere with the main world settings, though I am not sure how your output buffer keeps track of what colors are being used in this case. However unlike the basic ansi settings, there is no real reason to not have different custom colors from one plugin to the next.
As for item 9... I wonder if a binary tree of some sort could make 'walking' the scripts easier at least for things like aliases, since you could have pointer entries added for the tree each time an alias gets added that say starts with a-c, then when something is typed you just hunt the tree for pointers to that first letter and 'only' check those plugins that contain such an alias. Unless someone creates aliases that use every number and letter possible at least once this would probably speed things up quite a bit. I can't see any easy way to do that for trigger unfortunately. :P | | Top |
|
| Posted by
| Nick Gammon
Australia (23,173 posts) Bio
Forum Administrator |
| Date
| Reply #10 on Sun 26 May 2002 12:51 AM (UTC) |
| Message
|
Quote:
I'm not clear about this. Would this be an object?
I wasn't envisaging it. :)
Let me clarify, that when I first started adding COM to MUSHclient, I wasn't really an expert either (probably still aren't) and if I was, might have done it somewhat differently.
For example, a trigger should probably be a COM object, with properties. So, this sort of thing might work (it doesn't now) ...
dim aTrigger
set aTrigger = world.GetTrigger ("x")
world.note aTrigger.Name ' trigger's name
world.note aTrigger.Match ' match text
aTrigger.Enable ' enable myself
You are right, what you are proposing would be a big change, and frankly I want to not spend weeks tweaking whether nor not something is a property of a COM object or not, but make changes that might actually be useful for people playing a MUD (eg. a HP status bar). |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | | Top |
|
| Posted by
| Magnum
Canada (580 posts) Bio
|
| Date
| Reply #11 on Sun 26 May 2002 02:16 AM (UTC) |
| Message
| Hmm... I'm not sure where to go from here. Right this moment, the whole endevour is feeling a little futile. It would probably just be easier to write a standalone program to install plugins using the current "workaround" method. Indeed, if you wanted to take a vacation from this whole idea, I would understand...
If you wanted to, you could slowly move the client in that direction, casually refining code with "Plugins" something to aim for another time. |
Get my plugins here: http://www.magnumsworld.com/muds/
Constantly proving I don't know what I am doing...
Magnum. | | Top |
|
| Posted by
| Nick Gammon
Australia (23,173 posts) Bio
Forum Administrator |
| Date
| Reply #12 on Sun 26 May 2002 02:40 AM (UTC) |
| Message
|
Quote:
You save in reverse. Plugin data is stored back in the Plugin's XML file.
I don't like the idea of writing to plugin files. It seems to me the whole idea of include files (including plugins) is to share them between worlds. Thus, if you shared a plugin of any sort between two worlds, and it stored data in the plugin file (when? when the world saved?) then the only copy that really persists is the last one written.
Also, you have the issue of the plugin write routine having to reconstruct the plugin source (put the scripts back etc.).
No, no, I don't think that will work.
Maybe, have a "plugin save" file, where a plugin can remember its state. That might need a unique name, because you will have multiple plugins and multiple worlds. The mind boggles a bit thinking about it.
Probably simpler to let plugins save variables to the main world file, but then you have the issue of "your world file has changed - do you want to save it?" when you can't remember making any changes. |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | | Top |
|
| Posted by
| Nick Gammon
Australia (23,173 posts) Bio
Forum Administrator |
| Date
| Reply #13 on Sun 26 May 2002 03:25 AM (UTC) |
| Message
|
Quote:
Right this moment, the whole endevour is feeling a little futile. It would probably just be easier to write a standalone program to install plugins using the current "workaround" method. Indeed, if you wanted to take a vacation from this whole idea, I would understand...
I think I can make something work quite soon, ie. this week. Then some keen plugin writers can test it. :)
For instance, the recent post I did for someone who wanted to tell his friend where some other player was, would make a nice little plugin. |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | | Top |
|
| Posted by
| Shadowfyr
USA (1,792 posts) Bio
|
| Date
| Reply #14 on Sun 26 May 2002 03:36 AM (UTC) |
| Message
| Well.. For one if the plugin layer is in a seperate COM, then COM provides a means to save the state of the object anyway. Though not sure how or if it would work in this case.
As to the idea of saving it in the main world... It bugs me already that I have to tell the dang thing 'yes save the bloody variables' every time as it is. Some sort of persistance in needed though since some data 'must' be persistant in certain types of plugins and relying on writing the data to a file is not something everyone knows how to do. Not to mention that variables are persistant regardless, while a file needs to be intentionally updated, leaving you open to loosing the current state in process. This is one reason why saving the state probably wouldn't work anyway.
Maybe if it was simply explicitly stated that plugins must provide their own persistance methods, but... OF course on way to go would be to use a simpler ID method. Two bytes probably are sufficient, since who is going to plugin 65535 different pieces of code from other people. lol The use the ODBC to store the variables from plugins. All windows systems should have ODBC and a few basic database types installed by default, they have to or programs like Quickview wouldn't be able to view Excel files. Doing that would eliminate the saving of them into the world file and still support persistance, since each access would save/retrieve from the database. Just an idea anyway...
Either a way needs to exist or there has to be a specific statement to the effect that it isn't directly supported, but that makes such plugins a bit harder to use well, it also begs the question of what happens if you made the plugin and 'intended' it to be able to communicate with your main script. That is the most serious issue with regard to the problem. | | Top |
|
The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).
To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.
67,340 views.
This is page 1, subject is 2 pages long: 1 2
It is now over 60 days since the last post. This thread is closed.
Refresh page
top