diff --git a/client/src/services/Api.js b/client/src/services/Api.js index 53ba1e8b..1e3c82e3 100644 --- a/client/src/services/Api.js +++ b/client/src/services/Api.js @@ -7,6 +7,7 @@ import * as _Sound from "@/services/Sound" import * as _Tooltip from "@/services/Tooltip" import * as _Windows from "@/services/Windows" import Server from '@/services/Server'; +import { socket } from '@/services/Socket'; /** * Class for managing the client api @@ -16,6 +17,7 @@ class ClientApi { #_plugin #_router #_windows + #_socket /** * @param {*} plugin @@ -24,6 +26,7 @@ class ClientApi { this.#_plugin = plugin this.#_router = new ClientRouter(plugin.package) this.#_windows = new ClientWindows(plugin.package) + this.#_socket = new ClientSocket(plugin.package) } /** @@ -86,6 +89,10 @@ class ClientApi { get windows(){ return this.#_windows; } + + get socket(){ + return this.#_socket; + } } /** @@ -245,6 +252,18 @@ class ClientModule { } } +class ClientSocket { + #_package + + constructor(plugin){ + this.#_package = plugin; + } + + on(msg, callback){ + socket.on(`${this.#_package}/${msg}`, callback); + } +} + /** * @typedef {Object} Response * @property {Object} data diff --git a/documentation/docs/.vuepress/config.js b/documentation/docs/.vuepress/config.js index d3ea143c..5344a505 100644 --- a/documentation/docs/.vuepress/config.js +++ b/documentation/docs/.vuepress/config.js @@ -18,7 +18,7 @@ export default defineUserConfig({ text: "Guides", prefix: "/guide/", link: "/guide/", - children: ['/get-started'] + children: ['/get-started', '/firstplugin'] }, { diff --git a/documentation/docs/firstplugin.md b/documentation/docs/firstplugin.md index 4285d95f..c40b1162 100644 --- a/documentation/docs/firstplugin.md +++ b/documentation/docs/firstplugin.md @@ -1,3 +1,5 @@ +# Creating a plugin + This guide will help you through creating a plugin for Dragonroll ## Downloading the example plugin @@ -34,36 +36,118 @@ Your `plugin.json` file defines important information about your plugin, like it **Important**: The `package` field must be identical to the name of the folder containing your entire plugin > `plugin.json` -> ```json -> { -> "package": "your-plugin", -> "name": "My custom plugin", -> "description": "This is my first custom plugin", -> "authors": [ -> { -> "name": "Aran Roig" -> } -> ], -> "version": "1.0", -> "client": { -> "entrypoint": "main.js" -> }, -> "backend": { -> "entrypoint": "main.js" -> } -> } -> ``` +```json +{ + "package": "your-plugin", + "name": "My custom plugin", + "description": "This is my first custom plugin", + "authors": [ + { + "name": "Aran Roig" + } + ], + "version": "1.0", + "client": { + "entrypoint": "main.js" + }, + "backend": { + "entrypoint": "main.js" + } +} +``` ## Entrypoints When Dragonroll registers a plugin, it calls the `Main` method of the file specified in the entrypoint field inside the `plugin.json`, so if you don't export a function with that name your plugin won't load. Dragonroll passes its entire API through the main method -> `client/main.js` and `backend/main.js` -> ```js main.js -> function Main(Api){ -> console.log("Hello World!"); -> } -> export { Main }; -> ``` +> `client/main.js` +> `backend/main.js` +```js main.js +function Main(Api){ + console.log("Hello World!"); +} +export { Main }; +``` -In the client entrypoint, the `Api` variable will be a `ClientApi` object. In the backend entrypoint, the `Api` will be instead a `BackendApi` object. \ No newline at end of file +In the client entrypoint, the `Api` variable will be a `ClientApi` object. In the backend entrypoint, the `Api` will be instead a `BackendApi` object. + +If you want to make the `Api` object accessible throught your plugin files, you need to export it and then import `main.js` using relative paths: + +> `client/main.js` +> `backend/main.js` +```js main.js +let Api; +function Main(api){ + Api = api; + console.log("Hello World!"); +} +export { Main, Api }; +``` + +> `client/otherfile.js` +```js +import { Api } from './main.js' +// Do whatever +``` + +## Creating a window + +In Dragonroll, windows are managed in a data-oriented approach, each window has a `type` that defines what view corresponds to it, and then it has an `id` to identify every window. These two fields are mandatory for creating a window, and `id` must be unique. For ensuring that `type` and `id` won't collide with other plugins, the Dragonroll Api handles a prefix with the name of your package for all the ids you set. + +### Window view + +You can spawn Dragonroll internal windows or also you can create your own type with the `registerWindow` method. First, you need to create a view inside `client/views` folder: + +> `ExampleWindow.vue` +```vue + + + + + + +``` + +There's a lot to unpack here. Each Dragonroll window that is created contains a `data` prop. This contains all the information that has been supplied from the `createWindow` method, including the id and its type. Also, you will see that it has a `WindowHandle` partial. This draws the handle, and the `SetupHandle` function adds internal logic to it. + +You should add the body of the window where `

Hello window world!

` is placed. + +### Registering the window + +Call `registerWindow`, passing the view (without the .vue extension): + +```js +let exampleWindowView = Api.createView('ExampleWindow') +let exampleWindow = Api.registerWindow('example_window', exampleWindowView); +``` + +the first parameter of `registerWindow` is the `type` of the new window that is being registered, and the view is what Dragonroll will spawn as the window. + +### Creating the window + +```js +Api.createWindow(exampleWindow) +``` + +Keep in mind that `registerWindow` returns a `String` with the type of the registered window with the plugin prefix appended \ No newline at end of file diff --git a/plugins/dnd-5e/client/data.js b/plugins/dnd-5e/client/data.js index 5513d1e4..5d863867 100644 --- a/plugins/dnd-5e/client/data.js +++ b/plugins/dnd-5e/client/data.js @@ -4,7 +4,6 @@ import Server from '@/services/Server' import { reactive } from 'vue'; import { GetCampaign } from "@/services/Dragonroll"; -import { socket } from '@/services/Socket'; let data = reactive({}); @@ -24,9 +23,15 @@ function FetchData(){ FetchConcepts(); } +Api.socket.on('update-concepts', () => { + FetchConcepts(); +}); + +/* socket.on('update-concepts', () => { FetchConcepts(); }); +*/ let GetConcepts = () => data.value.concepts; let GetConcept = (id) => Server().get('/concept/get?campaign=' + GetCampaign()._id + "&id=" + id) diff --git a/plugins/dnd-5e/client/main.js b/plugins/dnd-5e/client/main.js index b95d4c95..121ce8a2 100644 --- a/plugins/dnd-5e/client/main.js +++ b/plugins/dnd-5e/client/main.js @@ -59,7 +59,6 @@ function Main(api){ // Api.windows.registerWindow('create_item_prompt', Api.createView('CreateItemPrompt')); dndModule.init = () => { - console.log("INIT") InitData(); FetchData(); }