Also, es geht darum, wie man vom Client aus eine serverseitige Funktion aufruft und dabei auch das zurückgegeben bekommt, was die serverseitige Funktion zurückgibt.
Hierbei muss mit coroutinen gearbeitet werden.
Mit Hilfe von coroutinen können Funktionen gestoppt werden um sie später weiterzuführen.
Die Funktion läuft, wenn sie wieder "angestoßen" wird, einfach weiter, als wäre nichts gewesen.
Dies nutzen wir für unser Vorhaben aus.
Der Code stammt übrigens nicht von mir, ich habe ihn in der GPS Resource gefunden.
Er ist allerdings nicht allzuschwer zu verstehen.
Als erstes benötigen wir eine Art Datenbank, in der wir unsere Daten speichern und abrufen können.
Nun überschreiben wir uns die coroutine.resume Funktion, damit sie, unsere Daten automatisch verarbeitet.
local _resume = coroutine.resume
function coroutine.resume(cr, ...)
local ret = { _resume(cr, ...) }
if coroutine.status(cr) == 'dead' then
CRs[CRs[cr]] = nil
CRs[cr] = nil
end
if not ret[1] then
outputDebugString(ret[2], 1)
return false
end
table.remove(ret, 1)
return unpack(ret)
end
Alles anzeigen
So, nun brauchen wir noch etwas, mit dem wir nun den Aufruf an den Server tätigen und unsere coroutine stoppen.
local serverMT = {}
function serverMT:__index(fnName)
return function(...)
triggerServerEvent('onServerCallback', getLocalPlayer(), CRs[coroutine.running()], fnName, ...)
return coroutine.yield()
end
end
server = setmetatable({}, serverMT)
Jetzt fehlt noch der clientseitige empfänger, der unsere Rückgabewerte empfängt.
addEvent('onServerCallbackReply', true)
addEventHandler('onServerCallbackReply', getResourceRootElement(getThisResource()),
function(crID, ...)
coroutine.resume(CRs[crID], ...)
end,
false
)
So, jetzt brauchen wir noch etwas, das unsere Funktionen zu coroutinen macht.
local function wrapHandler(fn)
return function(...)
local cr = coroutine.create(fn)
local id = #CRs + 1
CRs[id] = cr
CRs[cr] = id
coroutine.resume(cr, ...)
end
end
local _addEventHandler = addEventHandler
function addEventHandler(event, elem, fn, getPropagated)
return _addEventHandler(
event,
elem,
(event == 'onClientRender' or event == 'onClientPreRender') and fn or wrapHandler(fn),
getPropagated
)
end
local _addCommandHandler = addCommandHandler
function addCommandHandler(command, fn)
return _addCommandHandler(command, wrapHandler(fn))
end
Alles anzeigen
Hier wird die jeweilige Funktion in eine coroutine umgewandelt, wenn wir die mit einem Event- oder Commandhandler verknüpfen.
Dies dient dazu, damit sie angehalten werden kann.
Jetzt kommt der serverseitige Teil.
Dieser dient dazu, die Aufrufe an den Server zu empfangen und uns unseren Rückgabewerte zurück an den Client zu schicken.
addEvent('onServerCall', true)
addEventHandler('onServerCall', root,
function(fnName, ...)
_G[fnName](...)
end
)
addEvent('onServerCallback', true)
addEventHandler('onServerCallback', root,
function(crID, fnName, ...)
triggerClientEvent(source, 'onServerCallbackReply', getResourceRootElement(getThisResource()), crID, _G[fnName](...))
end
)
Alles anzeigen
So, jetzt wäre erstmal der kompliziertere Teil geschafft.
Nun können wir unsere serverseitigen Aufrufe z.B. so tätigen:
So wird serverseitig ein Fahrzeug erstellt.
Dieses wird dann an den Client zurückgetriggert.
Wir können als soetwas hier tun:
local vehicle = server.createVehicle(525, x, y, z, rx, ry, rz)
addEventHandler("onClientVehicleEnter", vehicle, function()
outputChatBox("LOL")
end)
Ich hoffe das Tutorial hat euch gefallen und Hilf euch in Zukunft evtl. etwas weiter.