-
Notifications
You must be signed in to change notification settings - Fork 18
Mario Kart 8 implementation #248
base: main
Are you sure you want to change the base?
Changes from all commits
4748bd0
74588b1
88674c3
2588cca
ee96248
b197c26
061e773
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| PN_MK8_AUTHENTICATION_SERVER_PORT=5781 | ||
| PN_MK8_SECURE_SERVER_PORT=5782 | ||
| PN_MK8_FRIENDS_GRPC_HOST=friends | ||
| PN_MK8_FRIENDS_GRPC_PORT=5001 | ||
| PN_MK8_ACCOUNT_GRPC_HOST=account | ||
| PN_MK8_ACCOUNT_GRPC_PORT=5000 | ||
| PN_MK8_GRPC_PORT=5780 | ||
| PN_MK8_ACCOUNT_DATABASE=pretendo_account | ||
| PN_MK8_MONGO_HOST=mongodb | ||
| PN_MK8_MONGO_PORT=27017 | ||
| PN_MK8_CONFIG_S3_ENDPOINT=minio.pretendo.cc | ||
| PN_MK8_CONFIG_S3_ACCESS_KEY=minio_pretendo | ||
| PN_MK8_CONFIG_S3_BUCKET=amkj | ||
| PN_MK8_REDIS_URI=redis:6379 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| diff --git a/requirements.txt b/requirements.txt | ||
| new file mode 100644 | ||
| index 0000000..d873a47 | ||
| --- /dev/null | ||
| +++ b/requirements.txt | ||
| @@ -0,0 +1,7 @@ | ||
| +aioconsole | ||
| +requests | ||
| +pymongo | ||
| +redis | ||
| +grpcio-tools | ||
| +minio | ||
| +nintendoclients | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like the CI on ARM failed while installing the dependencies here, while x64 succeeded. I'm seeing |
||
| \ No newline at end of file | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,104 @@ | ||
| diff --git a/server_config.py b/server_config.py | ||
| new file mode 100644 | ||
| index 0000000..dcb8279 | ||
| --- /dev/null | ||
| +++ b/server_config.py | ||
| @@ -0,0 +1,98 @@ | ||
| +from nintendo.nex import settings | ||
| +import pymongo | ||
| +import pymongo | ||
| +import urllib.parse | ||
| +import os | ||
| + | ||
| +GAME_SERVER_ID = 0x1010EB00 | ||
| +ACCESS_KEY = "25dbf96a" | ||
| +NEX_VERSION = 30504 | ||
| + | ||
| +# NEX_SETTINGS = settings.load("friends") | ||
| +NEX_SETTINGS = settings.default() | ||
| +NEX_SETTINGS.configure(ACCESS_KEY, NEX_VERSION) | ||
| +NEX_SETTINGS["prudp.resend_timeout"] = 1.5 | ||
| +NEX_SETTINGS["prudp.resend_limit"] = 3 | ||
| +NEX_SETTINGS["prudp.version"] = 1 | ||
| +NEX_SETTINGS["prudp.max_substream_id"] = 1 | ||
| + | ||
| + | ||
| +class MongoCredentials: | ||
| + def __init__(self, host: str, port: int, use_auth: bool = False, username: str = "", password: str = ""): | ||
| + self.host = host | ||
| + self.port = port | ||
| + self.use_auth = use_auth | ||
| + self.username = username | ||
| + self.password = password | ||
| + | ||
| + def connect(self): | ||
| + # Username and password must be percent-escaped | ||
| + db_use_auth = self.use_auth | ||
| + db_user = urllib.parse.quote_plus(self.username) | ||
| + db_pass = urllib.parse.quote_plus(self.password) | ||
| + db_host = self.host | ||
| + db_port = self.port | ||
| + | ||
| + if db_use_auth: | ||
| + db_uri = 'mongodb://%s:%s@%s:%d' % (db_user, db_pass, db_host, db_port) | ||
| + else: | ||
| + db_uri = 'mongodb://%s:%d' % (db_host, db_port) | ||
| + | ||
| + return pymongo.MongoClient(db_uri, serverSelectionTimeoutMS=3000) | ||
| + | ||
| + | ||
| +class NEXConfig: | ||
| + def __init__(self): | ||
| + self.nex_host = "0.0.0.0" | ||
| + self.nex_auth_port = int(os.getenv('PN_MK8_AUTHENTICATION_SERVER_PORT', 1000)) | ||
| + self.nex_secure_port = int(os.getenv('PN_MK8_SECURE_SERVER_PORT', 1001)) | ||
| + self.nex_secure_user_password = os.getenv('PN_MK8_SECURE_PASSWORD', 'abcdef123456') # PLEASE, make this a real private password. | ||
| + self.nex_external_address = os.getenv('PN_MK8_SECURE_SERVER_HOST', '0.0.0.0') # Your external IP, for external clients to connect. | ||
| + | ||
| + self.friends_grpc_host = os.getenv('PN_MK8_FRIENDS_GRPC_HOST', '123.123.123.123') | ||
| + self.friends_grpc_port = int(os.getenv('PN_MK8_FRIENDS_GRPC_PORT', 1002)) | ||
| + self.friends_grpc_api_key = os.getenv('PN_MK8_FRIENDS_GRPC_API_KEY', 'abcdefghijklmnopqrstuvwxyz123456789') | ||
| + | ||
| + self.account_grpc_host = os.getenv('PN_MK8_ACCOUNT_GRPC_HOST', '124.124.124.124') | ||
| + self.account_grpc_port = int(os.getenv('PN_MK8_ACCOUNT_GRPC_PORT', 1003)) | ||
| + self.account_grpc_api_key = os.getenv('PN_MK8_ACCOUNT_GRPC_API_KEY', 'abcdefghijklmnopqrstuvwxyz123456789') | ||
| + | ||
| + # These gRPC credentials are for the server we're implementing | ||
| + self.mario_kart_8_grpc_host = "localhost" | ||
| + self.mario_kart_8_grpc_port = int(os.getenv('PN_MK8_GRPC_PORT', 50051)) | ||
| + self.mario_kart_8_grpc_api_key = os.getenv('PN_MK8_GRPC_API_KEY', 'abcdefghijklmnopqrstuvwxyz123456789') | ||
| + | ||
| + self.account_database = os.getenv('PN_MK8_ACCOUNT_DATABASE', 'pretendo_account') | ||
| + | ||
| + self.pnid_collection = "pnids" | ||
| + self.nex_account_collection = "nexaccounts" | ||
| + | ||
| + self.game_db_server = MongoCredentials( | ||
| + host=os.getenv('PN_MK8_MONGO_HOST', '222.222.222.222'), | ||
| + port=int(os.getenv('PN_MK8_MONGO_PORT', 1004)) | ||
| + ) | ||
| + | ||
| + self.game_database = "mk8" | ||
| + | ||
| + self.sequence_collection = "counters" | ||
| + self.gatherings_collection = "gatherings" | ||
| + self.sessions_collection = "sessions" | ||
| + self.tournaments_collection = "tournaments" | ||
| + self.tournaments_score_collection = "tournaments_scores" | ||
| + self.ranking_common_data_collection = "commondata" | ||
| + self.rankings_score_collection = "rankings" | ||
| + self.secure_reports_collection = "secure_reports" | ||
| + self.datastore_collection = "datastore" | ||
| + self.restriction_collection = "restrictions" | ||
| + | ||
| + self.s3_endpoint_domain = os.getenv('PN_MK8_CONFIG_S3_ENDPOINT', 'minio.pretendo.cc') | ||
| + self.s3_endpoint = "http://" + self.s3_endpoint_domain | ||
| + self.s3_access_key = os.getenv('PN_MK8_CONFIG_S3_ACCESS_KEY', 'minio_pretendo') | ||
| + self.s3_secret = os.getenv('PN_MK8_CONFIG_S3_SECRET', '...') | ||
| + self.s3_region = "it" | ||
| + self.bucket_name = os.getenv('PN_MK8_CONFIG_S3_BUCKET', 'amkj') | ||
| + | ||
| + self.redis_uri = "redis://" + os.getenv('PN_MK8_REDIS_URI', '53.53.53.53:1005') # redis://HOST[:PORT][?db=DATABASE[&password=PASSWORD]] | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks great! Nice way to grab the server configuration from Docker environment variables even though the original server doesn't support it. I'm not sure that it makes sense to provide default values to |
||
| + | ||
| + | ||
| +NEX_CONFIG = NEXConfig() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| diff --git a/main.py b/main-diff.py | ||
| index 9fb8233..b9fa3a7 100644 | ||
| --- a/main.py | ||
| +++ b/main.py | ||
| @@ -8,6 +8,7 @@ import aioconsole | ||
| import contextlib | ||
| import datetime | ||
| import requests | ||
| +import signal | ||
|
|
||
| from datetime import datetime, timezone | ||
|
|
||
| @@ -246,7 +247,17 @@ async def main(): | ||
| logging.info("Starting gRPC amkj server on %s", listen_addr) | ||
|
|
||
| await server.start() | ||
| - await aioconsole.ainput("Press enter to exit...\n") | ||
| + | ||
| + # Set signal handlers for graceful shutdown | ||
| + loop = asyncio.get_running_loop() | ||
| + for sig in (signal.SIGINT, signal.SIGTERM): | ||
| + loop.add_signal_handler(sig, lambda: asyncio.create_task(shutdown(server))) | ||
| + | ||
| + # Keep server running | ||
| + try: | ||
| + await server.wait_for_termination() | ||
| + except asyncio.CancelledError: | ||
| + pass | ||
|
|
||
|
|
||
| async def sync_amkj_status_to_database(task: asyncio.Task): |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| diff --git a/Dockerfile b/Dockerfile | ||
| new file mode 100644 | ||
| index 0000000..9fb5b2d | ||
| --- /dev/null | ||
| +++ b/Dockerfile | ||
| @@ -0,0 +1,22 @@ | ||
| +# Use the official Python image as the base | ||
| +FROM python:3.9-slim | ||
| + | ||
| +# Set the working directory inside the container | ||
| +WORKDIR /app | ||
| + | ||
| +# Copy the requirements file to the working directory | ||
| +COPY requirements.txt . | ||
| + | ||
| +ENV PYTHONPATH="/usr/local/lib/python3.9/site-packages" | ||
| + | ||
| +# Install dependencies specified in requirements.txt | ||
| +RUN python -m pip install --no-cache-dir -r requirements.txt | ||
| + | ||
| +# Copy all project files into the container | ||
| +COPY . . | ||
| + | ||
| +# Generate gRPC Python files before running the application | ||
| +RUN python -m grpc_tools.protoc --proto_path=grpc --python_out=. --grpc_python_out=. grpc/amkj_service.proto | ||
| + | ||
| +# Set the command to run the application | ||
| +CMD ["python", "main.py"] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,14 +8,14 @@ use this if you're trying to update the submodules to a newer version than is su | |
| fails to apply, a 3-way merge will be attempted." | ||
| parse_arguments "$@" | ||
|
|
||
| print_info "Resetting all submodules..." | ||
| run_verbose git submodule sync | ||
| run_verbose git submodule foreach "git reset --hard" | ||
| run_verbose git submodule foreach "git clean -fd" | ||
| run_verbose git submodule update --init --checkout | ||
| print_info "Resetting all submodules (including nested submodules)..." | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A bit nitpicky but I don't feel like adding this to the info text is necessary. (same for below) |
||
| run_verbose git submodule sync --recursive | ||
| run_verbose git submodule foreach --recursive "git reset --hard" | ||
| run_verbose git submodule foreach --recursive "git clean -xfd" | ||
| run_verbose git submodule update --init --checkout --recursive | ||
| if [[ -n "$update_remote" ]]; then | ||
| print_info "Updating submodules from their remotes..." | ||
| git submodule update --remote | ||
| print_info "Updating submodules from their remotes (including nested submodules)..." | ||
| run_verbose git submodule update --remote --recursive | ||
| fi | ||
|
|
||
| print_info "Applying patches to submodules..." | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just as a consistency thing here: tabs can be removed, explicit branch and
ignore = dirtycan be added.