Lua sync to unsync

From Spring
Revision as of 16:51, 5 October 2010 by Knorke (talk | contribs) (started this page)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search

synced and unsynced lua

When making a gadget you will sometimes want to combine synced and unsynced code.
For example if you do some things with units, that will need to be synced code.
The UnitDestroyed, UnitFinished etc. callins only exist in synced code.
But if you also want to draw on the screen (for example to mark units) then the drawing will have to happen in unsynced code.

Here is a choatic gadget that makes "miners" fill their "cargo bay" if they kill ressources.
Notice the _G.miners = miners; it makes a copy (?) of the synced miners table acessable to the unsynced code.
In the the unsynced code, the miners table can now be acessed with SYNCED.miners
_G is a table that can be read in both synced and unsynced.
GG (not used here) is a table that can be acessed by all (synced) gadgets

function gadget:GetInfo()
  return {
    name      = "mining blabla2",
    desc      = "some broken stuff less broken",
    author    = "knorke",
    date      = "4 Okt 2010",
    license   = "rcdraco's draco license",
    layer     = 0,
    enabled   = true  --  loaded by default	
  }
end

if (gadgetHandler:IsSyncedCode()) then

local miners = {} --  [unitID] alive: true oder false   cargo: wieviel er trägt  status: was er gerade macht: "loading" "unloading" "mining" "to_res" "to_hq"
local miner_name = "arm_flash";
local ressource_name = "arm_solar_collector"

function gadget:UnitFinished(unitID, unitDefID, teamID)
	if (is_miner_type (unitDefID) == true) then add_miner (unitID) end
end

function gadget:UnitDestroyed(unitID, unitDefID, teamID, attackerID)
	--remove destroyed miners:
	if is_miner (unitID) then remove_miner (unitID) end
	--wenn etwas geerntet wurde:
	if (is_ressource_type (unitDefID)) then Spring.Echo ("ressource mined") end
	if (is_miner(attackerID)) then Spring.Echo ("miner mined") end
	if (is_ressource_type (unitDefID) and is_miner(attackerID)) then 	
		miners[attackerID].cargo = miners[attackerID].cargo + 25
		Spring.Echo ("finished mining! cargo:" .. miners[attackerID].cargo)
		end
end


function gadget:GameFrame(frameNum) 
	_G.miners = miners;
end

function gadget:Initialize()
	make_miner_table()
	_G.miners = miners;
end

function marker_on_unit (_uID, _text)
	if (markers == false) then return end
	if (_uID == nil) then return end
	if (_text == nil) then return end
	local x,y,z=Spring.GetUnitPosition (_uID)
	if (x == nil or y == nil or z == nil) then return end
	Spring.MarkerAddPoint (x,y,z, _text .. "id:" .. _uID)
end

function make_miner_table()
	miners = {}
	local all_units = Spring.GetAllUnits ()
	for i in pairs(all_units) do
		local unitDefID = Spring.GetUnitDefID(all_units[i])
		if (is_miner_type (unitDefID)==true) then
			add_miner (all_units[i])
		end
	end
end

function is_miner_type (unitDefID)
	if (unitDefID == nil) then return false end
	local unitDef = UnitDefs[unitDefID]
	if (unitDef == nil) then return false end
	if (unitDef.name == miner_name) then return true end
	return false
end

function is_ressource_type (unitDefID)
	if (unitDefID == nil) then return false end
	local unitDef = UnitDefs[unitDefID]
	if (unitDef == nil) then return false end
	if (unitDef.name == ressource_name) then return true end
	return false
end


function is_miner (unitID)
	if (miners [unitID] ~= nil) then return true else return false end
end

function add_miner (unitID)
	miners [unitID] = {}
	miners [unitID].alive = true
	miners [unitID].cargo = 0
	marker_on_unit (unitID, "added")
end

--------------------------------------------------------
--Border between SYNC and UNSYNC
--when i wear my frilly dress im a real touhou
end
if (not gadgetHandler:IsSyncedCode()) then
--------------------------------------------------------

--Length of table, for synced (using spairs)
function sxlen(tbl)
	local qq = 0;
	for v in spairs(tbl) do
		qq = qq + 1;
	end
	return qq;
end

function gadget:DrawScreen()
	gl.Color(0.5, 0.5, 0.5, 1)
	local ty = 0
	for i in spairs(SYNCED.miners) do
		ty = ty + 1
		gl.Text (ty .."| [" .. i .. "]".. "cargo:" .. SYNCED.miners[i].cargo, 100,300-ty*25 , 25, 'o')
	end
	gl.Text ("miners counted="..ty .. "#miners:" .. sxlen(SYNCED.miners), 100,300 , 25, 'o')
end

function gadget:DrawWorldPreUnit()
	gl.LineWidth(5.0)
	for i in spairs(SYNCED.miners) do
			if (SYNCED.miners[i].alive == true and i ~= nil and SYNCED.miners[i] ~=nil) then
			local x,y,z=Spring.GetUnitPosition (i)
			if (x ~= nil and y ~= nil and z ~= nil) then
				gl.Color(0, 1, 0, 1)
				gl.DrawGroundCircle (x,y,z, 50, 4) --all miners marked with a diamond shape
				--cargo status
				gl.Color(1, 0, 0, 1)
				gl.DrawGroundCircle (x+60,y,z, 90, 3)
				gl.Color(1, 1, 0, 1)
				gl.DrawGroundCircle (x+60,y,z, SYNCED.miners[i].cargo, 3)  --growing triangle shows cargo status
			end
		end
	end
end

end


The thread to this gadget: http://springrts.com/phpbb/viewtopic.php?f=23&t=24230


Another way is to use SendToUnsynced
Here is an example by quantum:
http://pastebin.com/hMHv3Lrf

[LCC]quantum[0K] every time there  is a new target, i send "addTarget" and its number to unsynced
[LCC]quantum[0K] when a target is removed from the list, i send "removeTarget" and its number
[LCC]quantum[0K] this wierd stuff:
[LCC]quantum[0K]   _G.laserEventArgs = eventArgs
[LCC]quantum[0K]   SendToUnsynced("LaserEvent")
[LCC]quantum[0K]   _G.laserEventArgs = nil
[LCC]quantum[0K] puts the eventArgs table somewhere were unsynced can find it
[LCC]quantum[0K] sends a signal to unsynced called "LaserEvent"
[LCC]quantum[0K] and removes the table
[LCC]quantum[0K] on the unsynced side, _G.laserEventArgs becomes SYNCED.laserEventArgs
[LCC]quantum[0K] this copies it to another table, ready for reuse:   for k, v in spairs(SYNCED.laserEventArgs) do
[LCC]quantum[0K]     eventArgs[k] = v
[LCC]quantum[0K]   end
[LCC]quantum[0K] also, this: gadgetHandler:AddSyncAction("LaserEvent", HandleLaserEvent)
LCC]quantum[0K] means that i want the HandleLaserEvent function to be called every time i do SendToUnsynced("LaserEvent")