UNPKG

@minecraft/creator-tools

Version:

Minecraft Creator Tools command line and libraries.

145 lines (128 loc) 6.04 kB
// Copyright (c) Mojang AB. All rights reserved. import { ActionTypes, CoreMenuType, IMenu, IPlayerUISession, registerEditorExtension, } from "@minecraft/server-editor"; /** * Per player storage can be attached to the IPlayerUISession type in a type safe manner for anything * you'd like to store and access in a player contextual manner. This makes the data safe for multiplayer * usage. This type can be passed to the registerEditorExtension function as a generic parameter to make * all access type safe. */ type PerPlayerStorage = { NUM_TIMES_PLAYER_CLICKED: number; }; // Output a message in the log window displaying the player's name and the number of times // the button has been clicked function showPlayerMessage(uiSession: IPlayerUISession<PerPlayerStorage>) { if (!uiSession.scratchStorage) { uiSession.log.error("We're missing scratch storage - this shouldn't happen!"); return; } const clickCount = uiSession.scratchStorage.NUM_TIMES_PLAYER_CLICKED; uiSession.log.info(`Hello ${uiSession.extensionContext.player.name} - You clicked ${clickCount} times`); } function incrementClickValue(storage: PerPlayerStorage) { storage.NUM_TIMES_PLAYER_CLICKED++; } /** * Provides a sample extension registration function * @public */ export function registerBasicsExtension() { registerEditorExtension<PerPlayerStorage>( "minimal-template-sample", // Provide a function closure which is executed when each player connects to the server // The uiSession object holds the context for the extension and the player (uiSession) => { uiSession.log.debug( `Initializing extension [${uiSession.extensionContext.extensionInfo.name}] for player [${uiSession.extensionContext.player.name}]` ); // Initialize the player specific, custom extension storage structure with whatever // the extension needs to store, and assign it to the `uiSession.scratchStorage` variable. // Using this in combination with JavaScript closure captures, you can access this player/extension // storage area in whatever events you need it const storage: PerPlayerStorage = { NUM_TIMES_PLAYER_CLICKED: 0, }; uiSession.scratchStorage = storage; // Create a basic property pane with a button. Property panes are the basic panels on to which you // can attach buttons, sliders and various other UI elements. // When you create a property pane, you bind it with an object which contains the values which represent // the contents of the UI elements you bind to the pane. The binding object is a 'property bag' - a simple // key/value pair collection which the UI elements modify when they are actioned. // E.g. if you were to create a slider, the slider would be bound to a property 'mySlider' for example, and // when you adjust the slider, you can inspect the binding object property 'mySlider' for the current value. const extensionPane = uiSession.createPropertyPane({ title: { id: "sample.minimal.pane.title", }, }); // Creating UI elements like buttons and sliders require a couple of simple steps. // - Create an action (a function declaration of what you want to happen when the element is actioned) // - Create the UI element and bind it to the action // (You can define a single action and bind it to many UI elements if you wish) const buttonAction = uiSession.actionManager.createAction({ actionType: ActionTypes.NoArgsAction, onExecute: () => { // Increment the click value in the player's storage incrementClickValue(storage); // Send a message to the log window showing the player's name and the number of times // you've hit the button showPlayerMessage(uiSession); }, }); // Now create a button and bind the action you want to execute when it's pressed extensionPane.addButton(buttonAction, { title: { id: "sample.minimal.pane.button.clickme" }, visible: true, }); // Try to get predefined top level core menu uiSession.menuBar .getMenu(CoreMenuType.Extensions) .then((coreMenu: IMenu) => { // Create a menu entry in the menu bar Core menu const extensionMenu = coreMenu.addItem({ label: "sample.minimal.menu.title", }); // Adds a child menu item to show the property pane // Note - we're creating an action too, which can be executed when the menu // item is selected extensionMenu.addItem( { label: "sample.minimal.menu.showpane", }, uiSession.actionManager.createAction({ actionType: ActionTypes.NoArgsAction, onExecute: () => { // make sure we show the property pane (in case you might have closed it) extensionPane.show(); }, }) ); }) .catch((error: Error) => { uiSession.log.error(error.message); }); // Normally we return a collection of IDisposable objects that the extension system will clean // up and dispose of on shutdown. We don't have any in this example, so let's just return // an empty collection return []; }, // Provide a function which is executed when the player disconnects from the server // This is where the extension would normally clean up any resources it created/loaded during activation (uiSession: IPlayerUISession<PerPlayerStorage>) => { // Do any explicit cleanup when a player is leaving and the extension instance is shutting down uiSession.log.debug( `Shutting down extension [${uiSession.extensionContext.extensionInfo.name}] for player [${uiSession.extensionContext.player.name}]` ); }, // Descriptor for the extension { description: "Basic Sample Extension", } ); }