Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for versioned achievement, leaderboard, and rich presence logic #2995

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

wescopeland
Copy link
Member

I fixed a ticket yesterday and realized how crazy it was that I was leaving a backup of the logic in the comments section. It seems this is a regular practice that developers are currently doing. That's what led me down this rabbit hole.

This PR begins the process of double-writing achievement, leaderboard, and RP logic to the triggers table. This will ultimately lead to:

  • Automated backups of all logic.
  • Auditable changelogs for logic that gets sent to emulators.
  • The ability to revert/roll back undesirable changes.

How It Works

The triggers table has the following structure:

CREATE TABLE `triggers` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `triggerable_type` varchar(255) NOT NULL,
  `triggerable_id` bigint(20) unsigned NOT NULL,
  `user_id` bigint(20) unsigned DEFAULT NULL,
  `version` int(10) unsigned DEFAULT NULL,
  `parent_id` bigint(20) unsigned DEFAULT NULL,
  `conditions` text DEFAULT NULL,
  `type` text DEFAULT NULL,
  `stat` varchar(255) DEFAULT NULL,
  `stat_goal` varchar(255) DEFAULT NULL,
  `stat_format` varchar(50) DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  `deleted_at` timestamp NULL DEFAULT NULL
)

These are the key columns to pay attention to:

  • triggerable_type - What kind of asset is this? Current possible values are achievement, leaderboard, and game (rich presence).
  • triggerable_id - What is the ID of the asset? (achievement ID, leaderboard ID, game ID)
  • user_id - Who made this change?
  • version - Nullable, and increments from 1 -> 2 -> 3 -> N. If an achievement has never been published, its version will always be null. Once it is published, the version is automatically set to 1. After every update, the version increments, regardless of who updated it.
  • parent_id - Forms a linked list of a triggerable's version history. If the current version is 2, parent_id will point to the row where version is 1.
  • conditions - Mem, MemAddr, RichPresencePatch.

type, stat, stat_goal, and stat_format are not currently being written to.

For achievements:

  • When a developer uploads a new achievement to unofficial, a new unversioned trigger is created.
  • When updating the logic in unofficial, the unversioned trigger is written to in-place. New trigger rows are not created for the achievement.
  • When the achievement is promoted, its version is set to 1.
  • When anyone edits the achievement, subsequent trigger versions are created.
  • The achievement remains versioned even if demoted.

For leaderboards:

  • When a developer uploads a new leaderboard, a versioned trigger is created (version 1).
  • When anyone edits the leaderboard, subsequent trigger versions are created (version 2, 3, etc).

For rich presence:

  • When a developer saves an RP script, a versioned trigger is created (version 1).
  • When anyone edits the RP script, subsequent trigger versions are created (version 2, 3, etc).

How to Test This PR

First, you'll need to sync all the existing trigger logic to your triggers table (which should currently be empty):

sail artisan ra:sync:triggers

Now, just create and update logic for triggerable assets as you normally do. You should observe changes being made in the triggers table.

Caveats

  • The Artisan sync command is only writing the latest triggerable logic to the triggers table. It does its best to try to preserve created_at and updated_at timestamps from triggerable asset and system comment model values.

Open Questions

  • Should there be some kind of nullable "comment field" on the triggers table, which could kind of be like a commit message?

Next Steps

  • Drop Mem, MemAddr, and RichPresencePatch. Read these values from the triggers table.

Prior Art

Documented migration which added the triggers table: https://github.com/RetroAchievements/RAWeb/blob/6bb51893178da57f26b4a8fd5bc715a9e17e7e9a/database/migrations/platform/2018_10_01_000001_create_triggers_table.php

@wescopeland wescopeland requested a review from a team December 28, 2024 00:54

$data['DisplayOrder'] = $displayOrder;
$data['Author'] = $originalAuthor?->display_name ?? "Unknown";
$originalAuthor = $foundLeaderboard->developer;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is absorbed from #2993. I discovered that issue while doing manual testing for all this stuff.

Comment on lines -318 to -319
$data['DisplayOrder'] = $displayOrder;
$data['Author'] = $originalAuthor?->display_name ?? "Unknown";
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As best as I can tell, these $data values are unused.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant