openvibers/openvibe.quest Commits

Quest: Publish a creator world (games.world.published, contracts 0.194.0) (#57)

OP OpenVibers committed 29 days ago · 1418965de0 · 4 files, +18 −0

OpenVibe.Games creator worlds: the owner of a world published for the first time gets the quest
(badge World Builder, 20 OpenCoins). A world a service published credits nobody.

Changes

ddiff --git a/README.md b/README.md
iindex eb44d74..b7ded9b 100644
---- a/README.md
++++ b/README.md
@@@ -137,6 +137,7 @@ OpenVibe.Events delivers an event when a site really does something. Quest count
| `run.job.succeeded` | OpenVibe.Run | `payload.requester` when it is a user (an app's or a service's job is nobody's) |
| `inventory.item.equipped` | OpenVibe.Inventory | `payload.owner` |
| `bot.robot.online` | OpenVibe.Bot | `payload.owner`, the robot's owner (Bot names it since contracts 0.192.0) |
++| `games.world.published` | OpenVibe.Games | `payload.owner`, who published a creator world for the first time (contracts 0.194.0) |
**App quests** (contracts 0.193.0, [server/quests/app-quests.js](server/quests/app-quests.js)): a developer app defines
quests on its own project's events with an app token (audience `openvibe.quest`, capability `quest.app_quest.manage`).
ddiff --git a/server/quests/apply.js b/server/quests/apply.js
iindex f24c7ec..dab382a 100644
---- a/server/quests/apply.js
++++ b/server/quests/apply.js
@@@ -64,6 +64,8 @@ function personOf(event) {
case 'inventory.item.equipped': // payload.owner (usr_…)
case 'bot.robot.online': // payload.owner (usr_…, contracts 0.192.0; absent from older events)
return isUser(p.owner) ? p.owner : null;
++ case 'games.world.published': // payload.owner (identity.subject-ref@1, contracts 0.194.0)
++ return refUser(p.owner);
default:
// An app's own event (app quests, server/quests/app-quests.js): the actor, when the app published it
// on_behalf_of a person; an app acting as itself is nobody.
ddiff --git a/server/quests/catalog.js b/server/quests/catalog.js
iindex 5d8b92d..e2fb049 100644
---- a/server/quests/catalog.js
++++ b/server/quests/catalog.js
@@@ -214,6 +214,15 @@ const QUESTS = Object.freeze([
reward: { badge: { id: 'robot-pilot', name: 'Robot Pilot' }, coins: 20 },
repeatable: false,
},
++ {
++ id: 'publish-a-world',
++ site: 'openvibe.games',
++ title: 'Publish a creator world',
++ why: 'Build a world in the map editor and publish it: anyone can join it from their browser.',
++ steps: [{ event_type: 'games.world.published', count: 1, label: 'Publish one of your worlds at openvibe.games/worlds' }],
++ reward: { badge: { id: 'world-builder', name: 'World Builder' }, coins: 20 },
++ repeatable: false,
++ },
{
id: 'settle-in',
site: 'openvibe.network',
@@@ -438,6 +447,7 @@ const EVENTS = Object.freeze([
{ event_type: 'run.job.succeeded', site: 'openvibe.run', what: 'A job finished on a node; the payload names its requester (a service or app requester is ignored).' },
{ event_type: 'inventory.item.equipped', site: 'inventory.openvibe.network', what: 'An item was equipped; the payload names its owner, never what else they own.' },
{ event_type: 'bot.robot.online', site: 'openvibe.bot', what: 'A device connected and serves a robot; the payload names the robot\'s owner (events from before Bot named it are ignored).' },
++ { event_type: 'games.world.published', site: 'openvibe.games', what: 'A player published one of their creator worlds for the first time; the payload names the owner.' },
]);
// The events Quest actually counts: the consumer subscribes to exactly these, and a quest may not count an event
ddiff --git a/test/events-consumer.test.js b/test/events-consumer.test.js
iindex 2aa1fd3..edb9aad 100644
---- a/test/events-consumer.test.js
++++ b/test/events-consumer.test.js
@@@ -198,6 +198,11 @@ const progressOf = async (t, subject, questId) => (await rows(t, 'SELECT step, c
assert.ok(!(await done()).includes('bring-a-robot-online'), 'an event that does not name the owner credits nobody');
await deliver(t, envelope('bot.robot.online', { robot_id: 'rob_1', device_id: 'dev_1', owner: sam.subject }, { source: 'bot' }));
assert.ok((await done()).includes('bring-a-robot-online'));
++ const world = { world: 'wk3j9x0a2bq', title: 'Moon base', url: 'https://openvibe.games/play?world=wk3j9x0a2bq', published_at: iso() };
++ await deliver(t, envelope('games.world.published', { ...world, owner: { type: 'service', id: 'games' } }, { source: 'games' }));
++ assert.ok(!(await done()).includes('publish-a-world'), 'a world a service published is nobody\'s');
++ await deliver(t, envelope('games.world.published', { ...world, owner: { type: 'user', id: sam.subject } }, { source: 'games' }));
++ assert.ok((await done()).includes('publish-a-world'));
});
await check('an event that names nobody creditable is ignored: no subject, a guest, a service, an unknown type', async () => {