EU-Utility/docs/NEXUS_USAGE_EXAMPLES.md

18 KiB

Nexus API Usage Examples for Plugin Developers

Practical examples for using the Entropia Nexus API in plugins


Table of Contents

  1. Basic Search Examples
  2. Entity Type-Specific Searches
  3. Item Details & Market Data
  4. Complete Plugin Examples
  5. Advanced Usage Patterns

Basic Search Examples

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

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

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

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

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

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

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

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

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

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

"""
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

"""
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

"""
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

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

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

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}


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