Variable passing question

Variable passing question

Discuss Lua based Spring scripts (LuaUI widgets, mission scripts, gaia scripts, mod-rules scripts, scripted keybindings, etc...)

Moderator: Moderators

Post Reply
Voidranaut
Posts: 47
Joined: 20 Dec 2009, 21:16

Variable passing question

Post by Voidranaut »

I am trying to pass a variable from synced to unsynced code here is the code

oh it is slighty modded from something zwzsg wrote but it said public liceance I hope thats ok

Code: Select all

function gadget:GetInfo()
   return {
      name = "KeyCatchEx",
      desc = "Show how to catch keypresses in gadgets",
      author = "zwzsg",
      date = "21st of January 2010",
      version = "1.0",
      license = "Public Domain",
      layer = 0,
      enabled = true
   }
end

local up_arrow,down_arrow,right_arrow,left_arrow,enter,space,dee = 273,274,275,276,13,32,100 --does nothing? there for my benifit?

local message_identifier = gadget:GetInfo().name..": " --when called will tak "KeyCatchEx" onto variable

if (gadgetHandler:IsSyncedCode()) then--SYNCED

   function gadget:RecvLuaMsg(msg,player) --LuaMsg must be a place were messages can be sent to be scrootanized by all the gadgets

      local MsgForMe=string.match(msg,message_identifier.."(.*)")

 --main purpose is to make sure the message it reads in luamsg is from "KeyCatchEx"

      if MsgForMe then 
         Spring.Echo("Synced recieved a message from unsynced:")
         Spring.Echo(MsgForMe)
      end
   end

[color=#FF0000]local function blockless(u) 
	Spring.SetUnitBlocking(u, false)
 end[/color]	

else--UNSYNCED

   function gadget:KeyPress(key) 

--key scope exists within the function

	if( key == 121 ) then
		for _,u in ipairs(Spring.GetAllUnits()) do
			Spring.Echo( u )
			[color=#FF0000]blockless(u) [/color]
		end
	end


  	Spring.Echo("Key "..key.." pressed in unsynced")

 --do the .. commands work same as + commands in say java when using the System.out.print(""); command?

	--key works as a variable only because of the scope (fact it was declaired in the function right?)	

      	Spring.SendLuaRulesMsg(message_identifier..key.." was pressed")
   end

end

the red areas are my trouble zone

the error displayed looks like this

Code: Select all

14680
LuaRules::RunCallIn: error = 2, KeyPress, [string "LuaRules/Gadgets/commandadditiontets.lua"]:38: attempt to call global 'blockless' (a nil value)
I am sure I am doing something backwards or totaly wrong ... u is not nil it was echoed as 14680 so I am wondering two things

question 1) what I did wrong

question 2) what exactly is the error trying to say is wrong? because I think I am missinterpriting its meaning
Last edited by Voidranaut on 22 Jan 2010, 06:31, edited 1 time in total.
User avatar
SpliFF
Posts: 1224
Joined: 28 Jul 2008, 06:51

Re: Variable passing question

Post by SpliFF »

Voidranaut wrote:question 1) what I did wrong
you didn't read the error properly
Voidranaut wrote:question 2) what exactly is the error trying to say is wrong? because I think I am missinterpriting its meaning
it's trying to say you don't have a global function called 'blockless'.

The reason is you declared it 'local', inside another scope (the top of your if / else block). Make it global.

EDIT: On second thoughts you're doing it all wrong. You can't just call from synced / unsynced like that. I have an explanation of message passing in my Spring Lua Guide

EDIT AGAIN: Ok I can see you're doing some things right but you're codes a mess, it's hard to tell (please use bbcode formatting for code too). The short answer is you've defined blockless in the wrong place and it isn't really required anyway. You just need to pass a message to RecvFromUnsync then call Spring.SetUnitBlocking(u, false) in there. The main thing is you'll need to pass the unit id with your message (and check the unit is still alive first).
Last edited by SpliFF on 22 Jan 2010, 06:31, edited 1 time in total.
Voidranaut
Posts: 47
Joined: 20 Dec 2009, 21:16

Re: Variable passing question

Post by Voidranaut »

oh awsome thanks for the source of info :)

will get to reading

thanks
User avatar
SpliFF
Posts: 1224
Joined: 28 Jul 2008, 06:51

Re: Variable passing question

Post by SpliFF »

The guide is still a bit incomplete. I looked and it doesn't really describe Unsynced->Synced very well. Have a look for a gadget that implements a synced event from unsynced for a better answer.
Voidranaut
Posts: 47
Joined: 20 Dec 2009, 21:16

Re: Variable passing question

Post by Voidranaut »

ok will do
Voidranaut
Posts: 47
Joined: 20 Dec 2009, 21:16

Re: Variable passing question

Post by Voidranaut »

