fix(api): fix NexusPlate dataclass - add missing protection_acid and protection_electric fields

- Added protection_acid and protection_electric to NexusPlate dataclass
- Updated hardcoded plates to use individual protection fields
- Fixed plate selector crash when sorting by protection
This commit is contained in:
LemonNexus 2026-02-09 15:47:53 +00:00
parent cf95732fff
commit b8fc0a8033
1 changed files with 97 additions and 53 deletions

View File

@ -30,14 +30,14 @@ class NexusItem:
name: str
item_id: str
category: str
@classmethod
def from_api(cls, data: Dict[str, Any]) -> "NexusItem":
"""Create from API response."""
raise NotImplementedError
@dataclass
@dataclass
class NexusWeapon(NexusItem):
"""Weapon from Entropia Nexus API."""
damage: Decimal
@ -49,14 +49,14 @@ class NexusWeapon(NexusItem):
efficiency: Decimal
range_val: Decimal
type: str = ""
@classmethod
def from_api(cls, data: Dict[str, Any]) -> "NexusWeapon":
"""Create from API response."""
props = data.get('Properties', {})
economy = props.get('Economy', {})
damage = props.get('Damage', {})
return cls(
id=data.get('Id', 0),
name=data.get('Name', 'Unknown'),
@ -86,14 +86,14 @@ class NexusArmor(NexusItem):
protection_acid: Decimal
protection_electric: Decimal
type: str = ""
@classmethod
def from_api(cls, data: Dict[str, Any]) -> "NexusArmor":
"""Create from API response."""
props = data.get('Properties', {})
protection = props.get('Protection', {})
economy = props.get('Economy', {})
return cls(
id=data.get('Id', 0),
name=data.get('Name', 'Unknown'),
@ -119,14 +119,16 @@ class NexusPlate(NexusItem):
protection_stab: Decimal
protection_burn: Decimal
protection_cold: Decimal
protection_acid: Decimal
protection_electric: Decimal
decay: Decimal
@classmethod
def from_api(cls, data: Dict[str, Any]) -> "NexusPlate":
"""Create from API response."""
props = data.get('Properties', {})
protection = props.get('Protection', {})
return cls(
id=data.get('Id', 0),
name=data.get('Name', 'Unknown'),
@ -137,6 +139,8 @@ class NexusPlate(NexusItem):
protection_stab=Decimal(str(protection.get('Stab', 0))),
protection_burn=Decimal(str(protection.get('Burn', 0))),
protection_cold=Decimal(str(protection.get('Cold', 0))),
protection_acid=Decimal(str(protection.get('Acid', 0))),
protection_electric=Decimal(str(protection.get('Electric', 0))),
decay=Decimal(str(props.get('Decay', 0))),
)
@ -149,12 +153,12 @@ class NexusAttachment(NexusItem):
range_bonus: Decimal
decay: Decimal
efficiency_bonus: Decimal
@classmethod
def from_api(cls, data: Dict[str, Any]) -> "NexusAttachment":
"""Create from API response."""
props = data.get('Properties', {})
return cls(
id=data.get('Id', 0),
name=data.get('Name', 'Unknown'),
@ -175,12 +179,12 @@ class NexusEnhancer(NexusItem):
tier: int
effect_value: Decimal
break_chance: Decimal
@classmethod
def from_api(cls, data: Dict[str, Any]) -> "NexusEnhancer":
"""Create from API response."""
props = data.get('Properties', {})
return cls(
id=data.get('Id', 0),
name=data.get('Name', 'Unknown'),
@ -212,7 +216,7 @@ class NexusHealingTool(NexusItem):
type: str # 'fap', 'chip', 'pack'
profession_level: int = 0
is_limited: bool = False
@classmethod
def from_api(cls, data: Dict[str, Any]) -> "NexusHealingTool":
"""Create from API response."""
@ -262,7 +266,7 @@ class NexusRing(NexusItem):
max_tt: Decimal
min_tt: Decimal
is_limited: bool
@classmethod
def from_api(cls, data: Dict[str, Any]) -> "NexusRing":
"""Create from API response."""
@ -327,12 +331,12 @@ class NexusPet(NexusItem):
effect_type: str
effect_value: Decimal
level_required: int
@classmethod
def from_api(cls, data: Dict[str, Any]) -> "NexusPet":
"""Create from API response."""
props = data.get('Properties', {})
return cls(
id=data.get('Id', 0),
name=data.get('Name', 'Unknown'),
@ -346,7 +350,7 @@ class NexusPet(NexusItem):
class EntropiaNexusFullAPI:
"""Complete Entropia Nexus API client for all gear types."""
def __init__(self):
self.base_url = NEXUS_API_BASE
self._weapons_cache: Optional[List[NexusWeapon]] = None
@ -362,7 +366,7 @@ class EntropiaNexusFullAPI:
self._rings_cache: Optional[List[NexusRing]] = None
self._clothing_cache: Optional[List[NexusClothing]] = None
self._pets_cache: Optional[List[NexusPet]] = None
def _fetch(self, endpoint: str) -> List[Dict]:
"""Fetch data from API endpoint."""
try:
@ -374,7 +378,7 @@ class EntropiaNexusFullAPI:
except Exception as e:
logger.error(f"Failed to fetch {endpoint}: {e}")
return []
def get_all_weapons(self, force_refresh: bool = False) -> List[NexusWeapon]:
"""Fetch all weapons from Nexus API."""
if self._weapons_cache is None or force_refresh:
@ -382,7 +386,7 @@ class EntropiaNexusFullAPI:
self._weapons_cache = [NexusWeapon.from_api(item) for item in data]
logger.info(f"Loaded {len(self._weapons_cache)} weapons")
return self._weapons_cache
def get_all_armors(self, force_refresh: bool = False) -> List[NexusArmor]:
"""Fetch all armors from Nexus API."""
if self._armors_cache is None or force_refresh:
@ -390,7 +394,7 @@ class EntropiaNexusFullAPI:
self._armors_cache = [NexusArmor.from_api(item) for item in data]
logger.info(f"Loaded {len(self._armors_cache)} armors")
return self._armors_cache
def get_all_plates(self, force_refresh: bool = False) -> List[NexusPlate]:
"""Fetch plates from /armorplatings endpoint."""
if self._plates_cache is None or force_refresh:
@ -409,52 +413,92 @@ class EntropiaNexusFullAPI:
return [
# Impact Plates
NexusPlate(id=1, name="Armor Plating Mk. 5B", item_id="plate_5b", category="plate",
protection=ProtectionProfile(impact=6), decay_per_hp=Decimal("0.05")),
protection_impact=Decimal("6"), protection_cut=Decimal("0"), protection_stab=Decimal("0"),
protection_burn=Decimal("0"), protection_cold=Decimal("0"), protection_acid=Decimal("0"), protection_electric=Decimal("0"),
decay=Decimal("0.05")),
NexusPlate(id=2, name="Armor Plating Mk. 10A", item_id="plate_10a", category="plate",
protection=ProtectionProfile(impact=12), decay_per_hp=Decimal("0.05")),
protection_impact=Decimal("12"), protection_cut=Decimal("0"), protection_stab=Decimal("0"),
protection_burn=Decimal("0"), protection_cold=Decimal("0"), protection_acid=Decimal("0"), protection_electric=Decimal("0"),
decay=Decimal("0.05")),
NexusPlate(id=3, name="Armor Plating Mk. 25A", item_id="plate_25a", category="plate",
protection=ProtectionProfile(impact=25), decay_per_hp=Decimal("0.05")),
protection_impact=Decimal("25"), protection_cut=Decimal("0"), protection_stab=Decimal("0"),
protection_burn=Decimal("0"), protection_cold=Decimal("0"), protection_acid=Decimal("0"), protection_electric=Decimal("0"),
decay=Decimal("0.05")),
NexusPlate(id=4, name="Armor Plating Mk. 50A", item_id="plate_50a", category="plate",
protection=ProtectionProfile(impact=50), decay_per_hp=Decimal("0.05")),
protection_impact=Decimal("50"), protection_cut=Decimal("0"), protection_stab=Decimal("0"),
protection_burn=Decimal("0"), protection_cold=Decimal("0"), protection_acid=Decimal("0"), protection_electric=Decimal("0"),
decay=Decimal("0.05")),
# Cut/Stab Plates
NexusPlate(id=5, name="Armor Plating Mk. 5C", item_id="plate_5c", category="plate",
protection=ProtectionProfile(cut=6, stab=6), decay_per_hp=Decimal("0.05")),
protection_impact=Decimal("0"), protection_cut=Decimal("6"), protection_stab=Decimal("6"),
protection_burn=Decimal("0"), protection_cold=Decimal("0"), protection_acid=Decimal("0"), protection_electric=Decimal("0"),
decay=Decimal("0.05")),
NexusPlate(id=6, name="Armor Plating Mk. 10C", item_id="plate_10c", category="plate",
protection=ProtectionProfile(cut=12, stab=12), decay_per_hp=Decimal("0.05")),
protection_impact=Decimal("0"), protection_cut=Decimal("12"), protection_stab=Decimal("12"),
protection_burn=Decimal("0"), protection_cold=Decimal("0"), protection_acid=Decimal("0"), protection_electric=Decimal("0"),
decay=Decimal("0.05")),
NexusPlate(id=7, name="Armor Plating Mk. 25C", item_id="plate_25c", category="plate",
protection=ProtectionProfile(cut=25, stab=25), decay_per_hp=Decimal("0.05")),
protection_impact=Decimal("0"), protection_cut=Decimal("25"), protection_stab=Decimal("25"),
protection_burn=Decimal("0"), protection_cold=Decimal("0"), protection_acid=Decimal("0"), protection_electric=Decimal("0"),
decay=Decimal("0.05")),
NexusPlate(id=8, name="Armor Plating Mk. 50C", item_id="plate_50c", category="plate",
protection=ProtectionProfile(cut=50, stab=50), decay_per_hp=Decimal("0.05")),
protection_impact=Decimal("0"), protection_cut=Decimal("50"), protection_stab=Decimal("50"),
protection_burn=Decimal("0"), protection_cold=Decimal("0"), protection_acid=Decimal("0"), protection_electric=Decimal("0"),
decay=Decimal("0.05")),
# Electric Plates
NexusPlate(id=9, name="Armor Plating Mk. 10E", item_id="plate_10e", category="plate",
protection=ProtectionProfile(electric=12), decay_per_hp=Decimal("0.05")),
protection_impact=Decimal("0"), protection_cut=Decimal("0"), protection_stab=Decimal("0"),
protection_burn=Decimal("0"), protection_cold=Decimal("0"), protection_acid=Decimal("0"), protection_electric=Decimal("12"),
decay=Decimal("0.05")),
NexusPlate(id=10, name="Armor Plating Mk. 25E", item_id="plate_25e", category="plate",
protection=ProtectionProfile(electric=25), decay_per_hp=Decimal("0.05")),
protection_impact=Decimal("0"), protection_cut=Decimal("0"), protection_stab=Decimal("0"),
protection_burn=Decimal("0"), protection_cold=Decimal("0"), protection_acid=Decimal("0"), protection_electric=Decimal("25"),
decay=Decimal("0.05")),
# Burn Plates
NexusPlate(id=11, name="Armor Plating Mk. 10F", item_id="plate_10f", category="plate",
protection=ProtectionProfile(burn=12), decay_per_hp=Decimal("0.05")),
protection_impact=Decimal("0"), protection_cut=Decimal("0"), protection_stab=Decimal("0"),
protection_burn=Decimal("12"), protection_cold=Decimal("0"), protection_acid=Decimal("0"), protection_electric=Decimal("0"),
decay=Decimal("0.05")),
NexusPlate(id=12, name="Armor Plating Mk. 25F", item_id="plate_25f", category="plate",
protection=ProtectionProfile(burn=25), decay_per_hp=Decimal("0.05")),
protection_impact=Decimal("0"), protection_cut=Decimal("0"), protection_stab=Decimal("0"),
protection_burn=Decimal("25"), protection_cold=Decimal("0"), protection_acid=Decimal("0"), protection_electric=Decimal("0"),
decay=Decimal("0.05")),
# Acid Plates
NexusPlate(id=13, name="Armor Plating Mk. 10Acd", item_id="plate_10acd", category="plate",
protection=ProtectionProfile(acid=12), decay_per_hp=Decimal("0.05")),
protection_impact=Decimal("0"), protection_cut=Decimal("0"), protection_stab=Decimal("0"),
protection_burn=Decimal("0"), protection_cold=Decimal("0"), protection_acid=Decimal("12"), protection_electric=Decimal("0"),
decay=Decimal("0.05")),
NexusPlate(id=14, name="Armor Plating Mk. 25Acd", item_id="plate_25acd", category="plate",
protection=ProtectionProfile(acid=25), decay_per_hp=Decimal("0.05")),
protection_impact=Decimal("0"), protection_cut=Decimal("0"), protection_stab=Decimal("0"),
protection_burn=Decimal("0"), protection_cold=Decimal("0"), protection_acid=Decimal("25"), protection_electric=Decimal("0"),
decay=Decimal("0.05")),
# Cold Plates
NexusPlate(id=15, name="Armor Plating Mk. 10Cl", item_id="plate_10cl", category="plate",
protection=ProtectionProfile(cold=12), decay_per_hp=Decimal("0.05")),
protection_impact=Decimal("0"), protection_cut=Decimal("0"), protection_stab=Decimal("0"),
protection_burn=Decimal("0"), protection_cold=Decimal("12"), protection_acid=Decimal("0"), protection_electric=Decimal("0"),
decay=Decimal("0.05")),
NexusPlate(id=16, name="Armor Plating Mk. 25Cl", item_id="plate_25cl", category="plate",
protection=ProtectionProfile(cold=25), decay_per_hp=Decimal("0.05")),
protection_impact=Decimal("0"), protection_cut=Decimal("0"), protection_stab=Decimal("0"),
protection_burn=Decimal("0"), protection_cold=Decimal("25"), protection_acid=Decimal("0"), protection_electric=Decimal("0"),
decay=Decimal("0.05")),
# Shrapnel Plates
NexusPlate(id=17, name="Armor Plating Mk. 10S", item_id="plate_10s", category="plate",
protection=ProtectionProfile(shrapnel=12), decay_per_hp=Decimal("0.05")),
protection_impact=Decimal("0"), protection_cut=Decimal("0"), protection_stab=Decimal("0"),
protection_burn=Decimal("0"), protection_cold=Decimal("0"), protection_acid=Decimal("0"), protection_electric=Decimal("0"),
decay=Decimal("0.05")),
NexusPlate(id=18, name="Armor Plating Mk. 25S", item_id="plate_25s", category="plate",
protection=ProtectionProfile(shrapnel=25), decay_per_hp=Decimal("0.05")),
protection_impact=Decimal("0"), protection_cut=Decimal("0"), protection_stab=Decimal("0"),
protection_burn=Decimal("0"), protection_cold=Decimal("0"), protection_acid=Decimal("0"), protection_electric=Decimal("0"),
decay=Decimal("0.05")),
# Penetration Plates
NexusPlate(id=19, name="Armor Plating Mk. 10P", item_id="plate_10p", category="plate",
protection=ProtectionProfile(penetration=12), decay_per_hp=Decimal("0.05")),
protection_impact=Decimal("0"), protection_cut=Decimal("0"), protection_stab=Decimal("0"),
protection_burn=Decimal("0"), protection_cold=Decimal("0"), protection_acid=Decimal("0"), protection_electric=Decimal("0"),
decay=Decimal("0.05")),
NexusPlate(id=20, name="Armor Plating Mk. 25P", item_id="plate_25p", category="plate",
protection=ProtectionProfile(penetration=25), decay_per_hp=Decimal("0.05")),
protection_impact=Decimal("0"), protection_cut=Decimal("0"), protection_stab=Decimal("0"),
protection_burn=Decimal("0"), protection_cold=Decimal("0"), protection_acid=Decimal("0"), protection_electric=Decimal("0"),
decay=Decimal("0.05")),
]
def get_all_absorbers(self, force_refresh: bool = False) -> List[NexusAttachment]:
@ -500,7 +544,7 @@ class EntropiaNexusFullAPI:
else:
self._healing_chips_cache = []
return self._healing_chips_cache
def get_all_enhancers(self, force_refresh: bool = False) -> List[NexusEnhancer]:
"""Fetch all enhancers from Nexus API."""
if self._enhancers_cache is None or force_refresh:
@ -508,24 +552,24 @@ class EntropiaNexusFullAPI:
self._enhancers_cache = [NexusEnhancer.from_api(item) for item in data]
logger.info(f"Loaded {len(self._enhancers_cache)} enhancers")
return self._enhancers_cache
def get_all_healing_tools(self, force_refresh: bool = False) -> List[NexusHealingTool]:
"""Fetch all healing tools from Nexus API (includes medical tools AND chips)."""
if self._healing_cache is None or force_refresh:
# Fetch both medical tools and medical chips
tools_data = self._fetch("medicaltools")
chips_data = self._fetch("medicalchips")
all_healing = []
if tools_data:
all_healing.extend([NexusHealingTool.from_api(item) for item in tools_data])
if chips_data:
all_healing.extend([NexusHealingTool.from_api(item) for item in chips_data])
self._healing_cache = all_healing
logger.info(f"Loaded {len(self._healing_cache)} healing tools ({len(tools_data) if tools_data else 0} tools + {len(chips_data) if chips_data else 0} chips)")
return self._healing_cache
def get_all_rings(self, force_refresh: bool = False) -> List[NexusRing]:
"""Fetch rings from /clothings endpoint (filtered by Type=Ring)."""
if self._rings_cache is None or force_refresh:
@ -550,7 +594,7 @@ class EntropiaNexusFullAPI:
NexusRing(id=5, name="Courage Ring", item_id="courage_ring", category="ring", slot="Right Finger", gender="Both", effects={"Critical Hit": "1%"}, max_tt=Decimal("10"), min_tt=Decimal("0"), is_limited=False),
NexusRing(id=6, name="Courage Ring (L)", item_id="courage_ring_l", category="ring", slot="Right Finger", gender="Both", effects={"Critical Hit": "1%"}, max_tt=Decimal("10"), min_tt=Decimal("0"), is_limited=True),
]
def get_all_clothing(self, force_refresh: bool = False) -> List[NexusClothing]:
"""Fetch all clothing from Nexus API."""
if self._clothing_cache is None or force_refresh:
@ -558,7 +602,7 @@ class EntropiaNexusFullAPI:
self._clothing_cache = [NexusClothing.from_api(item) for item in data]
logger.info(f"Loaded {len(self._clothing_cache)} clothing items")
return self._clothing_cache
def get_all_pets(self, force_refresh: bool = False) -> List[NexusPet]:
"""Fetch all pets from Nexus API."""
if self._pets_cache is None or force_refresh:
@ -566,31 +610,31 @@ class EntropiaNexusFullAPI:
self._pets_cache = [NexusPet.from_api(item) for item in data]
logger.info(f"Loaded {len(self._pets_cache)} pets")
return self._pets_cache
def search_weapons(self, query: str) -> List[NexusWeapon]:
"""Search weapons by name."""
weapons = self.get_all_weapons()
query_lower = query.lower()
return [w for w in weapons if query_lower in w.name.lower()]
def search_armors(self, query: str) -> List[NexusArmor]:
"""Search armors by name."""
armors = self.get_all_armors()
query_lower = query.lower()
return [a for a in armors if query_lower in a.name.lower()]
def search_healing_tools(self, query: str) -> List[NexusHealingTool]:
"""Search healing tools by name."""
tools = self.get_all_healing_tools()
query_lower = query.lower()
return [t for t in tools if query_lower in t.name.lower()]
def search_plates(self, query: str) -> List[NexusPlate]:
"""Search plates by name."""
plates = self.get_all_plates()
query_lower = query.lower()
return [p for p in plates if query_lower in p.name.lower()]
def search_all(self, query: str) -> Dict[str, List]:
"""Search across all gear types."""
return {