MP-Synchronisations-Fehler

  • Hallöchen,


    Bei einem selbst (um-)geschriebenem Script habe ich nun versucht es MP-fähig zu bekommen.
    Das Script soll eigentlich die "pipeRaycastDistance" bei Knopfdruck verschieben, um ein manuelles Abladen zu schaffen.
    Im SP klappt alles wunderbar. Der Host im MP hat auch keine Probleme. Der Client hat ohne ein "Event" das Problem, dass man zwar die Taste drücken kann, dann aber nichts weiter passiert. Also habe ich mich erstmals mit den Events ausernander gesetzt


    Ich liste hier mal die wichtigsten Einträge auf.
    In der update function habe ich
    [lua] if self:getIsActive() and self:getIsActiveForInput(false) and not self:hasInputConflictWithSelection() and InputBinding.hasEvent(InputBinding.ACTIVATE_UNLOADING) then
    self:setManualUnloading()
    end;[/lua]


    und:


    [lua] if not self.isAIThreshing then
    if self.pipeOpen then
    if self.grainTankFillLevel > 0 then
    local trailer, trailerDistance = self:findTrailerToUnload(self.currentGrainTankFruitType);
    if trailer == nil then
    self:setPipeRaycastDistance()
    else
    self:setPipeRaycastDistance()
    end;
    end;
    end;
    end;[/lua]


    dann gibts noch die hier:
    [lua]function manualPipe:setManualUnloading(unload, noEventSend)
    self.manualUnloading = not self.manualUnloading;
    unload = self.manualUnloading;
    manualPipeEvent.sendEvent(self, unload, noEventSend);
    end;
    [/lua]


    [lua]function manualPipe:setPipeRaycastDistance(state, noEventSend)
    if self.manualUnloading then
    self.pipeRaycastDistance = 6;
    else
    self.pipeRaycastDistance = 0.1;
    end;
    state = self.pipeRaycastDistance;
    manualPipeEvent.sendEvent(self, state, noEventSend);
    end;[/lua]



    Dann kommt noch das Event:
    [lua]


    manualPipeEvent = {};
    manualPipeEvent_mt = Class(manualPipeEvent, Event);


    InitEventClass(manualPipeEvent, "manualPipeEvent");


    function manualPipeEvent:emptyNew() -- hoier wir ein leeres Event objekt erzeugt
    local self = Event:new(manualPipeEvent_mt );
    self.className="manualPipeEvent";
    return self;
    end;


    function manualPipeEvent:new(vehicle, streamId) -- Der konsturktor des Events (erzeugt eben ein neues Event). Wir wollen das vehicle (aufrufer) und die neue richtung speichern bzw. übertragen
    local self = manualPipeEvent:emptyNew()
    self.vehicle = vehicle;
    self.state = state;
    self.unload = unload;
    return self;
    end;


    function manualPipeEvent:readStream(streamId, connection)
    local id = streamReadInt32(streamId);
    self.vehicle = networkGetObject(id);
    self.state = streamReadInt8(streamId);
    self.unload = streamReadBool(streamId);
    self:run(connection);
    end;


    function manualPipeEvent:writeStream(streamId, connection)
    streamWriteInt32(streamId, networkGetObjectId(self.vehicle));
    streamWriteInt8(streamId, self.state);
    streamWriteBool(streamId, self.unload);
    end;


    function manualPipeEvent:run(connection)
    self.vehicle:setPipeRaycastDistance(self.state, true);
    self.vehicle:setManualUnloading(self.unload, true);
    if not connection:getIsServer() then
    g_server:broadcastEvent(manualPipeEvent:new(self.vehicle, self.state, self.unload), nil, connection, self.vehicle);
    end;
    end;


    function manualPipeEvent.sendEvent(vehicle, state, unload, noEventSend)
    if noEventSend == nil or noEventSend == false then
    if g_server ~= nil then
    g_server:broadcastEvent(manualPipeEvent:new(vehicle, state, unload), nil, nil, vehicle);
    else
    g_client:getServerConnection():sendEvent(manualPipeEvent:new(vehicle, state, unload));
    end;
    end;
    end;
    [/lua]


    Naja kommt leider bei Host und Client im MP das hier in der Log:


    Code
    Error: Failed to create new object with class id 5751 in initial object array
    Error: LUA running function 'packetReceived'
    C:/Users/Michi/Documents/My Games/FarmingSimulator2013/mods/ClaasLexion550/manualPipe.lua(275) : attempt to index field 'vehicle' (a nil value)


    Zeile 275 ist übrigens
    self.vehicle:setPipeRaycastDistance(self.state, true);
    aus der :run function des Events.
    Im SP ist weiterhin alles sauber.


    Ich bin mitlerweile ratlos, vielleicht weiß einer von euch weiter..

  • Ach, doch etwas vergessen:


    [lua]function manualPipe:readStream(streamId, connection)
    local unload = streamReadBool(streamId)
    self:setManualUnloading(unload, true);
    local state = streamReadInt8(streamId);
    self:setPipeRaycastDistance(state, true);
    end;


    function manualPipe:writeStream(streamId, connection)
    streamWriteInt8(streamId, self.pipeRaycastDistance);
    streamWriteBool(streamId, self.manualUnloading);
    end;[/lua]



    So hab ich es derzeit drinnen.

  • Ich weiß nicht, ob es schlussendlich der Fehler ist, aber hier ist der Wurm drin:
    [lua]function manualPipe:setPipeRaycastDistance(state, noEventSend)
    if self.manualUnloading then
    self.pipeRaycastDistance = 6;
    else
    self.pipeRaycastDistance = 0.1;
    end;
    state = self.pipeRaycastDistance;
    manualPipeEvent.sendEvent(self, state, noEventSend);
    end;[/lua]


    Du übergibst der Funktion den Wert state und überschreibst ihn manuell wieder ?(


    Du musst die Funktion schon mit dem Wert aufrufen:
    [lua]if self.manualUnloading then
    self:setPipeRaycastDistance(6);
    else
    self:setPipeRaycastDistance(0.1);
    end;[/lua]


    und die Funktion ist dann:
    [lua]function manualPipe:setPipeRaycastDistance(state, noEventSend)


    self.pipeRaycastDistance = state;
    manualPipeEvent.sendEvent(self, state, noEventSend);
    end;[/lua]


    Edit:
    selbes gilt für die unload-Funktion!

  • Okay..


    Bei der unload Funktion habe ich aber ein Problem:


    [lua]
    function manualPipe:setManualUnloading(unload, noEventSend)
    self.manualUnloading = unload;
    manualPipeEvent.sendEvent(self, unload, noEventSend);
    end;
    [/lua]


    und das hier bei dem Tastendruck:
    [lua]
    if self.manualUnloading then
    self:setManualUnloading(false);
    else
    self:setManualUnloading(true);
    end;
    [/lua]


    Naja, dann kann ich sogar im SP zwar abladen aktivieren, aber nicht mehr deaktivieren. Ich glaub da steht ich grade auf der Leitung..

  • Das ganze Script und das Event sind falsch zusammenklamüsert.


    Warum soll die Methode self:setPipeRaycastDistance() mehrfach im Updateteil aufgerufen werden, wenn sich eh nichts ändert (würde).


    Die Werte der Variable self.pipeRaycastDistance würde ich in der Methode self:setManualUnloading() ändern. Die Werte sind sowieso konstant und eine Änderung von self.pipeRaycastDistance ist nur mit der Änderung der Variable self.manualUnloading relevant.
    Am Schönsten wäre es hier, wenn man den Standardwert vorher in einer BackUp-Variable gespeichert hat. So ist man nicht ganz so versteift ;)


    [lua]
    function manualPipe:setManualUnloading(manualUnloading, noEventSend)
    if manualUnloading == nil then
    self.manualUnloading = not self.manualUnloading
    else
    self.manualUnloading = manualUnloading
    end;

    if self.manualUnloading then
    self.pipeRaycastDistance = 6;
    else
    self.pipeRaycastDistance = 0.1;
    end;
    manualPipeEvent.sendEvent(self, self.manualUnloading, noEventSend);
    end;
    [/lua]



    Gleichzeitig solltest du in der Methode das SendEvent() aufrufen und den aktuellen Wert von self.manualUnloading übergeben.
    Im Event selbst, rufst du dann die Methode self:setManualUnloading() auf und übergibst den neuen Wert.


    So ändert sich der Wert nur bei einem Tastendruck in Relation zu der Variable self.manualUnloading. Das ist es ja eigentlich, was du mit dem Script bezwecken willst ;)


    Hier noch das korrigierte Event - dürfte so stimmen :


    [expander]
    [lua]
    manualPipeEvent = {};
    manualPipeEvent_mt = Class(manualPipeEvent, Event);


    InitEventClass(manualPipeEvent, "manualPipeEvent");


    function manualPipeEvent:emptyNew()
    local self = Event:new(manualPipeEvent_mt );
    self.className="manualPipeEvent";
    return self;
    end;


    function manualPipeEvent:new(vehicle, manualUnloading, streamId) --Parameter vergessen! Wir brauchen eine Variable für self.manualUnloading!
    local self = manualPipeEvent:emptyNew()
    self.vehicle = vehicle;
    self.manualUnloading = manualUnloading; -- Gleiche Namenskonventionen für eine bessere Übersichtlichkeit.
    return self;
    end;


    function manualPipeEvent:readStream(streamId, connection)
    local id = streamReadInt32(streamId);
    self.vehicle = networkGetObject(id);
    self.manualUnloading = streamReadBool(streamId);
    self:run(connection);
    end;


    function manualPipeEvent:writeStream(streamId, connection)
    streamWriteInt32(streamId, networkGetObjectId(self.vehicle));
    streamWriteBool(streamId, self.manualUnloading);
    end;


    function manualPipeEvent:run(connection)
    self.vehicle:setManualUnloading(self.manualUnloading);
    if not connection:getIsServer() then
    g_server:broadcastEvent(manualPipeEvent:new(self.vehicle, self.manualUnloading), nil, connection, self.vehicle);
    end;
    end;


    function manualPipeEvent.sendEvent(vehicle, manualUnloading, noEventSend)
    if noEventSend == nil or noEventSend == false then
    if g_server ~= nil then
    g_server:broadcastEvent(manualPipeEvent:new(vehicle, manualUnloading), nil, nil, vehicle);
    else
    g_client:getServerConnection():sendEvent(manualPipeEvent:new(vehicle, manualUnloading));
    end;
    end;
    end;
    [/lua]
    [/expander]



    Zusammenfassung : Alles raus, bis auf den Teil für das Input Binding :thumbsup:

  • Hm, ich glaube der Fehler liegt in deinem MP Event. Das rufst du z.b auf mit:
    [lua]manualPipeEvent.sendEvent(self, unload, noEventSend);


    --bzw
    manualPipeEvent.sendEvent(self, state, noEventSend);
    [/lua]
    was ja auch ok ist, aber in deinem MP Event, machst du folgendes:


    [lua]function manualPipeEvent:readStream(streamId, connection)
    local id = streamReadInt32(streamId);
    self.vehicle = networkGetObject(id);
    self.state = streamReadInt8(streamId);
    self.unload = streamReadBool(streamId);
    self:run(connection);
    end;
    [/lua]
    Und da ist der Fehler, beim ersten Aufruf fehlt dir ja der state, da du nur self, unload und sendEvent überträgst. Beim 2. Aufruf durch dein manualPipe:setPipeRaycastDistance fehlt dir dann aber dasd unload.


    So wie ich es jetzt verstanden habe willst du ja ein Manuelles Abladen erlauben. Also per Tastendruck die self.pipeRaycastDistance verändern.


    Das würde ich einfach folgender maßen umsetzen:


    [lua]if self:getIsActive() and self:getIsActiveForInput(false) and not self:hasInputConflictWithSelection() and InputBinding.hasEvent(InputBinding.ACTIVATE_UNLOADING) then
    self.manualUnloading = not self.manualUnloading;
    self:setManualUnloading(self.manualUnloading)
    end;




    function manualPipe:setManualUnloading(unload, noEventSend)

    if unload then
    self.pipeRaycastDistance = 6;
    else
    self.pipeRaycastDistance = 0.1;
    end;


    manualPipeEvent.sendEvent(self, unload, noEventSend);
    end;
    [/lua]


    Also wenn die Taste gedrückt wurde änderst du die eigentliche Statusvariable und rufst die Function auf, der du den aktuellen Wert übergibst.
    In der function führst du nun deine Änderung durch. Also das ändern der self.pipeRaycastDistance wenn true dann ist sie 6, ansonsten ist sie 0.1!




    Zudem würde ich dann noch die self.pipeRaycastDistance immer wieder auf 0.1 setzen sobald der Tank leer ist, zudem das manualUnloading auch zurücksetzen, das kannst du so machen:
    [lua]if self.grainTankFillLevel == 0 then
    if self.manualUnloading then
    self.manualUnloading = false;
    self:setManualUnloading(false);
    end;
    end;
    [/lua]
    Hier einfach ein false an die function übergeben wenn der Tank leer ist und self.manualUnloading true war/ist.



    Edit: Fiat80-90DT war schneller...

  • Also, schon einmal Danke für die ganze Hilfe hier, da bin ich euch echt dankbar :)


    Mitlerweile funktioniert es schon teilweise im MP. Leider wird ständig abgeladen und "self.manualUnloading" wird scheinbar sehr schnell ständig ein- und wieder ausgeschaltet, zumindest laut Hilfetext. Dies betrifft Client und Host. Im SP klapp alles perfekt. Die Log bleibt übrigens bei beiden fehlerfrei.


    Aktuelles Setup:


    [expander]
    [lua]
    function manualPipe:readStream(streamId, connection)
    local manualUnloading = streamReadBool(streamId)
    self:setManualUnloading(manualUnloading, true);
    end;


    function manualPipe:writeStream(streamId, connection)
    streamWriteBool(streamId, self.manualUnloading);
    end;


    function manualPipe:setManualUnloading(manualUnloading, noEventSend)
    if manualUnload == nil then
    self.manualUnloading = not self.manualUnloading
    else
    self.manualUnloading = manualUnload
    end;

    if self.manualUnloading then
    self.pipeRaycastDistance = 6;
    else
    self.pipeRaycastDistance = 0.1;
    end;
    manualPipeEvent.sendEvent(self, self.manualUnloading, noEventSend);
    end;
    [/lua]
    in der update-function:
    [lua]
    if self.isEntered then
    if self.pipeOpen and self.getIsPipeUnloadingAllowed then
    if self:getIsActive() and self:getIsActiveForInput(false) and not self:hasInputConflictWithSelection() and InputBinding.hasEvent(InputBinding.ACTIVATE_UNLOADING) then
    self:setManualUnloading();
    end;
    end;
    end;
    [/lua]


    und das Event: (eigentlich das selbe was FIAT80-90DT gepostet hat)
    [lua]
    manualPipeEvent = {};
    manualPipeEvent_mt = Class(manualPipeEvent, Event);


    InitEventClass(manualPipeEvent, "manualPipeEvent");


    function manualPipeEvent:emptyNew()
    local self = Event:new(manualPipeEvent_mt );
    self.className="manualPipeEvent";
    return self;
    end;


    function manualPipeEvent:new(vehicle, manualUnloading, streamId) --Parameter vergessen! Wir brauchen eine Variable für self.manualUnloading!
    local self = manualPipeEvent:emptyNew()
    self.vehicle = vehicle;
    self.manualUnloading = manualUnloading; -- Gleiche Namenskonventionen für eine bessere Übersichtlichkeit.
    return self;
    end;


    function manualPipeEvent:readStream(streamId, connection)
    local id = streamReadInt32(streamId);
    self.vehicle = networkGetObject(id);
    self.manualUnloading = streamReadBool(streamId);
    self:run(connection);
    end;


    function manualPipeEvent:writeStream(streamId, connection)
    streamWriteInt32(streamId, networkGetObjectId(self.vehicle));
    streamWriteBool(streamId, self.manualUnloading);
    end;


    function manualPipeEvent:run(connection)
    self.vehicle:setManualUnloading(self.manualUnloading);
    if not connection:getIsServer() then
    g_server:broadcastEvent(manualPipeEvent:new(self.vehicle, self.manualUnloading), nil, connection, self.vehicle);
    end;
    end;


    function manualPipeEvent.sendEvent(vehicle, manualUnloading, noEventSend)
    if noEventSend == nil or noEventSend == false then
    if g_server ~= nil then
    g_server:broadcastEvent(manualPipeEvent:new(vehicle, manualUnloading), nil, nil, vehicle);
    else
    g_client:getServerConnection():sendEvent(manualPipeEvent:new(vehicle, manualUnloading));
    end;
    end;
    end;
    [/lua]
    [/expander]


    Ich habe da auch selber noch bischen rumprobiert, aber leider immer mit ähnlichem Ergebnis.

  • Ach, ist ja klar ich bin einfach ein Volldeppen :D


    In deinem geposteten Event die Zeile 32:
    [lua]
    self.vehicle:setManualUnloading(self.manualUnloading);
    [/lua]


    in :


    [lua]
    self.vehicle:setManualUnloading(self.manualUnloading, true);
    [/lua]


    abändern.


    Was war hier falsch? Ganz klar, ich habe vergessen der Methode mitzuteilen, dass sie von einem Event aufgerufen wurde und dadurch kein neues Event senden muss :D


    EDIT:


    Und in deiner Methode self:setManualUnloading() ist auch was falsch ;)


    [lua]
    if manualUnload == nil then
    [/lua]


    muss zu


    [lua]
    if manualUnloading == nil then
    [/lua]
    Das erklärt auch die Negierung der Variable, mit dem fehlerhaften Eventaufruf.


    Grüße Kai

  • So,


    ich habe da wieder getestet mit deinen Änderungen, spricht:


    [lua]
    self.vehicle:setManualUnloading(self.manualUnloading, true);
    [/lua]
    und


    [lua]
    if manualUnloading == nil then
    [/lua]


    Dann kann der Client nicht abladen, Host schon.


    Wenn ich aber wieder statt


    [lua]if manualUnloading == nil then[/lua]


    dass einfüge:


    [lua]if manualUnload == nil then[/lua]


    klappt es bei beiden ohne logfehler. Leider ist mir aber trotzdem eine Kleinigkeit aufgefallen, die beim Client nicht stimmt. Und zwar wird dort der Hilfetext (F1) "falsch herum" angezeigt. Sprich wenn der Client abladet steht im Hilfetext abladen starten. Beim Host ist es aber richt.


    Hier mal der Hilfetext:


    [lua]function manualPipe:draw()
    if self.pipeOpen and self.manualUnloading then
    g_currentMission:addHelpButtonText(g_i18n:getText("Stopdumpinggrain"), InputBinding.ACTIVATE_UNLOADING);
    elseif self.pipeOpen then
    g_currentMission:addHelpButtonText(g_i18n:getText("Startdumpinggrain"), InputBinding.ACTIVATE_UNLOADING);
    end;
    end;[/lua]


    hier mal die :load function:
    [lua]function manualPipe:load(xmlFile)


    self.manualUnloading = false;
    self.pipeRaycastDistance = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.pipe#raycastDistance"));
    self.pipeRaycastDistance = 0.1;


    [/lua]


    Ich weiß nicht ob die damit was zu tun hat. Aber wieso ist beim Client dann nur der Hilfetext falsch herum? Bei Host und Client wird standardmäßig nicht abgeladen und mit einem Tastendruck auf abladen umgeschaltet.

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!