in my treck for the answers I have stumbled to a few halts

probleam1): so on that document you posted the link too it says on page 13 (near bottom) that synced code cant read from unsynced code... it dyscribes it as a one way pipe

question1): is this document from a time before it was possible to send variable from unsynced to synced? or am I miss reading/understading the limitation its dyscribing?

probleam2): I have looked in all the gadgets I have at my disposal and I cant find a good example of an unsynced variable going into synced code (most of my gadgets dont even ahve an unsynced setion)

question2): is there a good place to find the command you are dyscribing?

probleam 3): I tried the code with SendToSynced() and RecvFromUnsynced() and it is giving me error messages that segjest that they are entirely unrecognized... as I check my LuaRules/callins.lua I dont see any commands that discrible sending variables from unsynced to synced code

question3): is it possible that I am extreamly mistaken or just need an updated callins.lua file? or do these commands actaully not exist as all the info above segjests? (most likely I am confused)
User avatar
smoth
Posts: 22309
Joined: 13 Jan 2005, 00:46

Re: Variable passing question

Post by smoth »

you may want to start posting these queries in the lua forum.
Voidranaut
Posts: 47
Joined: 20 Dec 2009, 21:16

Re: Variable passing question

Post by Voidranaut »

thank you

I did not know i was posting in the wrong spot sorry

I dont want to clutter up the forum with the same quesiton in two spots is there a way to just move it all? or should I just repost on a new thread?
User avatar
smoth
Posts: 22309
Joined: 13 Jan 2005, 00:46

Re: Variable passing question

Post by smoth »

report your first post. select off topic. In the notes tell the moderator you want it moved to the lua forum.

No worries.
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: Variable passing question

Post by Argh »

probleam1): so on that document you posted the link too it says on page 13 (near bottom) that synced code cant read from unsynced code... it dyscribes it as a one way pipe

question1): is this document from a time before it was possible to send variable from unsynced to synced? or am I miss reading/understading the limitation its dyscribing?
It was probably before the LuaMessage system was introduced.

Either way, it should be updated; you can communicate both ways.
probleam2): I have looked in all the gadgets I have at my disposal and I cant find a good example of an unsynced variable going into synced code (most of my gadgets dont even ahve an unsynced setion)

question2): is there a good place to find the command you are dyscribing?
Spring.SendLuaRulesMsg("my string here") is the correct callout to use.
probleam 3): I tried the code with SendToSynced() and RecvFromUnsynced() and it is giving me error messages that segjest that they are entirely unrecognized... as I check my LuaRules/callins.lua I dont see any commands that discrible sending variables from unsynced to synced code

question3): is it possible that I am extreamly mistaken or just need an updated callins.lua file? or do these commands actaully not exist as all the info above segjests? (most likely I am confused)
There is no SendToSynced(), so far as I know. SendToUnsynced(), yes- but not in reverse. Use Spring.SendLuaRulesMsg()
Kloot
Spring Developer
Posts: 1867
Joined: 08 Oct 2006, 16:58

Re: Variable passing question

Post by Kloot »

probleam1): so on that document you posted the link too it says on page 13 (near bottom) that synced code cant read from unsynced code... it dyscribes it as a one way pipe

question1): is this document from a time before it was possible to send variable from unsynced to synced? or am I miss reading/understading the limitation its dyscribing?
No, you misunderstand a bit. It is a general limitation due to the engine's design that synced code can never *read* unsynced data directly (this has always been true, and is not an instance of SpliFF's guide predating anything). However, unsynced data can *become* synced by sending it via the server to all Spring clients, for which there is an unsynced SendLuaRulesMsg function. Similarly, unsynced code can never *write* synced data, only read it (or receive it, by reacting to RecvFromSynced events that are triggered by synced code running the SendToUnsynced callout).
It was probably before the LuaMessage system was introduced
Wrong, but even if it was, that's not the point.
User avatar
zwzsg
Kernel Panic Co-Developer
Posts: 7052
Joined: 16 Nov 2004, 13:08

Re: Variable passing question

Post by zwzsg »

Voidranaut wrote:question 1) what I did wrong
You declared blockless only in the synced part, yet call it from the unsynced part.


Voidranaut wrote:question 2) what exactly is the error trying to say is wrong? because I think I am missinterpriting its meaning
14680
LuaRules::RunCallIn: error = 2, KeyPress, [string "LuaRules/Gadgets/commandadditiontets.lua"]:38: attempt to call global 'blockless' (a nil value)
LuaRules: The error is in gadget. Or in one of the /LuaRules/ files, I dunno what would be the difference.
KeyPress: The error happens inside the function named KeyPress
LuaRules/Gadgets/commandadditiontets.lua: This is the file the error is happening in
38: This is the line number the error is happening with.

Ok, so far we know the exact location the error is occuring. Get a text editor that shows line number btw.

