EU-Utility-V3/docs/PLUGIN_GUIDE.md

324 lines
7.0 KiB
Markdown

# Plugin Development Guide
Create plugins for EU-Utility V3.
---
## Quick Start
### 1. Create Plugin Structure
```
my-plugin/
plugin.json # Plugin manifest
index.ts # Main plugin code
README.md # Documentation
```
### 2. Write Manifest
```json
{
"manifest_version": "3.0",
"plugin": {
"id": "com.example.myplugin",
"name": "My Plugin",
"version": "1.0.0",
"author": "Your Name",
"description": "What your plugin does",
"category": "utility"
},
"permissions": [
"log_reader:read",
"overlay:create",
"data_store:write"
],
"ui": {
"has_overlay": true,
"has_settings": true,
"hotkey": "ctrl+shift+m"
}
}
```
### 3. Write Plugin Code
```typescript
import { BasePlugin, PluginContext } from 'eu-utility-plugin-sdk';
export default class MyPlugin extends BasePlugin {
id = 'com.example.myplugin';
name = 'My Plugin';
version = '1.0.0';
private context: PluginContext;
private lootCount = 0;
async initialize(context: PluginContext): Promise<boolean> {
this.context = context;
// Subscribe to events
await this.context.api.subscribeEvent('loot.received', (event) => {
this.onLoot(event);
});
return true;
}
async activate(): Promise<boolean> {
this.context.logger.info('My Plugin activated');
return true;
}
async deactivate(): Promise<void> {
this.context.logger.info('My Plugin deactivated');
}
private onLoot(event: any) {
this.lootCount++;
// Show notification
this.context.api.showNotification({
title: 'Loot Tracked',
body: `Total loots: ${this.lootCount}`
});
// Save data
this.context.api.savePluginData(
this.id,
'stats',
{ lootCount: this.lootCount }
);
}
getSettingsUI(): HTMLElement {
// Return settings UI element
const div = document.createElement('div');
div.innerHTML = `
<label>Enable Feature</label>
<input type="checkbox" id="feature-toggle" />
`;
return div;
}
}
```
---
## BasePlugin Class
```typescript
abstract class BasePlugin {
abstract id: string;
abstract name: string;
abstract version: string;
// Required methods
abstract initialize(context: PluginContext): Promise<boolean>;
abstract activate(): Promise<boolean>;
abstract deactivate(): Promise<void>;
// Optional methods
getOverlayUI?(): HTMLElement;
getSettingsUI?(): HTMLElement;
onHotkey?(hotkey: string): void;
}
```
---
## Permissions
Available permissions:
| Permission | Description |
|------------|-------------|
| `log_reader:read` | Read game logs |
| `overlay:create` | Create overlay widgets |
| `data_store:write` | Save plugin data |
| `data_store:read` | Read plugin data |
| `network:external` | Make HTTP requests |
| `ocr:read` | Use OCR service |
| `clipboard:read` | Read clipboard |
| `clipboard:write` | Write to clipboard |
| `notification:send` | Send notifications |
---
## Example: Loot Tracker
Complete example plugin:
```typescript
import { BasePlugin, PluginContext } from 'eu-utility-plugin-sdk';
export default class LootTracker extends BasePlugin {
id = 'eu.utility.loot-tracker';
name = 'Loot Tracker';
version = '2.0.0';
author = 'Aether';
description = 'Track hunting loot with ROI analysis';
category = 'tracking';
private context: PluginContext;
private sessionStart = Date.now();
private totalLoot = 0;
private mobCount = 0;
async initialize(context: PluginContext): Promise<boolean> {
this.context = context;
// Load saved data
const saved = await context.api.loadPluginData(this.id, 'session');
if (saved) {
this.totalLoot = saved.totalLoot || 0;
this.mobCount = saved.mobCount || 0;
}
// Subscribe to loot events
await context.api.subscribeEvent('loot.received', (e) => {
this.handleLoot(e.data);
});
return true;
}
async activate(): Promise<boolean> {
this.sessionStart = Date.now();
this.context.logger.info('Loot Tracker: Session started');
// Create overlay widget
await this.createWidget();
return true;
}
async deactivate(): Promise<void> {
// Save session data
await this.context.api.savePluginData(this.id, 'session', {
totalLoot: this.totalLoot,
mobCount: this.mobCount,
duration: Date.now() - this.sessionStart
});
}
private async handleLoot(data: LootData) {
this.totalLoot += data.totalTT;
this.mobCount++;
// Update widget
await this.updateWidget();
// Notify on big loot
if (data.totalTT > 50) {
await this.context.api.showNotification({
title: 'Big Loot!',
body: `${data.mobName}: ${data.totalTT.toFixed(2)} PED`,
sound: true
});
}
// Log to file
await this.logLoot(data);
}
private async createWidget() {
await this.context.widget.create({
id: 'loot-tracker-main',
title: 'Loot Tracker',
width: 280,
height: 150,
x: 50,
y: 50,
content: this.renderWidget()
});
}
private renderWidget(): string {
const elapsed = Math.floor((Date.now() - this.sessionStart) / 1000);
const hours = Math.floor(elapsed / 3600);
const mins = Math.floor((elapsed % 3600) / 60);
const secs = elapsed % 60;
return `
<div style="font-family: system-ui; color: #fff; padding: 12px;">
<div style="font-size: 14px; font-weight: 600; margin-bottom: 8px;">
Session: ${hours}:${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}
</div>
<div style="font-size: 24px; font-weight: 700; color: #10b981;">
${this.totalLoot.toFixed(2)} PED
</div>
<div style="font-size: 12px; color: #94a3b8; margin-top: 4px;">
${this.mobCount} mobs killed
</div>
</div>
`;
}
private async updateWidget() {
await this.context.widget.update('loot-tracker-main', {
content: this.renderWidget()
});
}
private async logLoot(data: LootData) {
const entry = {
timestamp: new Date().toISOString(),
mob: data.mobName,
tt: data.totalTT,
items: data.items.length
};
const logs = await this.context.api.loadPluginData(this.id, 'logs') || [];
logs.push(entry);
// Keep last 1000 entries
if (logs.length > 1000) logs.shift();
await this.context.api.savePluginData(this.id, 'logs', logs);
}
onHotkey(hotkey: string): void {
if (hotkey === 'ctrl+shift+l') {
this.context.api.showNotification({
title: 'Loot Stats',
body: `Total: ${this.totalLoot.toFixed(2)} PED in ${this.mobCount} kills`
});
}
}
}
interface LootData {
mobName: string;
totalTT: number;
items: any[];
}
```
---
## Building Plugins
```bash
# Install SDK
npm install eu-utility-plugin-sdk
# Build
npm run build
# Package
eu-util plugin package
```
---
## Publishing
1. Create release on Git
2. Tag with version
3. Attach plugin.zip
---
*Plugin Development Guide - EU-Utility V3*