• Hey! Guest! The 40th (!!!) GMC Jam will take place between February 25th, 12:00 UTC to March 1st 12:00 UTC. Why not join in this very special anniversary jam! Click here to find out more!

GMS 2.3+ Pubsub in 2.3

samspade

Member
I have a working version of pubsub for 2.3, I currently have a working version but for some reason this pattern has been difficult for me to grasp so if anyone is feeling generous with their time and wanted to review it, I'd appreciate it:

GML:
///pubsub manager (persistent always present object)

///create event
event_map = ds_map_create();
event_queue = ds_queue_create();

subscribe = function(_event, _id, _func) {
    if !(ds_map_exists(event_map, _event)) {
        ds_map_add_list(event_map, _event, ds_list_create());
    }
    ds_list_add(event_map[? _event], [_id, _func]);
}

unsubscribe = function(_event, _id) {
    if (ds_map_exists(event_map, _event)) {
        var _subscribers_list = event_map[? _event];
        for (var i = 0; i < ds_list_size(_subscribers_list); i += 1) {
            if (_subscribers_list[| i][0] == _id) {
                ds_list_delete(_subscribers_list, i);
                break;
            }
        }
    }
}

publish = function(_event, _data) {
    ds_queue_enqueue(event_queue, [_event, _data]);
}

//step event

repeat (ds_queue_size(event_queue)) {
    var _event_data = ds_queue_dequeue(event_queue);
    if (ds_map_exists(event_map, _event_data[0])) {
        var _subscribers_list = event_map[? _event_data[0]];
        for (var i = 0; i < ds_list_size(_subscribers_list); i += 1) {
            _subscribers_list[| i][1](_event_data[1]);
        }      
    }
}


///clean up event
ds_map_destroy(event_map);
ds_queue_destroy(event_queue);
Here's an example use of subscribe and publish - this is for a health bar connected to a player object (the project I'm using it in is a prototype so I currently have some bad practices such as using obj_player instead of an instance id)

GML:
///example use

//subscribe from inside health bar
pubsub_manager.subscribe("damage", id, function(_data) {
    if (_data[0] == obj_player) {
        percent = _data[1];
    }
});

//publish from inside damage method
pubsub_manager.publish("damage", [object_index, current_hull_strength/max_hull_strength]);


The primary issues I have with this is that it requires the data to be passed in as an array (I could also use a struct) but as a group of data which this requires any specific function to reference the arguments as an array.
 
Last edited:
Top