Mes coses
This commit is contained in:
parent
73a3432c57
commit
d5856416fa
@ -84,7 +84,7 @@ class BackendRouter {
|
|||||||
/**
|
/**
|
||||||
* @hideconstructor
|
* @hideconstructor
|
||||||
*/
|
*/
|
||||||
class Model {
|
class BackendModel {
|
||||||
#_name;
|
#_name;
|
||||||
#_plugin;
|
#_plugin;
|
||||||
#_schema;
|
#_schema;
|
||||||
|
1
build.sh
1
build.sh
@ -1,5 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Gen docs
|
# Gen docs
|
||||||
npm run generate-docs
|
npm run generate-docs
|
||||||
|
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 82 KiB |
@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"id": "dnd-5e",
|
|
||||||
"title": "Dungeons & Dragons 5e",
|
|
||||||
"description": "Dungeons & Dragons Fifth edition game system support",
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Aran Roig"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"version": "1.0.0",
|
|
||||||
"color": "#e92026"
|
|
||||||
}
|
|
@ -15,13 +15,41 @@ import Server from '@/services/Server';
|
|||||||
class ClientApi {
|
class ClientApi {
|
||||||
#_plugin
|
#_plugin
|
||||||
#_router
|
#_router
|
||||||
|
#_windows
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {*} plugin
|
* @param {*} plugin
|
||||||
*/
|
*/
|
||||||
constructor(plugin){
|
constructor(plugin){
|
||||||
this.#_plugin = plugin
|
this.#_plugin = plugin
|
||||||
this.#_router = new ClientRouter()
|
this.#_router = new ClientRouter(plugin.package)
|
||||||
|
this.#_windows = new ClientWindows(plugin.package)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} path The path to the view relative to the client folder
|
||||||
|
* @returns {ClientView} a new ClientView corresponding to the view
|
||||||
|
*/
|
||||||
|
createView(path){
|
||||||
|
return new ClientView(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new registered Module
|
||||||
|
* @param {string} id The id of the new module
|
||||||
|
* @returns {ClientModule}
|
||||||
|
*/
|
||||||
|
createModule(id){
|
||||||
|
return new ClientModule(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a ClientModule
|
||||||
|
* @param {ClientModule} module The client module
|
||||||
|
*/
|
||||||
|
registerModule(module){
|
||||||
|
_Modules.CreateModule(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -31,6 +59,107 @@ class ClientApi {
|
|||||||
get router(){
|
get router(){
|
||||||
return this.#_router;
|
return this.#_router;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the windows object
|
||||||
|
* @type {ClientWindows}
|
||||||
|
*/
|
||||||
|
get windows(){
|
||||||
|
return this.#_windows;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for managing Dragonroll windows
|
||||||
|
* @hideconstructor
|
||||||
|
*/
|
||||||
|
class ClientWindows {
|
||||||
|
#_plugin;
|
||||||
|
|
||||||
|
constructor(plugin){
|
||||||
|
this.#_plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a new window for the given view
|
||||||
|
* @param {string} name
|
||||||
|
* @param {ClientView} view
|
||||||
|
*/
|
||||||
|
registerWindow(name, view){
|
||||||
|
_Windows.InjectWindow(`${this.#_plugin}/${name}`, this.#_plugin, view.path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for managing client views
|
||||||
|
* @hideconstructor
|
||||||
|
*/
|
||||||
|
class ClientView {
|
||||||
|
|
||||||
|
#_path;
|
||||||
|
|
||||||
|
constructor(path){
|
||||||
|
this.#_path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {string} The path of the view
|
||||||
|
*/
|
||||||
|
get path(){
|
||||||
|
return this.#_path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hideconstructor
|
||||||
|
*/
|
||||||
|
class ClientModule {
|
||||||
|
#_id;
|
||||||
|
#_title;
|
||||||
|
#_description;
|
||||||
|
#_version;
|
||||||
|
#_color;
|
||||||
|
#_icon;
|
||||||
|
|
||||||
|
constructor(id){ this.#_id = id; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The title of the module
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
set title(title) { this.#_title = title; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The description of the module
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
set description(description){ this.#_description = description; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The version of the module
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
set version(version){ this.#_version = version; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The accent color of the module. This will be displayed for example
|
||||||
|
* in the background title inside the campaign preview
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
set color(color){ this.#_color = color; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the icon for the module. It must be placed inside the public folder of the plugin
|
||||||
|
*/
|
||||||
|
set icon(icon){ this.#_icon = icon; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the module info in a json format
|
||||||
|
* @returns {Object}
|
||||||
|
*/
|
||||||
|
get info(){
|
||||||
|
return {id: this.#_id, title: this.#_title, description: this.#_description, version: this.#_version, color: this.#_color, icon: this.#_icon}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -65,59 +194,74 @@ class ClientRouter {
|
|||||||
* @param {routerCallback} callback
|
* @param {routerCallback} callback
|
||||||
*/
|
*/
|
||||||
get(route, callback){
|
get(route, callback){
|
||||||
Server().get(`${path}/${route}`).then(response => callback(response)).catch(err => console.log(err));
|
Server().get(`${path}/${route}`).then(callback).catch(err => console.log(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Sends a post request to specified plugin route
|
||||||
* @param {String} route
|
* @param {String} route
|
||||||
*
|
* @param {Object} data
|
||||||
|
* @param {routerCallback} callback
|
||||||
*/
|
*/
|
||||||
post(route){
|
post(route, data, callback){
|
||||||
|
Server().post(`${path}/${route}`, data).then(callback).catch(err => console.log(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Sends a put request to specified plugin route
|
||||||
* @param {String} route
|
* @param {String} route
|
||||||
*
|
* @param {Object} data
|
||||||
|
* @param {routerCallback} callback
|
||||||
*/
|
*/
|
||||||
put(route){
|
put(route, data, callback){
|
||||||
|
Server().put(`${path}/${route}`, data).then(callback).catch(err => console.log(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Sends a delete request to specified plugin route
|
||||||
* @param {String} route
|
* @param {String} route
|
||||||
*
|
* @param {routerCallback} callback
|
||||||
*/
|
*/
|
||||||
delete(route){
|
delete(route, callback){
|
||||||
|
Server().delete(`${route}`).then(callback).catch(err => console.log(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Sends a get request to an specified route
|
||||||
|
* @param {String} route
|
||||||
|
* @param {routerCallback} callback
|
||||||
*/
|
*/
|
||||||
baseGet(){
|
baseGet(route, callback){
|
||||||
|
Server().get(`${route}`).then(callback).catch(err => console.log(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Sends a post request to specified route
|
||||||
|
* @param {String} route
|
||||||
|
* @param {Object} data
|
||||||
|
* @param {routerCallback} callback
|
||||||
*/
|
*/
|
||||||
basePost(){
|
basePost(route, data, callback){
|
||||||
|
Server().post(`${route}`, data).then(callback).catch(err => console.log(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Sends a put request to specified route
|
||||||
|
* @param {String} route
|
||||||
|
* @param {Object} data
|
||||||
|
* @param {routerCallback} callback
|
||||||
*/
|
*/
|
||||||
baseUpdate(){
|
basePut(route, data, callback){
|
||||||
|
Server().put(`${route}`, data).then(callback).catch(err => console.log(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Sends a delete request to specified route
|
||||||
|
* @param {String} route
|
||||||
|
* @param {routerCallback} callback
|
||||||
*/
|
*/
|
||||||
baseDelete(){
|
baseDelete(route, callback){
|
||||||
|
Server().delete(`${route}`).then(callback).catch(err => console.log(err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,37 +1,33 @@
|
|||||||
let modulesToLoad = [
|
let modules = {};
|
||||||
"dnd-5e"
|
|
||||||
]
|
|
||||||
let modules = [];
|
|
||||||
|
|
||||||
|
function CreateModule(module){
|
||||||
|
let moduleInfo = module.info;
|
||||||
|
modules[moduleInfo.id] = moduleInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
async function GetJson(url){
|
async function GetJson(url){
|
||||||
let obj = await (await fetch(url)).json();
|
let obj = await (await fetch(url)).json();
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
async function ImportModule(moduleFolder) {
|
async function ImportModule(moduleFolder) {
|
||||||
let moduleInfo = await GetJson('/modules/' + moduleFolder + '/module.json');
|
let moduleInfo = await GetJson('/modules/' + moduleFolder + '/module.json');
|
||||||
modules.push(moduleInfo);
|
modules.push(moduleInfo);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
let GetModules = () => modules;
|
let GetModules = () => modules;
|
||||||
let GetModulesToLoad = () => modulesToLoad;
|
// let GetModulesToLoad = () => modulesToLoad;
|
||||||
|
|
||||||
function GetModule(id){
|
function GetModule(id){
|
||||||
let module = null;
|
return modules[id];
|
||||||
modules.forEach(mod => {
|
|
||||||
if(mod.id == id) module = mod;
|
|
||||||
})
|
|
||||||
return module;
|
|
||||||
}
|
|
||||||
|
|
||||||
function CreateModule(moduleInfo, registeredWindows){
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
ImportModule,
|
|
||||||
CreateModule,
|
CreateModule,
|
||||||
GetModules,
|
GetModules,
|
||||||
GetModule,
|
GetModule,
|
||||||
GetModulesToLoad,
|
|
||||||
}
|
}
|
@ -67,9 +67,9 @@ let windowMap = {
|
|||||||
plugin_window: PluginWindow
|
plugin_window: PluginWindow
|
||||||
};
|
};
|
||||||
|
|
||||||
async function InjectWindow(plugin, window_type, window_component){
|
async function InjectWindow(window_type, plugin, window_component){
|
||||||
let systemWidows = {};
|
let systemWidows = {};
|
||||||
systemWidows[plugin + "/" + window_type] = (await import(`../../plugins/${plugin}/views/${window_component}.vue`)).default;
|
systemWidows[window_type] = (await import(`../../plugins/${plugin}/views/${window_component}.vue`)).default;
|
||||||
windowMap = {...windowMap, ...systemWidows};
|
windowMap = {...windowMap, ...systemWidows};
|
||||||
|
|
||||||
console.log("Window injected");
|
console.log("Window injected");
|
||||||
|
@ -10,7 +10,6 @@ import { CreateWindow } from '@/services/Windows'
|
|||||||
import { GetUser, HasAdmin, LoadUser } from '@/services/User.js'
|
import { GetUser, HasAdmin, LoadUser } from '@/services/User.js'
|
||||||
import { DisplayToast, SetEmitter } from '@/services/Dragonroll';
|
import { DisplayToast, SetEmitter } from '@/services/Dragonroll';
|
||||||
import { FetchResources } from '@/services/Resources';
|
import { FetchResources } from '@/services/Resources';
|
||||||
import { ImportModule } from '@/services/Modules';
|
|
||||||
import { FetchPlugins } from '@/services/Plugins';
|
import { FetchPlugins } from '@/services/Plugins';
|
||||||
import useEmitter from '@/services/Emitter';
|
import useEmitter from '@/services/Emitter';
|
||||||
const emitter = useEmitter();
|
const emitter = useEmitter();
|
||||||
@ -65,8 +64,6 @@ async function start(){
|
|||||||
await FetchResources();
|
await FetchResources();
|
||||||
await FetchPlugins();
|
await FetchPlugins();
|
||||||
|
|
||||||
await ImportModule('dnd-5e')
|
|
||||||
|
|
||||||
DisplayToast('aqua', 'All plugins loaded successfully');
|
DisplayToast('aqua', 'All plugins loaded successfully');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { inject, onMounted, ref } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
import { GetEmitter } from '../../services/Dragonroll';
|
|
||||||
|
|
||||||
const props = defineProps(['data', 'click']);
|
const props = defineProps(['data', 'click']);
|
||||||
const data = props.data;
|
const data = props.data;
|
||||||
@ -13,8 +12,9 @@ function Select(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
console.log(data);
|
||||||
title.value = data.title;
|
title.value = data.title;
|
||||||
image.value.src = "modules/" + data.id + "/icon.png"
|
image.value.src = `plugins/${data.id}/${data.icon}`;
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -2,24 +2,20 @@
|
|||||||
// Entrypoint
|
// Entrypoint
|
||||||
function Main(Api){
|
function Main(Api){
|
||||||
console.log("Hello World!");
|
console.log("Hello World!");
|
||||||
console.log(Api);
|
|
||||||
|
|
||||||
Api.Modules.CreateModule({
|
let dndModule = Api.createModule('dnd-5e');
|
||||||
"id": "dnd-5e",
|
|
||||||
"title": "Dungeons & Dragons 5e",
|
|
||||||
"description": "Dungeons & Dragons Fifth edition game system support",
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Aran Roig"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"version": "0.1",
|
|
||||||
"color": "#e92026"
|
|
||||||
});
|
|
||||||
|
|
||||||
Api.Windows.InjectWindow('dnd-5e', 'character_sheet', 'CharacterSheet');
|
dndModule.title = "Dungeons & Dragons 5e";
|
||||||
Api.Windows.InjectWindow('dnd-5e', 'item_sheet', 'ItemSheet');
|
dndModule.description = "Dungeons & Dragons Fifth edition game system support";
|
||||||
Api.Windows.InjectWindow('dnd-5e', 'create_item_prompt', 'CreateItemPrompt');
|
dndModule.version = "0.1";
|
||||||
|
dndModule.color = "#e92026";
|
||||||
|
dndModule.icon = "icon.png"
|
||||||
|
|
||||||
|
Api.windows.registerWindow('character_sheet', Api.createView('CharacterSheet'));
|
||||||
|
Api.windows.registerWindow('item_sheet', Api.createView('ItemSheet'));
|
||||||
|
Api.windows.registerWindow('create_item_promptç', Api.createView('CreateItemPrompt'));
|
||||||
|
|
||||||
|
Api.registerModule(dndModule);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Main };
|
export { Main };
|
@ -12,6 +12,10 @@ function updateLogoThemes(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", (event) => {
|
document.addEventListener("DOMContentLoaded", (event) => {
|
||||||
|
let darkLogos = document.getElementsByClassName('logo-splash-dark');
|
||||||
|
let lightLogos = document.getElementsByClassName('logo-splash-light');
|
||||||
|
for(let i = 0; i < darkLogos.length; i++) darkLogos[i].style.display = "none";
|
||||||
|
for(let i = 0; i < lightLogos.length; i++) lightLogos[i].style.display = "none";
|
||||||
|
|
||||||
const attrObserver = new MutationObserver((mutations) => {
|
const attrObserver = new MutationObserver((mutations) => {
|
||||||
mutations.forEach(mu => {
|
mutations.forEach(mu => {
|
||||||
|
69
tutorials/firstplugin.md
Normal file
69
tutorials/firstplugin.md
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
This guide will help you through creating a plugin for Dragonroll
|
||||||
|
|
||||||
|
## Downloading the example plugin
|
||||||
|
|
||||||
|
The quickest way to start a plugin is starting from the example plugin template that you can find in [this]() repository. Every Dragonroll plugin has the following file structure:
|
||||||
|
|
||||||
|
```tree
|
||||||
|
/your-plugin/
|
||||||
|
├── plugin.json
|
||||||
|
├── client
|
||||||
|
│ └── main.js
|
||||||
|
│ └── ...
|
||||||
|
├── backend
|
||||||
|
│ └── main.js
|
||||||
|
│ └── ...
|
||||||
|
├── locales
|
||||||
|
│ └── en-US.json
|
||||||
|
│ └── ...
|
||||||
|
└── public
|
||||||
|
└── icon.png
|
||||||
|
└── ...
|
||||||
|
```
|
||||||
|
|
||||||
|
- The `plugin.json` contains basic information about your plugin, and also the entrypoints that Dragonroll will use to load and initialize the plugin
|
||||||
|
- The `client` folder contains all the code of your plugin that is relative to the client
|
||||||
|
- The `backend` folder contains all the code that is relative to the server
|
||||||
|
- The `locales` folder contains the translation files for your plugin
|
||||||
|
- The `public` folder contains all the media that will be publicly available for your plugin client
|
||||||
|
|
||||||
|
## The plugin.json file
|
||||||
|
|
||||||
|
Your `plugin.json` file defines important information about your plugin, like its name, package, authors, entrypoints, and other information
|
||||||
|
|
||||||
|
**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"
|
||||||
|
> }
|
||||||
|
> }
|
||||||
|
> ```
|
||||||
|
|
||||||
|
## 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 };
|
||||||
|
> ```
|
||||||
|
|
||||||
|
In the client entrypoint, the `Api` variable will be a `ClientApi` object. In the backend entrypoint, the `Api` will be instead a `BackendApi` object.
|
3
tutorials/howtoread.md
Normal file
3
tutorials/howtoread.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- The classes starting with the prefix `Client` are client specific
|
||||||
|
- The classes starting with the prefix `Backend` are backend specific
|
||||||
|
- All the other classes are accessible from both sides
|
@ -1 +0,0 @@
|
|||||||
This guide will help you through creating a plugin for Dragonroll
|
|
@ -1,5 +1,8 @@
|
|||||||
{
|
{
|
||||||
"plugin": {
|
"firstplugin": {
|
||||||
"title": "Creating a plugin"
|
"title": "Creating your first plugin"
|
||||||
|
},
|
||||||
|
"howtoread": {
|
||||||
|
"title": "How to read this documentation"
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user