Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
24 changes: 24 additions & 0 deletions .github/workflows/python-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# This workflow will install Python dependencies, run tests and lint with a single version of Python
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions

name: Python CI

on: [push, fork, pull_request]

jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- name: Set up uv
uses: astral-sh/setup-uv@v5
with:
python-version: "3.12"
- name: Install dependencies
run: uv sync
- name: Lint with ruff
run: uv run ruff check .
- name: Run tests
run: uv run pytest
29 changes: 0 additions & 29 deletions .github/workflows/pythonapp.yml

This file was deleted.

14 changes: 0 additions & 14 deletions .travis.yml

This file was deleted.

10 changes: 6 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ RUN apk --no-cache add git

WORKDIR /app

COPY requirements.txt start_server.py ./
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-dev --no-install-project

COPY server/ server/
COPY migrations/ migrations/
COPY storage/ storage/
COPY start_server.py ./

CMD python ./start_server.py
CMD ["uv", "run", "python", "./start_server.py"]
71 changes: 43 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,42 @@

KFO-Server is the official Python-based server for Attorney Online, forked from tsuserver3.

If you are looking to use KFO-Server to set up a server, see [Server setup](#server-setup) below.

## Development setup

To set up KFO-Server for development, follow these instructions.

First, install dependencies:

```bash
uv sync
```

Then you can run the server using uv:

```bash
uv run python start_server.py
```

### Run linter

```(bash)
uv run ruff check .
```

### Run tests

```(bash)
uv run tox
```

### Run formatter

```(bash)
uv run ruff format .
```

## Server setup

In order to set up the server, you must follow these instructions. This assumes you are familiar with using a terminal.
Expand All @@ -22,42 +58,21 @@ If you don't want to use Git, you can download the latest zip of KFO-Server [her

### Install dependencies

In order to install dependencies, you will need to open a terminal.

On Windows, you can do this by pressing Win+R, typing in `cmd`, and pressing Enter.
On Linux, you can do this by pressing Ctrl+Alt+T.

You should then navigate to the folder where the server is located.

Take note that depending on your operating system, the command for python may be python3 or python.
You should also verify the version by running `python --version` or `python3 --version`.

First, we need to create the virtual environment. This can be done by running the following command:
Install [uv](https://docs.astral.sh/uv/getting-started/installation/), then run:

```bash
python -m venv venv
uv sync
```

Then, we need to activate the virtual environment.
If you're on a unix system (bash or similar), you can run the following command:

```bash
./venv/bin/pip install -r requirements.txt
```

If you're on Windows (cmd), you may have to do this instead:

```batch
venv\Scripts\pip install -r requirements.txt
```
This will create a virtual environment and install all dependencies.

### Configure tsuserver
### Configure KFO-Server

* Copy `config_sample` to `config`
* Edit the values in the `.yaml` files to your liking.
* Be sure to check your YAML file for syntax errors. Use this website: <http://www.yamllint.com/>
* *Use spaces only; do not use tabs.*
* You don't need to copy characters into the `characters` folder *unless* you specifically chose to disable iniswapping in an area (in `areas.yaml`). In this case, all tsuserver needs to know is the `char.ini` of each character. It doesn't need sprites.
* You don't need to copy characters into the `characters` folder *unless* you specifically chose to disable iniswapping in an area (in `areas.yaml`). In this case, all KFO-Server needs to know is the `char.ini` of each character. It doesn't need sprites.

### Run

Expand All @@ -70,7 +85,7 @@ To stop the server, press Ctrl+C in the terminal.

You can also use docker to run KFO-server. First you need to install [Docker](https://get.docker.com/) and [Docker Compose](https://docs.docker.com/compose/install/).

Once you have everything configured, do `docker-compose up`. It will build the image and start tsuserver up for you. If you accidentally restart the server, the container will automatically start back up. If you're not understanding why it's starting, try starting it up manually:
Once you have everything configured, do `docker-compose up`. It will build the image and start KFO-Server up for you. If you accidentally restart the server, the container will automatically start back up. If you're not understanding why it's starting, try starting it up manually:

## Pro Tips

Expand All @@ -82,6 +97,6 @@ Once you have everything configured, do `docker-compose up`. It will build the i

## License

This server is licensed under the AGPLv3 license. In short, if you use a modified version of tsuserver3, you *must* distribute its source licensed under the AGPLv3 as well, and notify your users where the modified source may be found. The main difference between the AGPL and the GPL is that for the AGPL, network use counts as distribution. If you do not accept these terms, you should use [serverD](https://github.com/Attorney-Online-Engineering-Task-Force/serverD), which uses GPL rather than AGPL.
This server is licensed under the AGPLv3 license. In short, if you use a modified version of KFO-Server, you *must* distribute its source licensed under the AGPLv3 as well, and notify your users where the modified source may be found. The main difference between the AGPL and the GPL is that for the AGPL, network use counts as distribution. If you do not accept these terms, you should use [serverD](https://github.com/Attorney-Online-Engineering-Task-Force/serverD), which uses GPL rather than AGPL.

See the [LICENSE](LICENSE.md) file for more information.
4 changes: 2 additions & 2 deletions config_sample/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,14 @@ websocket_port: 50001

# Whether the server is open to secure websocket connections
use_securewebsockets: false
# Port that is advertised to the masterserver for WSS connections (KFO-Server does not accept SSL directly)
# Port advertised to the masterserver for WSS connections (KFO-Server does not accept SSL directly)
secure_websocket_port: 443

# WebAO Asset URL for hosting files. Leave blank to use vanilla
asset_url:

# Whether the server should be advertised on the server list.
use_masterserver: true
use_masterserver: false
# How the server should be listed on the server list.
masterserver_name: My First Server
masterserver_description: This is my flashy new server
Expand Down
5 changes: 2 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
version: "3.3"
services:
tsuserver:
kfo-server:
build: .
image: tsuserver
image: kfo-server
ports:
- 27016:27016
- 50001:50001
Expand Down
51 changes: 47 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,48 @@
[tool.black]
[project]
name = "kfo-server"
version = "0.1.0"
description = "KFO Attorney Online Server"
readme = "README.md"
requires-python = ">=3.11"
dependencies = [
"aiohttp>=3.13.2",
"arrow>=1.3.0",
"discord.py>=2.5.2",
"ruff",
"geoip2>=4.7.0",
"oyaml>=1.0",
"pystun3>=1.0.0",
"pytest",
"PyYAML>=6.0.1",
"requests>=2.31.0",
"timeparse-plus>=1.2.0",
"tox>=4",
"websockets>=12.0",
]

[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"

[tool.setuptools]
packages = ["server"]

[tool.ruff]
line-length = 120
target-version = ["py311"]
# You can add patterns here if you need to exclude generated files, etc.
# extend-exclude = []
target-version = "py311"
# Exclude utility scripts from linting
exclude = ["scripts/"]

[tool.ruff.format]
quote-style = "double"
indent-style = "space"
skip-magic-trailing-comma = false

[tool.ruff.lint]
# E741: Ambiguous variable name (e.g., 'l') - used intentionally in list comprehensions
ignore = ["E741"]

[tool.ruff.lint.per-file-ignores]
# E402: Module level import not at top of file - imports must come after __all__ definitions
# F403: Star imports - intentional for re-exporting command modules
"server/commands/__init__.py" = ["E402", "F403"]
24 changes: 0 additions & 24 deletions requirements.txt

This file was deleted.

22 changes: 4 additions & 18 deletions scripts/music2yaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
import os
import sys

from shutil import copy2

os.chdir(os.path.dirname(__file__))

arg = ""
Expand All @@ -24,9 +22,7 @@
" use_unique_folder: True #If true, this music will be contained entirely within its own folder e.g. base/music/<yaml name>/*.mp3\n"
)
if droppedFile:
input(
"Writing .ogg and .mp3 and categorizing them based on file argument to music.yaml. Press ENTER to begin."
)
input("Writing .ogg and .mp3 and categorizing them based on file argument to music.yaml. Press ENTER to begin.")
for line in droppedFile.readlines():
try:
line = line.rstrip()
Expand All @@ -42,18 +38,12 @@
# tag = TinyTag.get(line)
# duration = tag.duration
duration = -1
File.write(
' - name: "{}"\n'.format(current_category + "/" + line)
)
File.write(' - name: "{}"\n'.format(current_category + "/" + line))
File.write(" length: {}\n".format(duration))
print("Name: {} Length: {}".format(line, duration))
except:
Err.write("Error for {}\n".format(line))
input(
"Unable to process song: {}! Press ENTER to continue.".format(
line
)
)
input("Unable to process song: {}! Press ENTER to continue.".format(line))
except:
continue
else:
Expand Down Expand Up @@ -88,11 +78,7 @@
# tag = TinyTag.get(line)
# duration = tag.duration
duration = -1
File.write(
' - name: "{}"\n'.format(
current_category + "/" + song.name
)
)
File.write(' - name: "{}"\n'.format(current_category + "/" + song.name))
File.write(" length: {}\n".format(duration))
print("Name: {} Length: {}".format(song.name, duration))

Expand Down
Loading