Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2.0.0b5 #351

Open
wants to merge 46 commits into
base: main
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
d982127
beta5, players prop, demoparser upgrade
pnxenopoulos Sep 16, 2024
a7b724f
new lockfile
pnxenopoulos Sep 16, 2024
8968b04
ruff parse demo
pnxenopoulos Sep 16, 2024
2abd918
velocity as a default prop
pnxenopoulos Sep 16, 2024
aea1034
update demoparser2
pnxenopoulos Nov 24, 2024
09ad0d9
add 3.13 to build matrix
pnxenopoulos Nov 24, 2024
455cb42
poetry lock updated
pnxenopoulos Nov 24, 2024
5e4bd63
approve 3.13 in pyproject, change ruff lint settings
pnxenopoulos Nov 24, 2024
a2b280d
redo the pyproject.toml
pnxenopoulos Nov 25, 2024
926613e
Nav mesh parsing (#358)
pnxenopoulos Jan 5, 2025
13227b4
add requests
pnxenopoulos Jan 5, 2025
332a725
fix test
pnxenopoulos Jan 5, 2025
efbbcb4
under 3.13
pnxenopoulos Jan 5, 2025
9036754
nav command
pnxenopoulos Jan 6, 2025
1d62689
fix naming
pnxenopoulos Jan 6, 2025
0b311b6
fix nav test
pnxenopoulos Jan 6, 2025
92abe5c
i can see clearly now
pnxenopoulos Jan 6, 2025
113ea77
vis tests
pnxenopoulos Jan 6, 2025
96afbb7
fix code
pnxenopoulos Jan 6, 2025
7a8cf22
increase capacity
pnxenopoulos Jan 6, 2025
0d3cbce
faster read
pnxenopoulos Jan 6, 2025
e4aba32
fix tests
pnxenopoulos Jan 6, 2025
77b73bc
maybe 3.13
pnxenopoulos Jan 7, 2025
4ada526
remove 3.13 support
pnxenopoulos Jan 7, 2025
6d3a6e0
Fixed plot bugs, added functionality, updated images (#353)
ventsiR Jan 8, 2025
b5a4292
test 3.13
pnxenopoulos Jan 9, 2025
1d04f38
uv
pnxenopoulos Jan 9, 2025
337cfd4
precommit
pnxenopoulos Jan 9, 2025
42874f7
fix the readme
pnxenopoulos Jan 9, 2025
5ecdce0
ignore long line
pnxenopoulos Jan 9, 2025
2562da4
fix
pnxenopoulos Jan 9, 2025
6801a6b
Add extraction of spawn points. (#359)
JanEricNitschke Jan 13, 2025
1d594ea
small changes
pnxenopoulos Jan 13, 2025
1d8ca33
fix spacing
pnxenopoulos Jan 13, 2025
153a29e
log into steam
pnxenopoulos Jan 13, 2025
97a6fa3
source artifacts
pnxenopoulos Jan 13, 2025
fcdf8eb
one liner
pnxenopoulos Jan 13, 2025
7eb44c3
bash
pnxenopoulos Jan 13, 2025
9371cf1
pc
pnxenopoulos Jan 14, 2025
917964f
make run
pnxenopoulos Jan 14, 2025
0ed193e
move awpy install
pnxenopoulos Jan 14, 2025
a98f2d7
fix space
pnxenopoulos Jan 14, 2025
0dc08ee
new scripts
pnxenopoulos Jan 14, 2025
28c4d45
cleaning up
pnxenopoulos Jan 14, 2025
8417b6c
updated import
pnxenopoulos Jan 14, 2025
18b118f
scripts
pnxenopoulos Jan 14, 2025
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
Prev Previous commit
Next Next commit
nav command
  • Loading branch information
pnxenopoulos committed Jan 6, 2025
commit 903675404dbd9ad90265e95a069ca2aa10311cb8
3 changes: 2 additions & 1 deletion awpy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Provides data parsing, analytics and visualization capabilities for CSGO data."""

from awpy.demo import Demo
from awpy.nav import Nav

__version__ = "2.0.0b5"
__all__ = ["Demo"]
__all__ = ["Demo", "Nav"]
14 changes: 12 additions & 2 deletions awpy/cli.py
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@
from loguru import logger
from tqdm import tqdm

from awpy import Demo
from awpy import Demo, Nav
from awpy.data import AWPY_DATA_DIR
from awpy.data.usd_data import USD_LINKS

@@ -96,7 +96,7 @@ def get(
@click.option(
"--other-props", multiple=True, help="List of other properties to include."
)
def parse(
def parse_demo(
demo: Path,
*,
outpath: Optional[Path] = None,
@@ -117,3 +117,13 @@ def parse(
other_props=other_props[0].split(",") if other_props else None,
)
demo.compress(outpath=outpath)


@awpy.command(help="Parse a Counter-Strike 2 nav file.")
@click.argument("demo", type=click.Path(exists=True))
def parse_nav(nav_file: Path) -> None:
"""Parse a nav file given its path."""
nav_file = Path(nav_file)
nav_mesh = Nav(path=nav_file)
nav_mesh.to_json(path=nav_file.with_suffix(".json"))
logger.success(f"Nav mesh saved to {nav_file.with_suffix('.json')}\n{nav_mesh}")
54 changes: 44 additions & 10 deletions awpy/nav.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Module to parse and represent navigation mesh files."""

import json
import struct
from dataclasses import dataclass
from enum import Enum
@@ -92,6 +93,12 @@ def __init__(self) -> None:
self.ladders_above: list[int] = []
self.ladders_below: list[int] = []

def __repr__(self) -> str:
"""Returns string representation of NavArea."""
connected_ids = sorted({c.area_id for conns in self.connections for c in conns})
points = [(c.x, c.y, c.z) for c in self.corners]
return f"NavArea(id={self.area_id}, connected_ids={connected_ids}, points={points})" # noqa: E501

@staticmethod
def read_connections(br: BinaryIO) -> list[NavMeshConnection]:
"""Reads a list of connections from a binary stream.
@@ -159,11 +166,19 @@ def read(
ladder_id = struct.unpack("I", br.read(4))[0]
self.ladders_below.append(ladder_id)

def __repr__(self) -> str:
"""Returns string representation of NavArea."""
connected_ids = sorted({c.area_id for conns in self.connections for c in conns})
points = [(c.x, c.y, c.z) for c in self.corners]
return f"NavArea(id={self.area_id}, connected_ids={connected_ids}, points={points})" # noqa: E501
def to_dict(self) -> dict:
"""Converts the navigation area to a dictionary."""
return {
"area_id": self.area_id,
"hull_index": self.hull_index,
"dynamic_attribute_flags": int(self.dynamic_attribute_flags),
"corners": [{"x": c.x, "y": c.y, "z": c.z} for c in self.corners],
"connections": [
conn.area_id for conns in self.connections for conn in conns
],
"ladders_above": self.ladders_above,
"ladders_below": self.ladders_below,
}


class Nav:
@@ -195,6 +210,12 @@ def __init__(self, path: str | Path) -> None:
self.is_analyzed: bool = False
self.read(path)

def __repr__(self) -> str:
"""Returns string representation of Nav."""
return (
f"Nav(version={self.version}.{self.sub_version}, areas={len(self.areas)})"
)

def read(self, path: str | Path) -> None:
"""Reads nav mesh data from a file.

@@ -295,8 +316,21 @@ def _read_areas(
area.read(br, self, polygons)
self.areas[area.area_id] = area

def __repr__(self) -> str:
"""Returns string representation of Nav."""
return (
f"Nav(version={self.version}.{self.sub_version}, areas={len(self.areas)})"
)
def to_dict(self) -> dict:
"""Converts the entire navigation mesh to a dictionary."""
return {
"version": self.version,
"sub_version": self.sub_version,
"is_analyzed": self.is_analyzed,
"areas": {area_id: area.to_dict() for area_id, area in self.areas.items()},
}

def to_json(self, path: str | Path) -> None:
"""Writes the navigation mesh data to a JSON file.

Args:
path: Path to the JSON file to write.
"""
nav_dict = self.to_dict()
with open(path, "w", encoding="utf-8") as json_file:
json.dump(nav_dict, json_file)
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
@@ -77,6 +77,7 @@ You can take a look at the :doc:`examples/parse_demo` to see how to parse a demo
cli
data
demo
nav
plot
stats
vis
12 changes: 12 additions & 0 deletions docs/nav.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Nav
====================

This module contains the base Nav class.

awpy.nav
------------------------------

.. automodule:: awpy.nav
:members:
:undoc-members:
:show-inheritance:
24 changes: 19 additions & 5 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@
import pytest
from click.testing import CliRunner

from awpy.cli import parse
from awpy.cli import parse_demo, parse_nav


class TestCommandLine:
@@ -19,15 +19,29 @@ def setup_runner(self, setup): # noqa: ANN001, ARG002
"""Setup CLI runner. `setup` arg is the pytest setup fixture."""
self.runner = CliRunner()

def test_parse_invalid_filepath(self):
def test_parse_nav_invalid_filepath(self):
"""Test the nav command with an invalid filepath."""
result = self.runner.invoke(parse_nav, ["xyz.nav"])
assert result.exit_code != 0
assert isinstance(result.exception, SystemExit)

def test_parse_nav(self):
"""Test that the nav command produces a json file."""
result = self.runner.invoke(parse_nav, ["tests/de_dust2.nav"])
assert result.exit_code == 0

zip_name = "de_dust2.json"
assert os.path.exists(zip_name)

def test_parse_demo_invalid_filepath(self):
"""Test the parse command with an invalid filepath."""
result = self.runner.invoke(parse, ["xyz.dem"])
result = self.runner.invoke(parse_demo, ["xyz.dem"])
assert result.exit_code != 0
assert isinstance(result.exception, SystemExit)

def test_parse_zip_creation(self):
def test_parse_demo_zip_creation(self):
"""Test that the parse command produces a zip file."""
result = self.runner.invoke(parse, ["tests/spirit-vs-mouz-m1-vertigo.dem"])
result = self.runner.invoke(parse_demo, ["tests/spirit-vs-mouz-m1-vertigo.dem"])
assert result.exit_code == 0

zip_name = "spirit-vs-mouz-m1-vertigo.zip"
Loading
Loading