HOWTO: Inter-plugin communication
#1
As of rev945 I added the functionality needed to call functions on another plugin.
Even though this opens possibilities of deadlocks, these possibilities were already always there so I thought there was no harm in adding this.

To use this, first you need to acquire a reference to the plugin you want to use. You get this reference by asking the plugin manager for a plugin by its name.
PluginManager = cRoot:Get():GetPluginManager()
local CorePlugin = PluginManager:GetPlugin("Core")

Now you have this reference you can call ANY global function in its script.
CorePlugin:Call("HandleReloadCommand")
This will reload all plugins. The HandleReloadCommand is (AFAIK) the only function that does not require an array of strings or a player reference.

This Call() function is very flexible though, it can take any number of arguments and returns any number of values. You can for example do this

-- Plugin1
local Coins = 0
function GetCoins()
	return Coins
end

function AddCoins( Amount, PlayerName )
	Coins = Coins + Amount
	LOG("Added " .. Amount .. " coins to " .. PlayerName );
	return Coins, PlayerName
end

-- Plugin2
function HandleCoinCommand()
	PluginManager = cRoot:Get():GetPluginManager()
	local Plugin1 = PluginManager:GetPlugin("Plugin1")
	
	LOG( "Coins: " .. Plugin1:Call("GetCoins") )
	local NumCoins, PlayerName = Plugin1:Call("AddCoins", 100, "FakeTruth")
	LOG("AddCoins returned: ".. NumCoins ..", ".. PlayerName )
	LOG( "Coins: " .. Plugin1:Call("GetCoins") )
end

When Plugin2:HandleCoinCommand() is called, this should be the output
Coins: 0
Added 100 coins to FakeTruth
AddCoins returned: 100, FakeTruth
Coins: 100

There's one thing you should keep in mind though, and that is that you can only pass integers, booleans, strings and usertypes (cPlayer, cEntity, cCuboid, etc.). This means NO tables, arrays, lists, etc.
Reply
Thanks given by: ThuGie , Taugeshtu , NiLSPACE
#2
Really niceBig Grin,
And amazed at the speed you added it!

Will use it today! haha as its past 12:00 :p.
Reply
Thanks given by:
#3
Have you done any measurements as to the speed of this?

I recall it being mentioned that people wanted to use this as for "code library plugins", but from the underlying code it would seem that the Plugin:Call() call is quite time-consuming, so a code library usage would be a bad idea.
Reply
Thanks given by:
#4
What kind of code library? Doing this 100 times per tick should still be fast I think (I'll do some tests)
However doing things a million times per tick in Lua is not recommended anyway.


Okay doing it 10 times a tick goes by unnoticed. 100 times adds up to 3% of my CPU (including excessive logging and passing 3 arguments) all in debug mode. When I disable the logging it uses 0% of my CPU.

In release mode it uses 0~1% CPU with logging

Looks pretty fast to me, I logged something in the log every time the function was called and that seems to be the biggest bottleneck.


No logging, debug mode 10000 calls per tick uses 0~1% of my CPU
Reply
Thanks given by:
#5
Sounds reasonable Smile Good job.
Reply
Thanks given by:
#6
Thanks, I'm way in over my head though. I have no idea what I'm doing but it seems to work XD
Reply
Thanks given by:
#7
Hehe, are there really plugins that need to call it that much ?Big Grin
Reply
Thanks given by:
#8
Now you should take your time and document all this in the wiki Smile
Reply
Thanks given by:
#9
Is there a way to convert a table to a userdata since userdata can be passed with the Call function. How do you create a userdata object in the first place?
Reply
Thanks given by:
#10
Easiest thing to do is probably concat the table and resurrect it on the other side, asumming it's full of strings or ints.
Reply
Thanks given by:




Users browsing this thread: 9 Guest(s)