function patch(proto, name, fn) {
	// use the object prototype if possible
	if (typeof proto.prototype !== "undefined") {
		proto = proto.prototype;
	}
	// reuse the logic behind object extends
	if (typeof proto[name] === "function") {
		// save the original function
		const _parent = proto[name];
		// override the function with the new one
		Object.defineProperty(proto, name, {
			configurable: true,
			value: (function (name, fn) {
				return function () {
					this._patched = _parent;
					const ret = fn.apply(this, arguments);
					this._patched = null;
					return ret;
				};
			})(name, fn),
		});
	} else {
		throw new Error(name + " is not an existing function");
	}
}
patch a melonJS function
@name patch
@memberof plugin
@param {object} proto - target object
@param {string} name - target function
@param {Function} fn - replacement function
@example
// redefine the me.game.update function with a new one
me.plugin.patch(me.game, "update", function () {
  // display something in the console
  console.log("duh");
  // call the original me.game.update function
  this._patched();
});