Library globals

Source scenery.nas

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
###############################################################################
##
##  Support tools for multiplayer enabled scenery objects.
##
##  Copyright (C) 2011 - 2013  Anders Gidenstam  (anders(at)gidenstam.org)
##  This file is licensed under the GPL license version 2 or later.
##
###############################################################################

# The event channel for scenery objects.
# See mp_broadcast.EventChannel for documentation.
var events = nil;

###############################################################################
# An extended aircraft.door that transmits the door events over MP using the
# scenery.events channel.
# Use only for single instance objects (e.g. static scenery objects).
#
# Note: Currently toggle() is the only shared event.
var sharedDoor = {
    new: func(node, swingtime, pos = 0) {
        var obj = aircraft.door.new(node, swingtime, pos);
        obj.parents    = [sharedDoor] ~ obj.parents;
        obj.event_hash = mp_broadcast.Binary.stringHash
            (isa(node, props.Node) ? node.getPath() : node);
        obj.clock      = mp_broadcast.LamportClock.new();
        obj.loopid     = 0;
        events.register(obj.event_hash,
                        func (sender, msg) { obj._process(sender, msg) });
        return obj;
    },
    toggle: func {
        # Send current time, current position and target position.
        me.clock.advance();
        me.move(me.target);
        me._loop(me.loopid += 1);
    },
    destroy : func {
        me.loopid += 1;
        events.deregister(me.event_hash);
    },
    _process : func (sender, msg) {
        if (me.clock.merge(sender, msg)) {
            me.setpos(mp_broadcast.Binary.decodeDouble
                      (substr(msg, mp_broadcast.Binary.sizeOf["LamportTS"])));
            me.target = mp_broadcast.Binary.decodeByte
                (substr(msg,
                        mp_broadcast.Binary.sizeOf["LamportTS"] +
                        mp_broadcast.Binary.sizeOf["double"]));
            me.move(me.target);
        }
    },
    _loop : func (id) {
        id == me.loopid or return;
        # Send current time, current position and target position.
        events.send(me.event_hash,
                    me.clock.timestamp() ~
                    mp_broadcast.Binary.encodeDouble(me.positionN.getValue()) ~
                    mp_broadcast.Binary.encodeByte(!me.target));
        settimer(func { me._loop(id); }, 17, 1);
    }
};

###############################################################################
# Internals
var shared_pp = "scenery/share-events";

var _set_state = func {
    if (getprop("/sim/signals/reinit")) return; # Ignore resets.
    if (getprop(shared_pp)) {
        #print("scenery.nas: starting event sharing.");
        events.start();
    } else {
        #print("scenery.nas: stopping event sharing.");
        events.stop();
    }

}
#-- Init -----------------------------------------------------------------------
events = mp_broadcast.EventChannel.new("scenery/events");
if (getprop(shared_pp)) {
    #print("scenery.nas: starting event sharing.");
    events.start();
} else {
    #print("scenery.nas: stopping event sharing.");
    events.stop();
}
setlistener(shared_pp, _set_state);