EU-Utility/docs/NEXUS_USAGE_EXAMPLES.md

649 lines
18 KiB
Markdown

# Nexus API Usage Examples for Plugin Developers
> Practical examples for using the Entropia Nexus API in plugins
---
## Table of Contents
1. [Basic Search Examples](#basic-search-examples)
2. [Entity Type-Specific Searches](#entity-type-specific-searches)
3. [Item Details & Market Data](#item-details--market-data)
4. [Complete Plugin Examples](#complete-plugin-examples)
5. [Advanced Usage Patterns](#advanced-usage-patterns)
---
## Basic Search Examples
### Simple Item Search
```python
from plugins.base_plugin import BasePlugin
class MyPlugin(BasePlugin):
def find_weapons(self):
# Search for items containing "ArMatrix"
results = self.nexus_search("ArMatrix", entity_type="items")
for item in results:
print(f"Found: {item['name']} ({item['type']})")
```
### Search with Limit
```python
def find_top_results(self, query):
# Get up to 50 results
results = self.nexus_search(
query,
entity_type="items",
limit=50
)
return results
```
---
## Entity Type-Specific Searches
### Weapons
```python
def find_laser_weapons(self):
"""Search for laser weapons."""
results = self.nexus_search("laser", entity_type="weapons")
weapons = []
for item in results:
details = self.nexus_get_item_details(item['id'])
if details:
weapons.append({
'name': details['name'],
'damage': details.get('damage', 0),
'range': details.get('range', 0),
'decay': details.get('decay', 0)
})
return weapons
```
### Mobs/Creatures
```python
def find_mobs_by_name(self, name):
"""Search for creatures."""
results = self.nexus_search(name, entity_type="mobs")
mobs = []
for mob in results:
mobs.append({
'name': mob['name'],
'id': mob['id'],
'hitpoints': mob['data'].get('hitpoints', 'Unknown'),
'threat': mob['data'].get('threat', 'Unknown')
})
return mobs
# Usage
drakabas = self.find_mobs_by_name("Drakaba")
atrox = self.find_mobs_by_name("Atrox")
```
### Blueprints
```python
def find_crafting_blueprints(self, material_name):
"""Find blueprints that use a specific material."""
results = self.nexus_search(material_name, entity_type="blueprints")
blueprints = []
for bp in results:
details = self.nexus_get_item_details(bp['id'])
if details and 'materials' in details:
blueprints.append({
'name': details['name'],
'materials': details['materials'],
'qr': details.get('qr', 1.0)
})
return blueprints
```
### Locations
```python
def find_teleporters(self, planet="Calypso"):
"""Find teleporters on a specific planet."""
results = self.nexus_search(planet, entity_type="teleporters")
teleporters = []
for tp in results:
data = tp['data']
teleporters.append({
'name': tp['name'],
'x': data.get('x'),
'y': data.get('y'),
'planet': data.get('planet', planet)
})
return teleporters
```
### Skills
```python
def find_combat_skills(self):
"""Search for combat-related skills."""
results = self.nexus_search("", entity_type="skills")
combat_skills = [
s for s in results
if 'combat' in s.get('category', '').lower()
]
return combat_skills
```
---
## Item Details & Market Data
### Get Full Item Information
```python
def analyze_item(self, item_id):
"""Get complete item analysis."""
# Get basic details
details = self.nexus_get_item_details(item_id)
if not details:
return None
# Get market data
market = self.nexus_get_market_data(item_id)
analysis = {
'name': details['name'],
'category': details.get('category', 'Unknown'),
'tt_value': details.get('tt_value', 0),
'weight': details.get('weight', 0),
'decay': details.get('decay', 0),
}
# Add weapon stats if applicable
if 'damage' in details:
analysis['weapon_stats'] = {
'damage': details['damage'],
'range': details.get('range', 0),
'accuracy': details.get('accuracy', 0),
'ammo': details.get('ammo_consumption', 0)
}
# Add market info
if market:
analysis['market'] = {
'markup': market.get('current_markup', 0),
'volume_24h': market.get('volume_24h', 0),
'buy_orders': len(market.get('buy_orders', [])),
'sell_orders': len(market.get('sell_orders', []))
}
return analysis
```
### Market Price Monitoring
```python
def check_price_drops(self, watchlist):
"""Monitor items for price drops.
Args:
watchlist: List of {'item_id': str, 'max_price': float}
"""
deals = []
for watch in watchlist:
market = self.nexus_get_market_data(watch['item_id'])
if not market:
continue
current_price = market.get('current_markup', 0)
if current_price <= watch['max_price']:
deals.append({
'item_id': watch['item_id'],
'item_name': market.get('item_name', 'Unknown'),
'current_price': current_price,
'target_price': watch['max_price'],
'savings': watch['max_price'] - current_price
})
return deals
```
### Compare Item Stats
```python
def compare_weapons(self, weapon_ids):
"""Compare multiple weapons side by side."""
weapons = []
for wid in weapon_ids:
details = self.nexus_get_item_details(wid)
if details:
dpp = self.calculate_dpp(
details.get('damage', 0),
details.get('ammo_consumption', 0),
details.get('decay', 0)
)
weapons.append({
'name': details['name'],
'damage': details.get('damage', 0),
'range': details.get('range', 0),
'decay': details.get('decay', 0),
'dpp': dpp,
'tt': details.get('tt_value', 0)
})
# Sort by DPP (damage per pec)
return sorted(weapons, key=lambda w: w['dpp'], reverse=True)
```
---
## Complete Plugin Examples
### Weapon Comparison Plugin
```python
"""
Weapon Comparison Plugin
Compares weapons by DPP (Damage Per PEC) and other stats.
"""
from PyQt6.QtWidgets import (
QWidget, QVBoxLayout, QHBoxLayout,
QPushButton, QLineEdit, QTableWidget,
QTableWidgetItem, QLabel
)
from plugins.base_plugin import BasePlugin
class WeaponComparatorPlugin(BasePlugin):
name = "Weapon Comparator"
version = "1.0.0"
author = "EU-Utility"
description = "Compare weapons by DPP and stats"
hotkey = "ctrl+shift+w"
def initialize(self):
self.weapon_ids = []
def get_ui(self):
widget = QWidget()
layout = QVBoxLayout(widget)
# Search box
search_layout = QHBoxLayout()
self.search_input = QLineEdit()
self.search_input.setPlaceholderText("Search weapons...")
search_layout.addWidget(self.search_input)
add_btn = QPushButton("Add to Compare")
add_btn.clicked.connect(self.add_weapon)
search_layout.addWidget(add_btn)
layout.addLayout(search_layout)
# Results table
self.table = QTableWidget()
self.table.setColumnCount(6)
self.table.setHorizontalHeaderLabels([
"Name", "Damage", "Range", "Decay", "DPP", "TT Value"
])
layout.addWidget(self.table)
# Compare button
compare_btn = QPushButton("Compare")
compare_btn.clicked.connect(self.do_compare)
layout.addWidget(compare_btn)
return widget
def add_weapon(self):
query = self.search_input.text()
results = self.nexus_search(query, entity_type="weapons", limit=5)
if results:
# Add first result
self.weapon_ids.append(results[0]['id'])
self.search_input.clear()
self.search_input.setPlaceholderText(
f"Added {results[0]['name']} ({len(self.weapon_ids)} total)"
)
def do_compare(self):
if len(self.weapon_ids) < 2:
return
# Fetch and compare
weapons = []
for wid in self.weapon_ids:
details = self.nexus_get_item_details(wid)
if details:
dpp = self.calculate_dpp(
details.get('damage', 0),
details.get('ammo_consumption', 0),
details.get('decay', 0)
)
weapons.append({
'name': details['name'],
'damage': details.get('damage', 0),
'range': details.get('range', 0),
'decay': details.get('decay', 0),
'dpp': dpp,
'tt': details.get('tt_value', 0)
})
# Sort by DPP
weapons.sort(key=lambda w: w['dpp'], reverse=True)
# Display
self.table.setRowCount(len(weapons))
for i, w in enumerate(weapons):
self.table.setItem(i, 0, QTableWidgetItem(w['name']))
self.table.setItem(i, 1, QTableWidgetItem(f"{w['damage']:.1f}"))
self.table.setItem(i, 2, QTableWidgetItem(f"{w['range']:.0f}m"))
self.table.setItem(i, 3, QTableWidgetItem(f"{w['decay']:.2f}"))
self.table.setItem(i, 4, QTableWidgetItem(f"{w['dpp']:.2f}"))
self.table.setItem(i, 5, QTableWidgetItem(f"{w['tt']:.2f} PED"))
```
### Mob Info Plugin
```python
"""
Mob Information Plugin
Quick lookup for creature stats and locations.
"""
from PyQt6.QtWidgets import (
QWidget, QVBoxLayout, QHBoxLayout,
QLineEdit, QPushButton, QLabel
)
from plugins.base_plugin import BasePlugin
class MobInfoPlugin(BasePlugin):
name = "Mob Info"
version = "1.0.0"
author = "EU-Utility"
description = "Quick mob stats lookup"
hotkey = "ctrl+shift+m"
def get_ui(self):
widget = QWidget()
layout = QVBoxLayout(widget)
# Search
search_layout = QHBoxLayout()
self.search_input = QLineEdit()
self.search_input.setPlaceholderText("Enter mob name...")
self.search_input.returnPressed.connect(self.search_mob)
search_layout.addWidget(self.search_input)
search_btn = QPushButton("Search")
search_btn.clicked.connect(self.search_mob)
search_layout.addWidget(search_btn)
layout.addLayout(search_layout)
# Results
self.name_label = QLabel("Name: ")
self.hp_label = QLabel("HP: ")
self.damage_label = QLabel("Damage: ")
self.threat_label = QLabel("Threat: ")
self.planet_label = QLabel("Planet: ")
layout.addWidget(self.name_label)
layout.addWidget(self.hp_label)
layout.addWidget(self.damage_label)
layout.addWidget(self.threat_label)
layout.addWidget(self.planet_label)
layout.addStretch()
return widget
def search_mob(self):
query = self.search_input.text()
if not query:
return
results = self.nexus_search(query, entity_type="mobs", limit=1)
if not results:
self.name_label.setText("Mob not found")
return
mob = results[0]
data = mob.get('data', {})
self.name_label.setText(f"Name: {mob['name']}")
self.hp_label.setText(f"HP: {data.get('hitpoints', 'Unknown')}")
self.damage_label.setText(f"Damage: {data.get('damage', 'Unknown')}")
self.threat_label.setText(f"Threat: {data.get('threat', 'Unknown')}")
self.planet_label.setText(f"Planet: {data.get('planet', 'Unknown')}")
```
### Price Checker Plugin
```python
"""
Price Checker Plugin
Quick market price lookup for items.
"""
from PyQt6.QtWidgets import (
QWidget, QVBoxLayout, QHBoxLayout,
QLineEdit, QPushButton, QLabel, QFrame
)
from PyQt6.QtCore import Qt
from plugins.base_plugin import BasePlugin
class PriceCheckerPlugin(BasePlugin):
name = "Price Checker"
version = "1.0.0"
author = "EU-Utility"
description = "Quick market price lookup"
hotkey = "ctrl+shift+p"
def get_ui(self):
widget = QWidget()
layout = QVBoxLayout(widget)
# Search
search_layout = QHBoxLayout()
self.search_input = QLineEdit()
self.search_input.setPlaceholderText("Enter item name...")
self.search_input.returnPressed.connect(self.check_price)
search_layout.addWidget(self.search_input)
check_btn = QPushButton("Check Price")
check_btn.clicked.connect(self.check_price)
search_layout.addWidget(check_btn)
layout.addLayout(search_layout)
# Results frame
self.results_frame = QFrame()
results_layout = QVBoxLayout(self.results_frame)
self.item_name = QLabel("Item: ")
self.item_name.setStyleSheet("font-size: 14px; font-weight: bold;")
results_layout.addWidget(self.item_name)
self.markup_label = QLabel("Current Markup: ")
results_layout.addWidget(self.markup_label)
self.volume_label = QLabel("24h Volume: ")
results_layout.addWidget(self.volume_label)
self.range_label = QLabel("Price Range: ")
results_layout.addWidget(self.range_label)
layout.addWidget(self.results_frame)
layout.addStretch()
return widget
def check_price(self):
query = self.search_input.text()
if not query:
return
# Search for item
results = self.nexus_search(query, entity_type="items", limit=1)
if not results:
self.item_name.setText("Item not found")
return
item = results[0]
self.item_name.setText(f"Item: {item['name']}")
# Get market data
market = self.nexus_get_market_data(item['id'])
if not market:
self.markup_label.setText("No market data available")
return
markup = market.get('current_markup', 0)
avg_7d = market.get('avg_markup_7d', 0)
volume = market.get('volume_24h', 0)
self.markup_label.setText(f"Current Markup: {markup:.1f}%")
self.volume_label.setText(f"24h Volume: {volume}")
# Calculate range from orders
buy_orders = market.get('buy_orders', [])
sell_orders = market.get('sell_orders', [])
if buy_orders and sell_orders:
highest_buy = max(o['price'] for o in buy_orders)
lowest_sell = min(o['price'] for o in sell_orders)
self.range_label.setText(
f"Price Range: {highest_buy:.2f} - {lowest_sell:.2f} PED"
)
```
---
## Advanced Usage Patterns
### Caching Results
```python
class CachedSearchPlugin(BasePlugin):
def initialize(self):
self._cache = {}
self._cache_ttl = 300 # 5 minutes
def cached_search(self, query, entity_type="items"):
"""Search with local caching."""
cache_key = f"{entity_type}:{query}"
now = time.time()
# Check cache
if cache_key in self._cache:
result, timestamp = self._cache[cache_key]
if now - timestamp < self._cache_ttl:
return result
# Fetch fresh
results = self.nexus_search(query, entity_type)
self._cache[cache_key] = (results, now)
return results
```
### Batch Processing
```python
def analyze_multiple_items(self, item_names):
"""Process multiple items efficiently."""
analyses = []
for name in item_names:
# Search
results = self.nexus_search(name, entity_type="items", limit=1)
if not results:
continue
# Get details
details = self.nexus_get_item_details(results[0]['id'])
if not details:
continue
# Get market
market = self.nexus_get_market_data(results[0]['id'])
analyses.append({
'search_name': name,
'found_name': details['name'],
'tt_value': details.get('tt_value', 0),
'markup': market.get('current_markup', 0) if market else 0
})
return analyses
```
### Error Handling
```python
def safe_search(self, query, entity_type="items"):
"""Search with error handling."""
try:
if not self.nexus_is_available():
print("Nexus API not available")
return []
results = self.nexus_search(query, entity_type)
return results
except Exception as e:
print(f"Search error: {e}")
return []
def safe_get_details(self, item_id):
"""Get details with fallback."""
try:
details = self.nexus_get_item_details(item_id)
return details or {'name': 'Unknown', 'id': item_id}
except Exception as e:
print(f"Details error: {e}")
return {'name': 'Error', 'id': item_id}
```
---
## Related Documentation
- [NEXUS_API_REFERENCE.md](./NEXUS_API_REFERENCE.md) - Complete API documentation
- [NEXUS_LINKTREE.md](./NEXUS_LINKTREE.md) - URL and endpoint reference
- [Plugin Base Class](../plugins/base_plugin.py) - Available plugin methods
---
## Tips & Best Practices
1. **Always check for None**: `nexus_get_item_details()` and `nexus_get_market_data()` can return None
2. **Use try/except**: Wrap API calls to handle network errors gracefully
3. **Cache results**: For frequently accessed data, implement local caching
4. **Respect rate limits**: Don't make too many requests in rapid succession
5. **Check availability**: Use `nexus_is_available()` before making calls
6. **Handle both field formats**: API returns both `name` and `Name` - check both