attempt: There was something it tried to do but it failed.
call: What it tried was a function call
'blockless' (a nil value): You are using something called blockless, but there is variable, not function, nothing called blockless atm.

So, fire up Notepad++, open the file LuaRules/Gadgets/commandadditiontets.lua, and go the line 38 of that file.

Find where in that line it mention 'blockless'. (Assuming you followed previous tip about going straight to the right line, shouldn't be hard to find the word blockless in a line that has only three more characters ...)

Check for typos in the way you spelt blockless. Nope, no typos.

Check if you didnt forget to initialise blockless. Ok, there's that local function blockless(u), it's done before any call-in, should be good.

Check the scope: The local function blockless(u) is between "If synced" and "else". It only exists within those two lines. It doesn't exist outside of it. So, there blockless is not defined Between the "else --unsynced" and the final "end". Things not defined are nil. And you can't call nil(u) like if it was function! Hence the error message.

A naive fix attempt would be to move out the local function blockless(u) blabla out of "if synced". But that would not work because that function calls SetUnitBlocking that only exists within synced.

Similarly, as you learnt on the other thread, there is no keypress in the unsynced.

Therefore, you must learn how to make synced to unsynched communication.

Hint: Look at my original widget. It's short and does it.

In the unsynced, there is SendLuaRulesMsg to SEND the message.
In the synced, there is RecvLuaMsg to RECEIVE the message.

(Then there is more difficult to understand trick of prefixing the message with an identifier so you don't catch messages from other gadgets, but we'll leave that for later.)
User avatar
SpliFF
Posts: 1224
Joined: 28 Jul 2008, 06:51

Re: Variable passing question

Post by SpliFF »

zwzsg wrote: In the unsynced, there is SendLuaRulesMsg to SEND the message.
In the synced, there is RecvLuaMsg to RECEIVE the message.
I need to update my guide. If I put that in there it isn't in the right place.

Here's the updated manual section

Transfering variables between synced and unsynced code
From synced to unsynced

Code: Select all

SendToUnsynced(...)
RecvFromSynced(...)
So, say, you have my_synced_var set in some synced code, you call:

Code: Select all

SendToUnsynced("someStringDescribingMyVar", my_synced_var)
then in unsynced code you have:

Code: Select all

function RecvFromSynced(...)
if arg[2] == "someStringDescribingMyVar" then
  local my_unsynced_var = arg[3]
So you will now have the same value in my_unsynced_var as you did in my_synced_var

Caveats: Since the synced code is running on everyones computers don't send any data this way that shouldn't be seen by all players. It wouldn't be that hard for a cheating widget to intercept and use this data in unintended ways. By making something unsynced from synced you are effectively making it public. Keep in mind that if you want data that can only be accessed by synced code then you should think carefully about WHY it's only available there. 9 times out of 10 it will be because it would allow cheats.

From unsynced to synced
In the unsynced, there is SendLuaRulesMsg to SEND the message. Note that unlike the synced to unsynced process the message must be a string only. If you want to send variables you'll have to make them part of the string and decode them when they are received.

Code: Select all

Spring.SendLuaRulesMsg("funkify unit:"..unitID)
In the synced part of a gadget, there is available a RecvLuaMsg call-in to RECEIVE the message. Call-ins are described elsewhere in the manual but the basic code is:

Code: Select all

function gadget:RecvLuaMsg(msg, playerID)
  -- Message could be anything, we need to see if it's the right one
  if string.find(msg,"funkify unit:") then
    -- yep, this is our message, get the unitID by removing the rest
    unitID = msg:gsub("funkify unit:","")
    Spring.Echo("Unit "..unitID.. " got da funk!")
  end
end
Caveats: The same call-in runs on all clients and receives all messages from all players so it's up to you to sort out the messages using string parsing and the player id.
Voidranaut
Posts: 47
Joined: 20 Dec 2009, 21:16

Re: Variable passing question

Post by Voidranaut »

wow thank you all for all the awsome info :)

especially zwzsg thanks for taking the time to go over it all in such detail your explination really helped ALOT!!
User avatar
jK
Spring Developer
Posts: 2299
Joined: 28 Jun 2007, 07:30

Re: Variable passing question

Post by jK »

btw for performance reasons you shouldn't use RecvFromSynced, you should use the action handler instead:

Code: Select all

if (gadgetHandler:IsSyncedCode())  then
  ...
  SendToUnsynced("my_command", ...)
  ...
else
  local function MyUnsyncedAction(...)
     ...
  end

  function gadget:Initialize()
    gadgetHandler:AddSyncAction("my_command", MyUnsyncedAction)
  end

  function gadget:Shutdown()
    gadgetHandler:RemoveSyncAction("my_command")
  end
end
Post Reply

Return to “Lua Scripts”