diff --git a/packages/plugins/README.mdown b/packages/plugins/README.mdown index f026fb68..ce800f6a 100644 --- a/packages/plugins/README.mdown +++ b/packages/plugins/README.mdown @@ -2,21 +2,53 @@ Plugins are client-side code that players can run in the Sky Strife client to modify their gameplay experience. Full access is given to Sky Strife's internal client API. +![plugin button location](./public/button.png) +You can open the Plugin Manager using the button in the upper-right of the Sky Strife client. + +![plugin manager sidebar](./public/sidebar.png) +Here you can add, remove, or run your plugins. + +![example plugin window](./public/plugin_window.png) +Each plugin receives it's own movable window to render into. + ## Getting Started Using the plugin dev server is the easiest way to start plugin development. To start, run (in this directory): + - `pnpm install` - `pnpm run dev` This will start the plugin dev server. It automatically looks for plugin files in the `dev` folder and makes them available to any Sky Strife client you are currently connected to. +![dev server notification](./public/dev_server.png) +If everything is working correctly, this should appear in your Plugin Manager. Now when you edit any files in your `dev` folder, they will be available in your Plugin Manager. +> NOTE: Hot realoding is not currently implemented, so you will need to manually refresh when changing your plugins. + +Plugins must implement this interface: +```typescript +function createPlugin(pluginLayer: PluginLayer) { + // Code here will be run on plugin initialization + + return { + // Called when a plugin is run + mount: (container: HTMLDivElement) => {}, + // Called when a plugin is stopped or destroyed + // Use this to clean up anything your plugin has setup + // i.e. hotkeys, in-game visuals + unmount: () => {} + } +} +``` + +You can view the `PluginLayer` API [here](https://github.com/latticexyz/skystrife/blob/main/packages/client/src/layers/Plugins/createPluginLayer.ts). + ## Examples There are some example plugins provided in the client by default. The purpose of these is to introduce players to what is possible with a plugin and inspire them to create their own. Currently, the examples are: - - `Frenzy`: Provides a hotkey that commands on of your units to attack the nearest enemy automatically. It has a small informational UI and also highlights the intended target in-game. This is a good introduction to gameplay plugins as it accesses enemy unit information, does some calculation, and issues an attack transaction on behalf of the user. - - `Player Details`: Display a more detailed view of a player in your match. This introduces fetching data that is not otherwise shown in the Sky Strife UI. - - `Simple Example`: This example is used to show all of the built in UI components provided by plugins. You can use this as a starting point for a new plugin. +- `Frenzy`: Provides a hotkey that commands on of your units to attack the nearest enemy automatically. It has a small informational UI and also highlights the intended target in-game. This is a good introduction to gameplay plugins as it accesses enemy unit information, does some calculation, and issues an attack transaction on behalf of the user. +- `Player Details`: Display a more detailed view of a player in your match. This introduces fetching data that is not otherwise shown in the Sky Strife UI. +- `Simple Example`: This example is used to show all of the built in UI components provided by plugins. You can use this as a starting point for a new plugin. ## Plugin API @@ -69,11 +101,10 @@ function createPlugin(pluginLayer: PluginLayer) { unmount: () => {}, }; } - ``` ## Security Considerations > Plugins have FULL access to the Sky Strife client. This means they have access to the **private key of your session wallet**. Malicious plugins could steal this key, steal any ETH in your session wallet, or take control of your units in a match. -That being said, the attack surface of your session wallet key is limited. There should only ever be a small amount of ETH in your session wallet, and if you've suspected that it is compromised you can revoke and generate a new session wallet easily. \ No newline at end of file +That being said, the attack surface of your session wallet key is limited. There should only ever be a small amount of ETH in your session wallet, and if you've suspected that it is compromised you can revoke and generate a new session wallet easily. diff --git a/packages/plugins/public/button.png b/packages/plugins/public/button.png new file mode 100644 index 00000000..05d06b19 Binary files /dev/null and b/packages/plugins/public/button.png differ diff --git a/packages/plugins/public/dev_server.png b/packages/plugins/public/dev_server.png new file mode 100644 index 00000000..21d74738 Binary files /dev/null and b/packages/plugins/public/dev_server.png differ diff --git a/packages/plugins/public/plugin_window.png b/packages/plugins/public/plugin_window.png new file mode 100644 index 00000000..614a67b7 Binary files /dev/null and b/packages/plugins/public/plugin_window.png differ diff --git a/packages/plugins/public/sidebar.png b/packages/plugins/public/sidebar.png new file mode 100644 index 00000000..27ba7b3b Binary files /dev/null and b/packages/plugins/public/sidebar.png differ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 768c7efe..2ae4bbe0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -368,9 +368,6 @@ importers: abitype: specifier: 0.9.3 version: 0.9.3(typescript@5.2.2) - ace-builds: - specifier: 1.32.6 - version: 1.32.6 async-mutex: specifier: ^0.3.2 version: 0.3.2 @@ -455,9 +452,6 @@ importers: react: specifier: ^18.2.0 version: 18.2.0 - react-ace: - specifier: 10.1.0 - version: 10.1.0(react-dom@18.2.0)(react@18.2.0) react-collapse: specifier: ^5.1.1 version: 5.1.1(react@18.2.0) @@ -5989,10 +5983,6 @@ packages: negotiator: 0.6.3 dev: false - /ace-builds@1.32.6: - resolution: {integrity: sha512-dO5BnyDOhCnznhOpILzXq4jqkbhRXxNkf3BuVTmyxGyRLrhddfdyk6xXgy+7A8LENrcYoFi/sIxMuH3qjNUN4w==} - dev: false - /acorn-jsx@5.3.2(acorn@8.10.0): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -7249,10 +7239,6 @@ packages: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} dev: false - /diff-match-patch@1.0.5: - resolution: {integrity: sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==} - dev: false - /diff@4.0.2: resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} engines: {node: '>=0.3.1'} @@ -9738,10 +9724,6 @@ packages: resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} dev: false - /lodash.get@4.4.2: - resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} - dev: false - /lodash.isequal@4.5.0: resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} dev: false @@ -11384,21 +11366,6 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /react-ace@10.1.0(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-VkvUjZNhdYTuKOKQpMIZi7uzZZVgzCjM7cLYu6F64V0mejY8a2XTyPUIMszC6A4trbeMIHbK5fYFcT/wkP/8VA==} - peerDependencies: - react: ^0.13.0 || ^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 - react-dom: ^0.13.0 || ^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 - dependencies: - ace-builds: 1.32.6 - diff-match-patch: 1.0.5 - lodash.get: 4.4.2 - lodash.isequal: 4.5.0 - prop-types: 15.8.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - dev: false - /react-collapse@5.1.1(react@18.2.0): resolution: {integrity: sha512-k6cd7csF1o9LBhQ4AGBIdxB60SUEUMQDAnL2z1YvYNr9KoKr+nDkhN6FK7uGaBd/rYrYfrMpzpmJEIeHRYogBw==} peerDependencies: