### Clone repository and switch to template branch Source: https://wiki.sonolus.com/sonolus.py-guide/play/01 Clones the guide repository and switches to the template branch to start from the initial setup. ```shell git clone https://github.com/qwewqa/wiki-sonolus.py-guide-code.git cd wiki-sonolus.py-guide-code git switch template ``` -------------------------------- ### init_ui helper for runtime UI setup Source: https://wiki.sonolus.com/sonolus.py-guide/play/03 Configures the menu button in the runtime UI. Called by Initialization.preprocess to set up UI before the level starts. ```python from sonolus.script.runtime import HorizontalAlign, runtime_ui, safe_area from sonolus.script.vec import Vec2 def init_ui(): ui = runtime_ui() ui.menu.update( anchor=safe_area().tl + Vec2(0.05, -0.05), pivot=Vec2(0, 1), dimensions=Vec2(0.15, 0.15) * ui.menu_config.scale, rotation=0, alpha=ui.menu_config.alpha, horizontal_align=HorizontalAlign.CENTER, background=True, ) ``` -------------------------------- ### Start tutorial dev server Source: https://wiki.sonolus.com/sonolus.js-guide/tutorial/01 Run this command in the project directory to start the dev server for the engine tutorial. ```shell npm run dev-tutorial ``` -------------------------------- ### Example JSON Response for GET /sonolus/info Source: https://wiki.sonolus.com/custom-server-specs/endpoints/get-sonolus-info Example JSON response body for the GET /sonolus/info endpoint. Shows the structure with title, description, buttons, configuration options, and banner. The buttons and configuration options arrays are left as placeholders. ```json { "title": "My Server Title", "description": "Description of my server.", "buttons": [ // ... ], "configuration": { "options": [ // ... ] }, "banner": { // ... } } ``` -------------------------------- ### Example response body for GET /sonolus/{type}/{itemName} Source: https://wiki.sonolus.com/custom-server-specs/endpoints/get-sonolus-type-item-name Example JSON response body for the GET /sonolus/{type}/{itemName} endpoint. The item, actions, leaderboards, and sections fields are placeholders, while description and hasCommunity are shown with example values. ```json { "item": { // ... }, "description": "Description of the item.", "actions": [ // ... ], "hasCommunity": true, "leaderboards": [ // ... ], "sections": [ // ... ] } ``` -------------------------------- ### Start development server Source: https://wiki.sonolus.com/sonolus.py-guide/play/01 Starts the development server. Keep it running and use 'r' to reload after code changes. ```shell uv run sonolus-py dev ``` -------------------------------- ### Verify Node.js and npm installation Source: https://wiki.sonolus.com/sonolus.js-guide/play/01 Verify Node.js and npm are installed by checking their versions. If both commands output a version number, the installation is successful. ```shell node -v ``` ```shell npm -v ``` -------------------------------- ### Engine Configuration Option Category Example Source: https://wiki.sonolus.com/engine-specs/resources/engine-configuration-option-category Example of a category with name 'gameplay' and title '#GAMEPLAY'. ```json { "name": "gameplay", "title": "#GAMEPLAY" } ``` -------------------------------- ### Example response JSON Source: https://wiki.sonolus.com/custom-server-specs/endpoints/post-sonolus-type-create Example JSON response for the create endpoint, showing the fields and comment placeholders. ```json { "key": "...", "hashes": [ // ... ], "shouldUpdateInfo": true, "shouldNavigateToItem": "..." } ``` -------------------------------- ### Start dev server for watch with npm run dev-watch Source: https://wiki.sonolus.com/sonolus.js-guide/watch/01 Run this command in the project directory to start a dev server for level watch. This is similar to starting the dev server in previous sections. ```shell npm run dev-watch ``` -------------------------------- ### ServerItemInfo JSON response example Source: https://wiki.sonolus.com/custom-server-specs/endpoints/get-sonolus-type-info Example JSON response body for the GET /sonolus/{type}/info endpoint. Shows the top-level fields and placeholder comments for array contents. ```json { "creates": [ // ... ], "searches": [ // ... ], "sections": [ // ... ], "banner": { // ... } } ``` -------------------------------- ### Example room creation response Source: https://wiki.sonolus.com/custom-server-specs/endpoints/post-sonolus-rooms-create Example response JSON containing the room's name and key. ```json { "name": "...", "key": "..." } ``` -------------------------------- ### Background configuration example Source: https://wiki.sonolus.com/background-specs/resources/background-configuration Example background configuration with a blur of 0.05 and a semi-transparent black mask (#00000080). ```json { "blur": 0.05, "mask": "#00000080" } ``` -------------------------------- ### Engine Configuration JSON Example Source: https://wiki.sonolus.com/engine-specs/resources/engine-configuration A minimal example of an Engine Configuration JSON object with placeholder options and ui fields. ```json { "options": [ // ... ], "ui": { // ... } } ``` -------------------------------- ### Sonolus-Session Header Example Source: https://wiki.sonolus.com/custom-server-specs/headers/sonolus-session Example of the Sonolus-Session header. The session value is the same as returned by POST /sonolus/authenticate. ```http Sonolus-Session: ... ``` -------------------------------- ### Verify uv installation Source: https://wiki.sonolus.com/sonolus.py-guide/play/01 Verifies that uv is installed and prints its version number. ```shell uv --version ``` -------------------------------- ### Sonolus-Signature Header Example Source: https://wiki.sonolus.com/custom-server-specs/headers/sonolus-signature Example of the Sonolus-Signature header with a placeholder signature value. ```http Sonolus-Signature: ... ``` -------------------------------- ### WatchInitialization preprocess setup Source: https://wiki.sonolus.com/sonolus.py-guide/watch/03 Imports setup functions and defines the preprocess callback for the WatchInitialization archetype. Reuses bucket, score, UI, and layout helpers from Play chapters. Do not copy spawn_order or update_sequential from Play's Initialization. ```python from sonolus.script.archetype import WatchArchetype from guide.lib import archetype_names from guide.lib.buckets import init_buckets from guide.lib.layout import init_layout from guide.lib.note import init_score from guide.lib.options import Options from guide.lib.ui import init_ui class WatchInitialization(WatchArchetype): name = archetype_names.INITIALIZATION def preprocess(self): init_buckets() init_score() init_ui() init_layout(Options.note_size) ``` -------------------------------- ### Start preview dev server with npm run dev-preview Source: https://wiki.sonolus.com/sonolus.js-guide/preview/01 Run this command in the project directory to start a development server for the level preview. This is similar to the dev server used in previous sections. ```shell npm run dev-preview ``` -------------------------------- ### Select Option Example Source: https://wiki.sonolus.com/custom-server-specs/misc/server-option Example of a select option with query 'genre', showing configuration for a dropdown with a default value and a list of values. ```json { "query": "genre", "name": "#GENRE", "required": false, "type": "select", "def": "...", "values": [ // ... ] } ``` -------------------------------- ### Example Response JSON Source: https://wiki.sonolus.com/custom-server-specs/misc/external-authentication Example response body for external authentication, showing a message field. ```json { "message": "..." } ``` -------------------------------- ### Engine Tutorial Data JSON Example Source: https://wiki.sonolus.com/engine-specs/resources/engine-tutorial-data Example JSON resource for engine tutorial data. The file must be GZip compressed and use the .json extension. The `preprocess`, `navigate`, and `update` fields are optional and can be omitted or filled with function definitions. ```json { "skin": { "sprites": [ { "name": "#NOTE_HEAD_CYAN", "id": 0 } ] }, "effect": { "clips": [ { "name": "#PERFECT", "id": 0 } ] }, "particle": { "effects": [ { "name": "#NOTE_CIRCULAR_TAP_CYAN", "id": 0 } ] }, "instruction": { "texts": [ { "name": "#TAP", "id": 0 } ], "icons": [ { "name": "#HAND", "id": 0 } ] }, "preprocess": { // ... }, "navigate": { // ... }, "update": { // ... }, "nodes": [ // ... ] } ``` -------------------------------- ### Multi Option Example Source: https://wiki.sonolus.com/custom-server-specs/misc/server-option Example of a multi-select option with query 'difficulty', showing configuration for multiple selections with a default array and values. ```json { "query": "difficulty", "name": "#DIFFICULTY", "required": false, "type": "multi", "def": [ // ... ], "values": [ // ... ] } ``` -------------------------------- ### Toggle Option Example Source: https://wiki.sonolus.com/custom-server-specs/misc/server-option Example of a toggle option with query 'random', showing configuration for a boolean toggle with a default value. ```json { "query": "random", "name": "#RANDOM", "required": false, "type": "toggle", "def": false } ``` -------------------------------- ### Example JSON response Source: https://wiki.sonolus.com/custom-server-specs/endpoints/get-sonolus-type-list Example response body for the list endpoint. Shows the structure with pageCount and items array; searches is optional. The items array is truncated with comments in the example. ```json { "pageCount": 5, "items": [ // ... ], "searches": [ // ... ] } ``` -------------------------------- ### SIL Example (JSON) Source: https://wiki.sonolus.com/custom-server-specs/misc/sil Example JSON object for a SIL item, with placeholder address and name values. ```json { "address": "https:// ...", "name": "..." } ``` -------------------------------- ### Replay Configuration JSON Example Source: https://wiki.sonolus.com/replay-specs/resources/replay-configuration Example of a Replay Configuration JSON resource. The 'options' array is populated with engine option values, with a placeholder comment indicating where additional values would go. ```json { "options": [ // ... ] } ``` -------------------------------- ### Text Option Example Source: https://wiki.sonolus.com/custom-server-specs/misc/server-option Example of a text option with query 'keywords', showing configuration for a text input with a default value, placeholder, and limit. ```json { "query": "keywords", "name": "#KEYWORDS", "required": false, "type": "text", "def": "", "placeholder": "#KEYWORDS", "limit": 10, "shortcuts": [ // ... ] } ``` -------------------------------- ### Initialization preprocess menu UI setup Source: https://wiki.sonolus.com/sonolus.js-guide/play/03 Sets up the menu UI in preprocess, using safeArea and ui.configuration.menu.scale/alpha to position and style the menu button. ```TypeScript export class Initialization extends Archetype { preprocess() { ui.menu.set({ anchor: safeArea.rect.lt.add(new Vec(0.05, -0.05)), pivot: { x: 0, y: 1 }, size: new Vec(0.15, 0.15).mul(ui.configuration.menu.scale), rotation: 0, alpha: ui.configuration.menu.alpha, horizontalAlign: HorizontalAlign.Center, background: true, }) } // ... } ``` ```JavaScript export class Initialization extends Archetype { preprocess() { ui.menu.set({ anchor: safeArea.rect.lt.add(new Vec(0.05, -0.05)), pivot: { x: 0, y: 1 }, size: new Vec(0.15, 0.15).mul(ui.configuration.menu.scale), rotation: 0, alpha: ui.configuration.menu.alpha, horizontalAlign: HorizontalAlign.Center, background: true, }) } // ... } ``` -------------------------------- ### Level Data JSON Example Source: https://wiki.sonolus.com/level-specs/resources/level-data Example JSON resource for level data. Must be GZip compressed and use the .json format. ```json { "bgmOffset": 0, "entities": [ // ... ] } ``` -------------------------------- ### Start dev server with npm run dev-play Source: https://wiki.sonolus.com/sonolus.js-guide/play/01 Start the development server for the project. After running this, connect to the server using the Sonolus app and enable Always Revalidate in Cache and Debug Mode in Developer settings to play the dev level. ```shell npm run dev-play ``` -------------------------------- ### Replay Data JSON Example Source: https://wiki.sonolus.com/replay-specs/resources/replay-data Example JSON resource illustrating the ReplayData structure with placeholder values and comments. The resource must be GZip compressed and use the .json extension. ```json { "startTime": 1640995200000, "saveTime": 1640995320000, "duration": 120, "inputOffset": 0.05, "playArea": { "width": 1024, "height": 768 }, "result": { // ... }, "inputs": { "entityIndex": [ // ... ], "time": [ // ... ], "judgment": [ // ... ], "accuracy": [ // ... ] }, "entities": [ { "data": [ // ... ] } // more entities ], "touches": { "l": [ // ... ], "t": [ // ... ], "x": [ // ... ], "y": [ // ... ] } } ``` -------------------------------- ### ServerItemLeaderboard JSON Example Source: https://wiki.sonolus.com/custom-server-specs/misc/server-item-leaderboard Example JSON representation of a ServerItemLeaderboard object, showing the required name and title fields. ```json { "name": "...", "title": "..." } ``` -------------------------------- ### Example authenticate response Source: https://wiki.sonolus.com/custom-server-specs/endpoints/post-sonolus-authenticate Example JSON response body for POST /sonolus/authenticate, showing a session string and an expiration timestamp. ```json { "session": "...", "expiration": 1640995200000 } ``` -------------------------------- ### EngineItem JSON Example Source: https://wiki.sonolus.com/custom-server-specs/misc/engine-item Example JSON object for an EngineItem, showing a concrete instance with name 'bandori', version 13, and placeholder comments for various properties. The example illustrates the structure but omits actual nested data. ```json { "name": "bandori", "version": 13, "title": "BanG Dream!", "subtitle": "BanG Dream! Girls Band Party!", "author": "Burrito", "tags": [ // ... ], "skin": { // ... }, "background": { // ... }, "effect": { // ... }, "particle": { // ... }, "thumbnail": { // ... }, "playData": { // ... }, "previewData": { // ... }, "tutorialData": { // ... }, "configuration": { // ... } } ``` -------------------------------- ### Engine Configuration UI JSON example Source: https://wiki.sonolus.com/engine-specs/resources/engine-configuration-ui Example JSON object for an engine configuration UI. The scope is set to 'ExampleEngine', which causes UI values to be saved and shared between all engines with that scope. ```json { "scope": "ExampleEngine", "primaryMetric": "arcade", "secondaryMetric": "life", "menuVisibility": { "scale": 1, "alpha": 1 }, "judgmentVisibility": { "scale": 1, "alpha": 1 }, "comboVisibility": { "scale": 1, "alpha": 1 }, "primaryMetricVisibility": { "scale": 1, "alpha": 1 }, "secondaryMetricVisibility": { "scale": 1, "alpha": 1 }, "judgmentAnimation": { "scale": { "from": 1, "to": 1, "duration": 0, "ease": "linear" }, "alpha": { "from": 1, "to": 0, "duration": 0.2, "ease": "inQuart" } }, "comboAnimation": { "scale": { "from": 1.2, "to": 1, "duration": 0.2, "ease": "inBack" }, "alpha": { "from": 1, "to": 1, "duration": 0, "ease": "linear" } }, "judgmentErrorStyle": "late", "judgmentErrorPlacement": "top", "judgmentErrorMin": 20 } ``` -------------------------------- ### Example response body Source: https://wiki.sonolus.com/custom-server-specs/endpoints/post-sonolus-levels-result-submit Example JSON response showing the structure of the response body with a key and an array of hashes. ```JSON { "key": "...", "hashes": [ // ... ] } ``` -------------------------------- ### Slider Option Example Source: https://wiki.sonolus.com/custom-server-specs/misc/server-option Example of a slider option with query 'minRating', showing configuration for a numeric slider with min, max, and step values. ```json { "query": "minRating", "name": "#RATING_MINIMUM", "required": false, "type": "slider", "def": 0, "min": 0, "max": 100, "step": 1 } ``` -------------------------------- ### Background Data Example (JSON) Source: https://wiki.sonolus.com/background-specs/resources/background-data Example of a background data object with an aspect ratio of 1.778, fit strategy 'cover', and black background color. ```json { "aspectRatio": 1.778, "fit": "cover", "color": "#000000" } ``` -------------------------------- ### Example Response Body Source: https://wiki.sonolus.com/custom-server-specs/endpoints/get-sonolus-type-item-name-leaderboards-leaderboard-name-records-record-name Example JSON response body for the record details endpoint. The `replays` array is shown with a placeholder comment. ```json { "replays": [ // ... ] } ``` -------------------------------- ### SkinData JSON example Source: https://wiki.sonolus.com/skin-specs/resources/skin-data An example of a SkinData JSON resource with width, height, interpolation, and sprites array (sprites not shown). ```JSON { "width": 2048, "height": 2048, "interpolation": true, "sprites": [ // ... ] } ``` -------------------------------- ### BackgroundItem JSON Example Source: https://wiki.sonolus.com/custom-server-specs/misc/background-item Example JSON representation of a BackgroundItem. The tags, thumbnail, data, image, and configuration fields are shown as placeholders. ```json { "name": "bandori-live-00", "version": 2, "title": "デフォルト背景", "subtitle": "BanG Dream! Girls Band Party!", "author": "BanG Dream! Girls Band Party!", "tags": [ // ... ], "thumbnail": { // ... }, "data": { // ... }, "image": { // ... }, "configuration": { // ... } } ``` -------------------------------- ### ServerItemLeaderboardRecord JSON Example Source: https://wiki.sonolus.com/custom-server-specs/misc/server-item-leaderboard-record Example JSON representation of a leaderboard record. The fields name, rank, player, and value are shown as placeholders. ```json { "name": "...", "rank": "...", "player": "...", "value": "..." } ``` -------------------------------- ### Import Particles class Source: https://wiki.sonolus.com/sonolus.py-guide/tutorial/09 Add this import with the other guide imports in guide/tutorial/note.py. ```python from guide.lib.particle import Particles ``` -------------------------------- ### Example JSON Response Source: https://wiki.sonolus.com/custom-server-specs/endpoints/get-sonolus-type-item-name-leaderboards-leaderboard-name-records-list Example response body showing a `pageCount` of 5 and a `records` array. The `records` array is truncated with a comment placeholder. ```json { "pageCount": 5, "records": [ // ... ] } ``` -------------------------------- ### Add function node example Source: https://wiki.sonolus.com/engine-specs/resources/engine-data-node Example JSON for an Add function node. The args array contains indices of argument nodes in the nodes array. ```json { "func": "Add", "args": [1, 2] } ``` -------------------------------- ### Engine Preview Data Archetype JSON Example Source: https://wiki.sonolus.com/engine-specs/resources/engine-preview-data-archetype Example JSON object for an engine preview data archetype named TapNote, with a preprocess callback and an import of #BEAT at index 0. ```json { "name": "TapNote", "preprocess": { "index": 0, "order": 0 }, "imports": [ { "name": "#BEAT", "index": 0 } ] } ``` -------------------------------- ### Initialize project with TS + Oxlint + Oxfmt template Source: https://wiki.sonolus.com/sonolus.js-guide/play/01 Initialize a new project using the TS + Oxlint + Oxfmt template. Run these commands in order to create the project directory, navigate into it, and install dependencies. ```shell npx degit Sonolus/sonolus.js-template-ts-oxlint-oxfmt my-project cd my-project npm i ``` -------------------------------- ### Engine Watch Data JSON Example Source: https://wiki.sonolus.com/engine-specs/resources/engine-watch-data Example JSON resource for engine watch data. The file must be GZip compressed and use the `.json` extension. The `buckets`, `archetypes`, and `nodes` arrays are omitted here for brevity. ```json { "skin": { "sprites": [ { "name": "#NOTE_HEAD_CYAN", "id": 0 } ] }, "effect": { "clips": [ { "name": "#PERFECT", "id": 0 } ] }, "particle": { "effects": [ { "name": "#NOTE_CIRCULAR_TAP_CYAN", "id": 0 } ] }, "buckets": [ // ... ], "archetypes": [ // ... ], "updateSpawn": 0, "nodes": [ // ... ] } ``` -------------------------------- ### Initialization preprocess calling init_ui Source: https://wiki.sonolus.com/sonolus.py-guide/play/03 Calls the init_ui helper during preprocess to set up UI. This is part of the Initialization archetype's one-time setup. ```python from guide.lib.ui import init_ui class Initialization(PlayArchetype): def preprocess(self): init_ui() # ... ``` -------------------------------- ### GET /sonolus/{type}/{itemName} Source: https://wiki.sonolus.com/custom-server-specs/endpoints/get-sonolus-type-item-name Detailed API documentation for the GET /sonolus/{type}/{itemName} endpoint, including parameters, request headers, response body structure, and examples. ```APIDOC ## GET /sonolus/{type}/{itemName} ### Description Provides detailed information of an item of name `{itemName}`. Used by Sonolus app to populate server item details view. ### Method GET ### Endpoint /sonolus/{type}/{itemName} ### Parameters #### Path Parameters - **type** (string) - Required - `posts`, `playlists`, `levels`, `skins`, `backgrounds`, `effects`, `particles`, `engines`, or `replays`. - **itemName** (string) - Required - Name of item. #### Query Parameters - **localization** (string) - Optional - See `localization`. - **Configuration Options** (any) - Optional - See Options Query Parameters. #### Request Headers - **Sonolus-Session** (string) - Optional - See `Sonolus-Session`. #### Request Body None. ### Response #### Success Response (200) - **item** (T) - The item details. - **description** (Text | (string & {})) - Optional - Description of the item. - **actions** (ServerForm[]) - List of actions. - **hasCommunity** (boolean) - Whether the item has community features. - **leaderboards** (ServerItemLeaderboard[]) - List of leaderboards. - **sections** (ServerItemSection[]) - List of sections. #### Response Example ```json { "item": { // ... }, "description": "Description of the item.", "actions": [ // ... ], "hasCommunity": true, "leaderboards": [ // ... ], "sections": [ // ... ] } ``` #### Error Responses - **401 Unauthorized** - Authentication required or expired. - **404 Not Found** - Item not found. #### Response Headers - **Sonolus-Version** (string) - Optional - See `Sonolus-Version`. ``` -------------------------------- ### ServerItemSection JSON example Source: https://wiki.sonolus.com/custom-server-specs/misc/server-item-section Example JSON object for a ServerItemSection with a title of "#RECOMMENDED", itemType "level", and an items array containing levels. The items array is shown as a comment placeholder. ```json { "title": "#RECOMMENDED", "itemType": "level", "items": [ // levels ] } ``` -------------------------------- ### PostItem JSON example Source: https://wiki.sonolus.com/custom-server-specs/misc/post-item Shows an example JSON representation of a PostItem. The name is 'bandori-info', version is 1, title is 'Bandori Information', time is a timestamp, and author is 'BanG Dream! Girls Band Party!'. The tags and thumbnail fields are shown with placeholder comments. ```json { "name": "bandori-info", "version": 1, "title": "Bandori Information", "time": 1640995200000, "author": "BanG Dream! Girls Band Party!", "tags": [ // ... ], "thumbnail": { // ... } } ``` -------------------------------- ### SetAddPointed Source: https://wiki.sonolus.com/engine-specs/functions/set-add-pointed Set a value in a block. Arguments: id (block identifier), index, offset, value. Returns the value. Equivalent to: `Set(Get(id, index), Get(id, index + 1) + offset, Add(Get(Get(id, index), Get(id, index + 1) + offset), value))`. ```APIDOC ## SetAddPointed ### Description Set a value in a block. ### Arguments - **id** (block identifier) - Required - Block identifier - **index** - Required - Index - **offset** - Required - Offset - **value** - Required - Value ### Return Value. ### Remarks Equivalent to: `Set(Get(id, index), Get(id, index + 1) + offset, Add(Get(Get(id, index), Get(id, index + 1) + offset), value))`. ``` -------------------------------- ### TapNote Archetype Example Source: https://wiki.sonolus.com/engine-specs/resources/engine-play-data-archetype Example JSON object for an archetype named TapNote with hasInput true, a preprocess callback, an import of #BEAT at index 0, and an export of hitTime. ```json { "name": "TapNote", "hasInput": true, "preprocess": { "index": 0, "order": 0 }, "imports": [ { "name": "#BEAT", "index": 0 } ], "exports": ["hitTime"] } ``` -------------------------------- ### EnginePlayData JSON Example Source: https://wiki.sonolus.com/engine-specs/resources/engine-play-data Example JSON structure for EnginePlayData. The buckets, archetypes, and nodes arrays are shown with placeholder comments. The file must be GZip compressed and use the .json extension. ```json { "skin": { "sprites": [ { "name": "#NOTE_HEAD_CYAN", "id": 0 } ] }, "effect": { "clips": [ { "name": "#PERFECT", "id": 0 } ] }, "particle": { "effects": [ { "name": "#NOTE_CIRCULAR_TAP_CYAN", "id": 0 } ] }, "buckets": [ // ... ], "archetypes": [ // ... ], "nodes": [ // ... ] } ``` -------------------------------- ### Engine Preview Data JSON Example Source: https://wiki.sonolus.com/engine-specs/resources/engine-preview-data Example JSON structure for engine preview data. The skin section lists sprites with a name and id; archetypes and nodes are placeholders. This resource must be a .json file that is GZip compressed. ```json { "skin": { "sprites": [ { "name": "#NOTE_HEAD_CYAN", "id": 0 } ] }, "archetypes": [ // ... ], "nodes": [ // ... ] } ``` -------------------------------- ### preprocess: init UI, layout, and reset phase Source: https://wiki.sonolus.com/sonolus.py-guide/tutorial/03 Replacement for guide/tutorial/preprocess.py. Calls init_layout(1) with the base note size, initializes the UI, and resets the phase clock via reset_phase() from guide/tutorial/navigate.py. ```python from guide.lib.layout import init_layout from guide.lib.ui import init_ui from guide.tutorial.navigate import reset_phase def preprocess(): init_ui() init_layout(1) reset_phase() ``` -------------------------------- ### JSON example of submit community comment action response Source: https://wiki.sonolus.com/custom-server-specs/endpoints/post-sonolus-type-item-name-community-comments-comment-name-submit Example response body showing the `key`, `hashes`, and optional update flags. The `hashes` array is shown with a comment placeholder. ```JSON { "key": "...", "hashes": [ // ... ], "shouldUpdateCommunity": true, "shouldUpdateComments": true, "shouldNavigateCommentsToPage": 5 } ``` -------------------------------- ### Replace preprocess.py with init_ui call Source: https://wiki.sonolus.com/sonolus.py-guide/tutorial/02 Replaces guide/tutorial/preprocess.py with a minimal preprocess function that calls the shared init_ui helper to set up the tutorial UI. ```python from guide.lib.ui import init_ui def preprocess(): init_ui() ``` -------------------------------- ### RoomItem JSON example Source: https://wiki.sonolus.com/custom-server-specs/misc/room-item Example JSON representation of a RoomItem object, showing placeholder values for name, title, subtitle, master, and tags, with cover, bgm, and preview objects omitted for brevity. ```json { "name": "...", "title": "Let's Play", "subtitle": "Yes! BanG_Dream!", "master": "Player#0000", "tags": [ // ... ], "cover": { // ... }, "bgm": { // ... }, "preview": { // ... } } ``` -------------------------------- ### PreviewInitialization archetype with Transform2d and canvas update Source: https://wiki.sonolus.com/sonolus.py-guide/preview/02 Complete implementation for guide/preview/initialization.py. Moves origin to center-bottom of first panel, scales x by screen height/20 and y by screen height/PANEL_HEIGHT, calls init_ui, and updates canvas with LEFT_TO_RIGHT scroll and size based on all panels. ```python from sonolus.script.archetype import PreviewArchetype from sonolus.script.runtime import ScrollDirection, canvas, screen, set_skin_transform from sonolus.script.transform import Transform2d from sonolus.script.vec import Vec2 from guide.lib import archetype_names from guide.lib.ui import init_ui from guide.preview.chart import PANEL_COUNT, PANEL_HEIGHT, PANEL_WIDTH class PreviewInitialization(PreviewArchetype): name = archetype_names.INITIALIZATION def preprocess(self): init_ui() transform = ( Transform2d.new() .translate(Vec2(PANEL_WIDTH / 2, 0)) .scale(Vec2(screen().h / 20, screen().h / PANEL_HEIGHT)) .translate(screen().bl) ) set_skin_transform(transform) canvas().update( scroll_direction=ScrollDirection.LEFT_TO_RIGHT, size=PANEL_COUNT * PANEL_WIDTH * screen().h / 20, ) ``` -------------------------------- ### Set up instruction UI with ui.instruction.set Source: https://wiki.sonolus.com/sonolus.js-guide/tutorial/02 Sets up instruction UI at the center of the screen to show text explaining the action the player needs to take. Uses Vec.zero as anchor and scales size by ui.configuration.instruction.scale. ```typescript export const initialization = { preprocess() { // ... ui.instruction.set({ anchor: Vec.zero, pivot: { x: 0.5, y: 0.5 }, size: new Vec(1.2, 0.15).mul(ui.configuration.instruction.scale), rotation: 0, alpha: ui.configuration.instruction.alpha, background: true, }) }, } ``` ```javascript export const initialization = { preprocess() { // ... ui.instruction.set({ anchor: Vec.zero, pivot: { x: 0.5, y: 0.5 }, size: new Vec(1.2, 0.15).mul(ui.configuration.instruction.scale), rotation: 0, alpha: ui.configuration.instruction.alpha, background: true, }) }, } ``` -------------------------------- ### Example JSON response Source: https://wiki.sonolus.com/custom-server-specs/endpoints/get-sonolus-type-item-name-community-comments-list Example response body for the comments list endpoint, showing a pageCount of 5 and a comments array with placeholder entries. The comments array is truncated with a comment marker in the example. ```json { "pageCount": 5, "comments": [ // ... ] } ``` -------------------------------- ### Initialize note display component Source: https://wiki.sonolus.com/sonolus.js-guide/tutorial/05 Initializes the note display component as an empty object. This is the starting point for the note display component in the tutorial. ```TypeScript export const noteDisplay = {} ``` ```JavaScript export const noteDisplay = {} ``` -------------------------------- ### PlaylistItem JSON Example Source: https://wiki.sonolus.com/custom-server-specs/misc/playlist-item Example JSON representation of a PlaylistItem, showing required fields like name, version, title, subtitle, author, tags, and levels, with optional thumbnail. The version is always 1. ```json { "name": "bandori-1-expert", "version": 1, "title": "Yes! BanG_Dream!", "subtitle": "Poppin'Party", "author": "BanG Dream! Girls Band Party!", "tags": [ // ... ], "levels": [ // ... ], "thumbnail": { // ... } } ``` -------------------------------- ### LevelItem example JSON Source: https://wiki.sonolus.com/custom-server-specs/misc/level-item Example JSON object for a LevelItem. Shows typical fields like name, version, rating, title, artists, author, and references to engine, skin, background, effect, particle, cover, bgm, and data. Placeholder comments (// ...) indicate omitted nested objects. ```json { "name": "bandori-1-expert", "version": 1, "rating": 20, "title": "Yes! BanG_Dream!", "artists": "Poppin'Party", "author": "BanG Dream! Girls Band Party!", "tags": [ // ... ], "engine": { // ... }, "useSkin": { "useDefault": true }, "useBackground": { "useDefault": true }, "useEffect": { "useDefault": false, "item": { // ... } }, "useParticle": { "useDefault": false, "item": { // ... } }, "cover": { // ... }, "bgm": { // ... }, "data": { // ... } } ``` -------------------------------- ### BeatToStartingTime Source: https://wiki.sonolus.com/engine-specs/functions/beat-to-starting-time Returns the starting time of the BPM change at the specified beat. ```APIDOC ## BeatToStartingTime ### Description Returns the starting time of the BPM change at the specified beat. ### Arguments - **beat** (number) - Required - The beat to query. ### Return Starting time of BPM change at `beat`. ``` -------------------------------- ### ReplayItem JSON example Source: https://wiki.sonolus.com/custom-server-specs/misc/replay-item Example JSON representation of a ReplayItem. The version is 1, and fields like title, subtitle, author, tags, level, data, and configuration are shown with placeholder values. The source field is omitted in this example. ```json { "name": "...", "version": 1, "title": "FC / 987654321", "subtitle": "432 / 1 / 0 / 0", "author": "Player#0000", "tags": [ // ... ], "level": { // ... }, "data": { // ... }, "configuration": { // ... } } ``` -------------------------------- ### GET /sonolus/info Source: https://wiki.sonolus.com/custom-server-specs/endpoints/get-sonolus-info Documentation for the GET /sonolus/info endpoint, which provides server information for the Sonolus app home page. ```APIDOC ## GET /sonolus/info ### Description Provides information of the server, and is used by Sonolus app to populate server home page. ### Method GET ### Endpoint /sonolus/info ### Parameters #### Query Parameters - **localization** (string) - Optional - See localization. - **Configuration Options** (any) - Optional - See Options Query Parameters. #### Request Headers - **Sonolus-Session** (string) - Optional - See Sonolus-Session. ### Request Body None. ### Response #### Success Response (200) - **title** (Text | (string & {})) - Required - Title of the server. - **description** (Text | (string & {})) - Optional - Description of the server. - **buttons** (ServerInfoButton[]) - Required - List of buttons. - **configuration** (ServerConfiguration) - Required - Server configuration. - **banner** (Srl) - Optional - Banner resource. #### Response Example { "title": "My Server Title", "description": "Description of my server.", "buttons": [ // ... ], "configuration": { "options": [ // ... ] }, "banner": { // ... } } #### Error Responses - **401 Unauthorized** - Authentication required or expired. ``` -------------------------------- ### Declare tap instruction and hand icon in guide/tutorial/instructions.py Source: https://wiki.sonolus.com/sonolus.py-guide/tutorial/07 Declares the tutorial-specific instruction and instruction icon classes using the built-in StandardInstruction.TAP and StandardInstructionIcon.HAND resources. Replace guide/tutorial/instructions.py with this content. ```python from sonolus.script.instruction import ( StandardInstruction, StandardInstructionIcon, instruction_icons, instructions, ) @instructions class Instructions: tap: StandardInstruction.TAP @instruction_icons class InstructionIcons: hand: StandardInstructionIcon.HAND ``` -------------------------------- ### Immutable Read Optimization with Get Source: https://wiki.sonolus.com/engine-specs/function-optimizations/block-access-functions When reading from an immutable block, the Get function is replaced with the corresponding value at compile time. ```ts Get(EngineRom, 0) // will be optimized into a value node with corresponding value ``` -------------------------------- ### Replace guide/level.py with Level definition Source: https://wiki.sonolus.com/sonolus.py-guide/play/13 Defines the guide_level Level with metadata, cover, BGM, and entities built from BPMS and NOTE_BEATS. Uses BpmChange and Note archetypes. Note.beat uses StandardImport.BEAT so constructing Note(beat=beat) writes the standard beat field. ```python from sonolus.script.level import BpmChange, Level, LevelData from guide.chart import BPMS, NOTE_BEATS from guide.play.initialization import Initialization from guide.play.note import Note from guide.play.stage import Stage guide_level = Level( name="guide", title="Patience", artists="More Plastic & VinDon", author="ntsu", description=( "Song: More Plastic & VinDon - Patience\n" "Music provided by NoCopyrightSounds\n" "Free Download/Stream: http://NCS.io/Patience\n" "Watch: https://youtu.be/Lxf65uhlR6s" ), cover="levels/patience/cover.jpg", bgm="levels/patience/bgm.mp3", data=LevelData( bgm_offset=0, entities=[ Initialization(), Stage(), *(BpmChange(beat=beat, bpm=bpm) for beat, bpm in BPMS), *(Note(beat=beat) for beat in NOTE_BEATS), ], ), ) def load_levels(): yield guide_level ``` -------------------------------- ### Call init_layout from preprocess in initialization.py Source: https://wiki.sonolus.com/sonolus.py-guide/play/04 Adds the init_layout import and calls it from preprocess in guide/play/initialization.py. Passes 1 as the note_size multiplier for now. ```python from guide.lib.layout import init_layout from guide.lib.ui import init_ui class Initialization(PlayArchetype): def preprocess(self): init_ui() init_layout(1) ``` -------------------------------- ### Effect Data Clip Example Source: https://wiki.sonolus.com/effect-specs/resources/effect-data-clip Example JSON object for an effect data clip with name '#PERFECT' and filename 'perfect.mp3'. ```json { "name": "#PERFECT", "filename": "perfect.mp3" } ``` -------------------------------- ### SRL JSON Example Source: https://wiki.sonolus.com/custom-server-specs/misc/srl Example JSON representation of an SRL resource object, showing the optional `hash` and `url` fields. ```json { "hash": "...", "url": "https:// ..." } ``` -------------------------------- ### Show tap instruction in draw_frozen in guide/tutorial/note.py Source: https://wiki.sonolus.com/sonolus.py-guide/tutorial/07 Adds the Instructions import and replaces draw_frozen in guide/tutorial/note.py to show the tap instruction while the frozen range is active. Calling show() replaces any currently displayed instruction, and the instruction remains visible until replaced or cleared. ```python from guide.tutorial.instructions import Instructions def draw_frozen(elapsed: float): Instructions.tap.show() draw_note(1) ``` -------------------------------- ### Call init_buckets from Initialization.preprocess in guide/play/initialization.py Source: https://wiki.sonolus.com/sonolus.py-guide/play/15 Imports init_buckets and calls it inside the preprocess method of Initialization. This runs once because there is one Initialization entity. ```python from guide.lib.buckets import init_buckets class Initialization(PlayArchetype): def preprocess(self): # ... init_buckets() # ... ``` -------------------------------- ### GameplayResult JSON Example Source: https://wiki.sonolus.com/replay-specs/misc/gameplay-result Example JSON object representing a GameplayResult with an 'allPerfect' grade, showing all fields populated with sample values. ```json { "grade": "allPerfect", "arcadeScore": 1000000, "accuracyScore": 987654, "combo": 765, "perfect": 765, "great": 0, "good": 0, "miss": 0, "totalCount": 765 } ``` -------------------------------- ### JSON property expression example Source: https://wiki.sonolus.com/particle-specs/essentials/particle-effect-particle-property-expression Example JSON configuration for a particle property expression, defining coefficients for inputs 'c' and 'cosr1'. ```json { "x": { "c": 0.1, "cosr1": 0.2 } } ``` -------------------------------- ### Build project with uv run sonolus-py build Source: https://wiki.sonolus.com/sonolus.py-guide/preview/10 Builds the project from the project directory to verify the changes. Run this command after adding the timescale change implementation. ```shell uv run sonolus-py build ``` -------------------------------- ### Basic Note Touch and Despawn Check in Python (sonolus.script.runtime) Source: https://wiki.sonolus.com/sonolus.py-guide/play/11 Adds touch handling to despawn the note when a started touch is found, and adds an early return in update_parallel if despawned. Replace the existing `time` import in `guide/play/note.py` with the combined import shown below. ```python from sonolus.script.runtime import time, touches class Note(PlayArchetype): # ... def touch(self): for touch in touches(): if not touch.started: continue self.despawn = True return def update_parallel(self): if self.despawn: return # ... ``` -------------------------------- ### Paint Source: https://wiki.sonolus.com/engine-specs/functions/paint Paints an instruction icon with the given parameters. Only available in tutorial mode. ```APIDOC ## Paint ### Description Paints an instruction icon with the specified properties. This function is only available in tutorial mode. ### Method Paint ### Endpoint Paint ### Parameters #### Arguments - **id** (string) - Required - Icon identifier - **x** (number) - Required - X coordinate - **y** (number) - Required - Y coordinate - **size** (number) - Required - Size of the icon - **rotation** (number) - Required - Rotation angle - **z** (number) - Required - Z-order - **a** (number) - Required - Alpha (opacity) ### Return `0` ### Remarks Only available in tutorial. ``` -------------------------------- ### Example response body Source: https://wiki.sonolus.com/custom-server-specs/endpoints/post-sonolus-rooms-item-name Example JSON response body for the room join endpoint, showing the url, type, and session fields. ```json { "url": "wss://...", "type": "round", "session": "..." } ``` -------------------------------- ### Use Options.note_size in Initialization preprocess Source: https://wiki.sonolus.com/sonolus.py-guide/play/22 Imports Options and replaces init_layout(1) with init_layout(Options.note_size) in the Initialization archetype's preprocess method, so the note layout uses the selected note size. ```python from guide.lib.layout import init_layout from guide.lib.options import Options from guide.lib.ui import init_ui class Initialization(PlayArchetype): def preprocess(self): # ... init_ui() init_layout(Options.note_size) # ... ``` -------------------------------- ### Set up menu UI with ui.menu.set Source: https://wiki.sonolus.com/sonolus.js-guide/tutorial/02 Sets up the menu UI at the top-left corner of the screen in the initialization component's preprocess method. Uses safeArea.rect.lt offset by (0.05, -0.05) and scales size by ui.configuration.menu.scale. ```typescript export const initialization = { preprocess() { ui.menu.set({ anchor: safeArea.rect.lt.add(new Vec(0.05, -0.05)), pivot: { x: 0, y: 1 }, size: new Vec(0.15, 0.15).mul(ui.configuration.menu.scale), rotation: 0, alpha: ui.configuration.menu.alpha, background: true, }) }, } ``` ```javascript export const initialization = { preprocess() { ui.menu.set({ anchor: safeArea.rect.lt.add(new Vec(0.05, -0.05)), pivot: { x: 0, y: 1 }, size: new Vec(0.15, 0.15).mul(ui.configuration.menu.scale), rotation: 0, alpha: ui.configuration.menu.alpha, background: true, }) }, } ``` -------------------------------- ### Example response body Source: https://wiki.sonolus.com/custom-server-specs/endpoints/post-sonolus-levels-result-upload Example response body for the POST /sonolus/levels/result/upload endpoint. It is an empty JSON object, matching the ServerUploadLevelResultResponse type. ```json {} ```