Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/tests/protocols/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Protocols Tests
test_gamespy4/index
test_teamspeak3/index
test_won/index
test_toxikk/index
test_gamespy1/index
test_minecraft/index
test_raknet/index
Expand Down
7 changes: 7 additions & 0 deletions docs/tests/protocols/test_toxikk/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.. _test_toxikk:

test_toxikk
===========

.. toctree::
test_toxikk_status
242 changes: 242 additions & 0 deletions docs/tests/protocols/test_toxikk/test_toxikk_status.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
test_toxikk_status
==================

Here are the results for the test method.

.. code-block:: json

{
"name": "TOXIKK Server",
"map": "BL-Foundation",
"game_type": "cruzade.CRZBloodLust",
"num_players": 1,
"max_players": 8,
"password_protected": false,
"stats_enabled": true,
"lan_mode": true,
"players": [],
"raw": {
"hostaddress": "10.13.37.149",
"hostport": 7777,
"num_players": 1,
"max_players": 8,
"lan_mode": true,
"uses_stats": true,
"owner_id": "0110000101734c32",
"owner_name": "TOXIKK Server",
"localized_settings": [
{
"id": 32779,
"value_index": 8,
"advertisement_type": 1
},
{
"id": 0,
"value_index": 2,
"advertisement_type": 1
},
{
"id": 1,
"value_index": 0,
"advertisement_type": 1
},
{
"id": 6,
"value_index": 1,
"advertisement_type": 1
},
{
"id": 7,
"value_index": 0,
"advertisement_type": 1
},
{
"id": 8,
"value_index": 0,
"advertisement_type": 1
},
{
"id": 9,
"value_index": 0,
"advertisement_type": 1
},
{
"id": 10,
"value_index": 0,
"advertisement_type": 1
},
{
"id": 11,
"value_index": 0,
"advertisement_type": 1
},
{
"id": 12,
"value_index": 0,
"advertisement_type": 1
},
{
"id": 13,
"value_index": 0,
"advertisement_type": 1
},
{
"id": 14,
"value_index": 0,
"advertisement_type": 1
},
{
"id": 15,
"value_index": 1,
"advertisement_type": 1
},
{
"id": 16,
"value_index": 0,
"advertisement_type": 1
},
{
"id": 17,
"value_index": 0,
"advertisement_type": 1
},
{
"id": 18,
"value_index": 0,
"advertisement_type": 1
},
{
"id": 19,
"value_index": 0,
"advertisement_type": 1
}
],
"settings_properties": [
{
"id": 1073741825,
"data": "BL-Foundation",
"advertisement_type": 2
},
{
"id": 1073741826,
"data": "cruzade.CRZBloodLust",
"advertisement_type": 2
},
{
"id": 268435704,
"data": 20,
"advertisement_type": 1
},
{
"id": 268435705,
"data": 10,
"advertisement_type": 1
},
{
"id": 268435703,
"data": 7,
"advertisement_type": 1
},
{
"id": 1073741827,
"data": "MY SERVER",
"advertisement_type": 2
},
{
"id": 268435717,
"data": 0,
"advertisement_type": 1
},
{
"id": 1073741828,
"data": "INSTAGIB\u001cNO STEALTH\u001cSpawn Protection Time",
"advertisement_type": 2
},
{
"id": 268435706,
"data": 8,
"advertisement_type": 1
},
{
"id": 268435707,
"data": 0,
"advertisement_type": 0
},
{
"id": 268435708,
"data": 1,
"advertisement_type": 1
},
{
"id": 268435709,
"data": 12,
"advertisement_type": 1
},
{
"id": 1073741829,
"data": "76561197984599090",
"advertisement_type": 2
},
{
"id": 1073741830,
"data": "",
"advertisement_type": 2
},
{
"id": 1073741831,
"data": "",
"advertisement_type": 2
},
{
"id": 1073741832,
"data": "GAMIE ?",
"advertisement_type": 2
},
{
"id": 1073741833,
"data": "",
"advertisement_type": 2
},
{
"id": 1073741834,
"data": "",
"advertisement_type": 2
},
{
"id": 1073741837,
"data": "1.0000",
"advertisement_type": 2
},
{
"id": 1073741838,
"data": "1",
"advertisement_type": 2
},
{
"id": 1073741839,
"data": "1.2",
"advertisement_type": 2
},
{
"id": 1073741840,
"data": "DefaultGameList",
"advertisement_type": 2
}
],
"map": "BL-Foundation",
"gametype": "BloodLust",
"frag_limit": 20,
"time_limit": 10,
"numbots": 7,
"mutators": [
"Instagib",
"No Stealth",
"Spawn Protection Time"
],
"bot_skill": "Experienced",
"pure_server": 1,
"password": 0,
"vs_bots": "None",
"force_respawn": 0
}
}
1 change: 1 addition & 0 deletions opengsq/protocols/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from opengsq.protocols.scum import Scum
from opengsq.protocols.source import Source
from opengsq.protocols.teamspeak3 import TeamSpeak3
from opengsq.protocols.toxikk import Toxikk
from opengsq.protocols.udk import UDK
from opengsq.protocols.unreal2 import Unreal2
from opengsq.protocols.ut3 import UT3
Expand Down
82 changes: 82 additions & 0 deletions opengsq/protocols/toxikk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
from opengsq.protocols.udk import UDK
from opengsq.responses.toxikk.status import Status

