Skip to content
Draft
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
4 changes: 2 additions & 2 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ handbook
sql
tools

# Created by the db when using docker-compose, large and causes rebuild issues if sent to the context.
docker-db-data
# Database backups
database/backups
86 changes: 71 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,74 @@ The project follows the [semantic versioning](https://semver.org/) scheme using
* *General changes or improvements* are treated as MINOR: 1.__2__.3 -> 1.__3.0__
* *Major changes* are treated as MAJOR: __1__.2.3 -> __2.0.0__

## Getting started
Follow along as I go through the steps to play the game on your local computer from start to finish. I won't go into extreme detail, so if you don't have prior experience with Java or git, you might struggle.
## Quick start

### Prerequisite

1. [Docker](https://www.docker.com)
2. [Docker Compose](https://docs.docker.com/compose/install)

### Start services

To start all services, run:

```bash
docker compose up -d
```

It starts the following services:

* **maplestory**: The main part of Cosmic server.
* **db**: The database for Cosmic server.
* **db-backup**: Database backup service.
* Performs an initial database backup on startup, followed by hourly backups.
* Backups older than 7 days are removed automatically.
* You can find the backups in [database/backups](./database/backup).

Then you can use

```bash
docker compose logs -f maplestory
```

to check the logs of Cosmic server.

Once the server is ready, you will see a message like:

```log
07:24:20.269 [main] INFO server.Server - Cosmic is now online after 14547 ms.
```

### Stop services

```bash
docker compose down
```

### Restore database

To restore the database using a backup, run:

```bash
./tools/restore_db <path_to_backup>
```

### Rebuild

You must rebuild images after any code changes:

```bash
docker compose build
```

## Local setup
You can also run Cosmic on your actual machine.

We will set up the following:
- Database - the database is used by the server to store game data such as accounts, characters and inventory items.
- Server - the server is the "brain" and routes network traffic between the clients.
- Client - the client is the application used to _play the game_, i.e. MapleStory.exe.

### 1 - Database
### 1 - Database
You will start by installing the database server and database client. Then you will connect to the server with the client to create a new database schema.

#### Steps
Expand Down Expand Up @@ -88,11 +147,6 @@ You will start by cloning the repository, then configure the database properties

Below, I list other ways of running the server which are completely optional.

#### Docker
Support for Docker is also provided out of the box, as an alternative to running straight in the IDE. If you have [Docker Desktop](https://www.docker.com/products/docker-desktop/) installed it's as easy as running `docker compose up`.

Making changes becomes a bit more tedious though as you have to rebuild the server image via `docker compose up --build`.

#### Jar
Another option is to start the server from a terminal by running a jar file. You first need to build the jar file from source which requires [Maven](https://maven.apache.org/). Fortunately, [Maven Wrapper](https://maven.apache.org/wrapper/) is provided so you don't have to install Maven separately.

Expand All @@ -102,15 +156,17 @@ To run the jar, a ``launch.bat`` file is provided for convenience. Simply double

Alternatively, run the jar file from the terminal. Just remember to provide the `wz-path` system property pointing to your wz directory.

### 3 - Client
The client files are located in a separate repository: https://github.com/P0nk/Cosmic-client
## Client
Client is the application used to _play the game_, i.e. MapleStory.exe.

The files are located in a separate repository: https://github.com/P0nk/Cosmic-client

Follow the installation guide in the README.

### 4 - Getting into the game
You have successfully started the client, and you're looking at the login screen.
## Getting into the game
You have successfully started the client, and you're looking at the login screen.

#### Logging in
### Logging in
At this point, you can log in to the admin account using the following credentials:
* Username: "admin"
* Password: "admin"
Expand All @@ -119,7 +175,7 @@ At this point, you can log in to the admin account using the following credentia

You can also create a new regular account by typing in your desired username & password and attempting to log in. This "automatic registration" feature lets you create new accounts to play around with. It is enabled by default (see _config.yaml_).

#### Entering the game
### Entering the game
Create a new character as you normally would, and then select it to enter the game. Hooray, finally we're in!

If you log in to the "Admin" character, you'll notice that the character looks almost invisible. This is hide mode, which is enabled by default when you log in to a GM character. You won't be visible to normal players and no mobs will move if you're alone on the map. Toggle hide mode on or off by typing "@hide" in the in-game chat.
Expand Down
2 changes: 2 additions & 0 deletions database/backups/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*
!.gitignore
3 changes: 0 additions & 3 deletions database/docker-db-data/.gitignore

This file was deleted.

34 changes: 30 additions & 4 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
version: '3'
services:
maplestory:
build: .
depends_on:
- db
db:
condition: service_healthy
ports:
# Login server
- "8484:8484"
Expand All @@ -19,7 +19,7 @@ services:
- ./wz:/opt/server/wz
environment:
DB_HOST: "db" ## Remember if this is present it will OVERRIDE the host in the config.yaml, if you put here anything other than db, you'll need to change the config.yaml jdbc string to port 3307, and not port 3306

db:
image: mysql:8.4.0
environment:
Expand All @@ -29,4 +29,30 @@ services:
ports:
- "3307:3306"
volumes:
- ./database/docker-db-data:/var/lib/mysql
- db-data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping"]
timeout: 5s
interval: 5s
retries: 3

db-backup:
image: percona/percona-xtrabackup:8.4
init: true
depends_on:
db:
condition: service_healthy
volumes:
- ./docker/db-backup/scripts:/scripts
- db-data:/var/lib/mysql:ro
- ./database/backups:/backup
user: root
environment:
DB_HOST: db
DB_USER: root
DB_PASSWORD:
command:
- /scripts/auto_backup

volumes:
db-data:
21 changes: 21 additions & 0 deletions docker/db-backup/scripts/auto_backup
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/bin/bash

while true; do
echo "$(date +'%F %T.%3N') Starting backup process..."

xtrabackup --backup --compress --compress-threads=4 \
--host="${DB_HOST}" --user="${DB_USER}" --password="${DB_PASSWORD}" \
--target-dir="/backup/$(date +%Y%m%d%H%M)"

if [[ $? == 0 ]]; then
echo "$(date +'%F %T.%3N') Backup completed successfully."

echo "$(date +'%F %T.%3N') Removing backups older than 7 days..."
find "/backup" -maxdepth 1 -type d -mtime +7 -exec rm -rf {} +
else
echo "$(date +'%F %T.%3N') ERROR: Backup failed! Cleanup is skipped." >&2
fi

echo "$(date +'%F %T.%3N') Sleeping for 1 hour..."
sleep 1h
done
52 changes: 52 additions & 0 deletions docker/db-backup/scripts/restore
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/bin/bash

readonly TARGET_DIR="/tmp/db_backup"
readonly DATA_DIR="/var/lib/mysql"

validate_args() {
if [[ -z "$1" ]]; then
echo "Usage: $0 <path_to_backup>"
exit 1
fi
}

assert_dir() {
if [[ ! -d "$1" ]]; then
echo "Error: Directory '$1' does not exist."
exit 1
fi
}

main() {
set -e

validate_args "$@"

backup_dir="$1"
assert_dir "${backup_dir}"

echo "Restoring database using ${backup_dir}..."

echo "Removing existing database data..."
rm -rf ${DATA_DIR}/*

# The backup might become unusable if the preparation is interrupted.
# So we use a copy instead of original backup to recover the database.
cp -R ${backup_dir} ${TARGET_DIR}

echo "Decompressing the backup..."
xtrabackup --decompress --target-dir="${TARGET_DIR}"

echo "Preparing the backup..."
xtrabackup --prepare --target-dir="${TARGET_DIR}"

echo "Moving files..."
xtrabackup --move-back --target-dir="${TARGET_DIR}" --datadir="${DATA_DIR}"

echo "Changing the ownership of database files..."
chown -R mysql:mysql ${DATA_DIR}

echo "Restoration completed successfully."
}

main "$@"
22 changes: 22 additions & 0 deletions tools/restore_db
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/bash

set -e

if [[ -z "$1" ]]; then
echo "Usage: $0 <path_to_backup>"
exit 1
fi

read -p "This will stop all services and overwrite the current database. \
Continue? (y/n) " -n 1 -r
echo
if [[ ! "$REPLY" == "y" ]]; then
echo "Restoration is cancelled."
exit 1
fi

echo "Stopping all services..."
docker compose down

docker compose run --no-deps -it --rm -v db-data:/var/lib/mysql \
-v $(realpath $1):/to_restore db-backup /scripts/restore /to_restore
Loading