Events and polling between plugins

Posted by Victorious on Thu 16 Jun 2016 03:31 PM — 8 posts, 34,748 views.

#0
Hi,

I notice that when developing plugins for a mud, there is common information that most of them would need like information from the prompt. There is duplication when each plugin has a trigger so that it can get that information. I'm thinking of having 1 plugin collect all the incoming info that could be useful to other plugins, and somehow sharing it.

1. (polling) This centralized plugin would have an internal table keeping track of the incoming info, e.g what is the current health. How can I allow other plugins to get to this information, preferably in such a way that other plugins wouldn't accidentally modify it?

2. (events) My plan is to have each event's info stored in a table, serialize that into a string and have it broadcasted with broadcastPlugin. Guess this relates to Q1 - I'd want this plugin to have some sort of constant enumeration that maps the message ID to the type of event for readability, and need other plugins to be able to get at it.

3. Is this approach the best way of achieving what I describe?
USA #1
I would think http://gammon.com.au/forum/bbshowpost.php?id=4534&page=1 would be a good starting point for what you're trying to achieve.
USA Global Moderator #2
For 1, you can use the CallPlugin interface to externally run a data retrieval function and have it return the value.
#3
BroadcastPlugin and CallPlugin is working out nicely - thanks :)

When I use the serialize functions, the output I get is something like this:

{
hp = 5,
mn = 10,
...
}

If ran through the loadstring function, I think this creates an anonymous table. I'd like to be able to do something like this, from the consuming plugin:

function getPlayerInfo()
local returnCode, playerTableStr = CallPlugin (PLUGIN_ID, "getPlayerInfo")
return loadstring(playerTableStr)
end

If i understand loadstring right, this doesn't return a table. How can I do so?
USA Global Moderator #4
loadstring creates a function which you then have to call.

loadstring("foo = {b=4}")()
require "tprint"
tprint(foo)

or

foo = loadstring("return {b=4}")()
require "tprint"
tprint(foo)
Amended on Sat 18 Jun 2016 01:29 PM by Fiendish
#5
Perfect, that worked like a charm.

Just to check, the performance impact of the serialization/deserialization and cross-plugin communication (via CallPlugin and BroadcastPlugin) should be minimal and won't be an issue? Wanted to make sure before using this extensively.
Australia Forum Administrator #6
It's pretty fast. Since the core work in loadstring is done in the C code Lua is written in, it is likely to be faster than anything you would write in Lua.
Australia Forum Administrator #7
There's quite a bit of detail about serializing here:

http://www.gammon.com.au/forum/?id=4960

I did some timings on the table mentioned in that thread (mobs table).

The timings vary a bit (probably due to garbage collection) so I took an average of 500 iterations. The results are:

  • serialize.save -> 60 µs
  • serialize.save_simple -> 3 µs
  • loadstring -> 27 µs


That's pretty quick. YMMV due to processor speeds, operating systems, size of table etc., still that is indicative. You might want to use save_simple as that is considerably faster than save.




Code to reproduce:


mobs = {}
  mobs.worm = {}
    mobs.worm.attacks = {}
      mobs.worm.attacks[1] = "bite"
      mobs.worm.attacks[2] = "poison"
    mobs.worm.treasure = {}
      mobs.worm.treasure[1] = "food"
      mobs.worm.treasure[2] = "knife"
    mobs.worm.name = "gordon"
    mobs.worm.gold = 15
    mobs.worm.location = "underground"
    mobs.worm.hp = 4
  mobs.kobold = {}
    mobs.kobold.treasure = {}
      mobs.kobold.treasure[1] = "sword"
      mobs.kobold.treasure[2] = "gold"
      mobs.kobold.treasure[3] = "helmet"
    mobs.kobold.name = "killer"
    mobs.kobold.gold = 5
    mobs.kobold.location = "city square"
    mobs.kobold.hp = 22

require "serialize"

local start
local s
local time_taken
local total
local iterations = 500


total = 0
for i = 1, iterations do
  start = utils.timer ()
  s = serialize.save_simple ("mobs")
  time_taken = utils.timer () - start
  total = total + time_taken
end -- for

print (string.format ("Time taken to serialize.save_simple = %0.3f", total / iterations  * 1e6))

total = 0
for i = 1, iterations do
  start = utils.timer ()
  s = serialize.save ("mobs")
  time_taken = utils.timer () - start
  total = total + time_taken
end -- for

print (string.format ("Time taken to serialize.save = %0.3f", total / iterations * 1e6))




total = 0
for i = 1, iterations do
  start = utils.timer ()
  assert (loadstring (s)) ()
  time_taken = utils.timer () - start
  total = total + time_taken
end -- for

print (string.format ("Time taken to loadstring = %0.3f", total / iterations  * 1e6))