class Toxikk(UDK):
GAMEMODE_NAMES = {
"cruzade.CRZBloodLust": "BloodLust",
"cruzade.CRZTeamGame": "Squad Assault",
"cruzade.CRZSquadSurvival": "Squad Survival",
"cruzade.CRZCellCapture": "Cell Capture",
"cruzade.CRZAreaDomination": "Area Domination",
"cruzade.CRZArchRivals": "Arch Rivals"
}

BOT_SKILL_NAMES = {
0: "Novice",
1: "Average",
2: "Experienced",
3: "Skilled",
4: "Adept",
5: "Masterful",
6: "Inhuman",
7: "Godlike"
}

VS_BOTS_NAMES = {
0: "None",
1: "1:1",
2: "3:2",
3: "2:1"
}

full_name = "Toxikk Protocol"

def __init__(self, host: str, port: int = 14001, timeout: float = 5.0):
super().__init__(host, port, timeout)
self.game_id = 0x4D5707DB
self.packet_version = 7

def _parse_response(self, buffer: bytes) -> dict:
base_response = super()._parse_response(buffer)
toxikk_properties = {}

for prop in base_response['raw']['settings_properties']:
prop_id = prop['id']
if prop_id == 1073741825: # Map
base_response['map'] = prop['data']
toxikk_properties['map'] = prop['data']
elif prop_id == 1073741826: # Game Type
base_response['game_type'] = prop['data']
toxikk_properties['gametype'] = self.GAMEMODE_NAMES.get(prop['data'], prop['data'])
elif prop_id == 268435704: # Frag Limit
toxikk_properties['frag_limit'] = prop['data']
elif prop_id == 268435705: # Time Limit
toxikk_properties['time_limit'] = prop['data']
elif prop_id == 268435703: # Number of Bots
toxikk_properties['numbots'] = prop['data']
elif prop_id == 1073741828: # Mutators
toxikk_properties['mutators'] = self._parse_mutators(prop['data'])

for setting in base_response['raw']['localized_settings']:
setting_id = setting['id']
value_index = setting['value_index']

if setting_id == 0:
toxikk_properties['bot_skill'] = self.BOT_SKILL_NAMES.get(value_index)
elif setting_id == 6:
toxikk_properties['pure_server'] = value_index
elif setting_id == 7:
base_response['password_protected'] = value_index == 1
toxikk_properties['password'] = value_index
elif setting_id == 8:
toxikk_properties['vs_bots'] = self.VS_BOTS_NAMES.get(value_index)
elif setting_id == 10:
toxikk_properties['force_respawn'] = value_index

base_response['raw'].update(toxikk_properties)
return base_response

def _parse_mutators(self, mutator_value: any) -> list:
if not mutator_value or not isinstance(mutator_value, str):
return []
return [m.title() for m in mutator_value.split('\x1c') if m]
1 change: 1 addition & 0 deletions opengsq/responses/toxikk/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .status import Status
9 changes: 9 additions & 0 deletions opengsq/responses/toxikk/status.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from __future__ import annotations
from dataclasses import dataclass, field
from typing import List
from opengsq.responses.udk.status import Status as UDKStatus

@dataclass
class Status(UDKStatus):
"""Toxikk-specific status response"""
mutators: List[str] = field(default_factory=list)
Loading