diff --git a/.github/workflows/build-docker.yml b/.github/workflows/build-docker.yml index 6e7432022ad..559deab9321 100644 --- a/.github/workflows/build-docker.yml +++ b/.github/workflows/build-docker.yml @@ -9,7 +9,7 @@ on: - main jobs: - docker: + build_docker_x86: runs-on: ubuntu-latest steps: - name: Checkout @@ -27,7 +27,7 @@ jobs: uses: gittools/actions/gitversion/execute@v0.9.15 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2.1.0 + uses: docker/setup-buildx-action@v2 with: install: true @@ -35,12 +35,12 @@ jobs: uses: actions/cache@main with: path: /tmp/.buildx-cache - key: ${{ runner.os }}-buildx-${{ github.sha }} + key: ${{ runner.os }}-x86-${{ github.sha }} restore-keys: | - ${{ runner.os }}-buildx- + ${{ runner.os }}-x86- - name: Login to GitHub Container Registry - uses: docker/login-action@v2.1.0 + uses: docker/login-action@v2 with: registry: ghcr.io username: ${{ github.repository_owner }} @@ -50,7 +50,7 @@ jobs: if: ${{ github.event_name == 'pull_request' }} uses: docker/build-push-action@v3.2.0 with: - file: docker/server/Dockerfile + file: docker/Dockerfile.x86 tags: ghcr.io/${{ github.repository }}:${{ steps.gitversion.outputs.semVer }} cache-from: type=gha, scope=${{ github.workflow }} cache-to: type=gha, scope=${{ github.workflow }} @@ -60,7 +60,7 @@ jobs: if: ${{ github.event_name == 'push' }} uses: docker/build-push-action@v3.2.0 with: - file: docker/server/Dockerfile + file: docker/Dockerfile.x86 push: true tags: ghcr.io/${{ github.repository }}:${{ steps.gitversion.outputs.semVer }} cache-from: type=gha, scope=${{ github.workflow }} @@ -70,10 +70,40 @@ jobs: if: ${{ github.event_name == 'push' }} run: echo ${{ steps.docker_build.outputs.digest }} - # # Temp fix - # # https://github.com/docker/build-push-action/issues/252 - # # https://github.com/moby/buildkit/issues/1896 - # - name: Move cache - # run: | - # rm -rf /tmp/.buildx-cache - # mv /tmp/.buildx-cache-new /tmp/.buildx-cache + build_docker_arm: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@main + with: + fetch-depth: 0 + + - name: Install GitVersion + uses: gittools/actions/gitversion/setup@v0.9.15 + with: + versionSpec: '5.x' + + - name: Determine Version + id: gitversion + uses: gittools/actions/gitversion/execute@v0.9.15 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + with: + install: true + + - name: Cache Docker layers + uses: actions/cache@main + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-arm-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-arm- + + - name: Build + uses: docker/build-push-action@v3.2.0 + with: + file: docker/Dockerfile.arm + tags: ghcr.io/${{ github.repository }}:${{ steps.gitversion.outputs.semVer }} + cache-from: type=gha, scope=${{ github.workflow }} + cache-to: type=gha, scope=${{ github.workflow }} diff --git a/docker/.gitignore b/docker/.gitignore deleted file mode 100644 index 71f67ff2df6..00000000000 --- a/docker/.gitignore +++ /dev/null @@ -1 +0,0 @@ -data/web/* diff --git a/docker/Dockerfile.arm b/docker/Dockerfile.arm new file mode 100644 index 00000000000..f96c0ca0cff --- /dev/null +++ b/docker/Dockerfile.arm @@ -0,0 +1,49 @@ +# Stage 1: Download all dependencies +FROM ubuntu:22.04 AS dependencies + +RUN apt-get update && apt-get install -y --no-install-recommends cmake git \ + unzip build-essential ca-certificates curl zip unzip tar \ + pkg-config ninja-build autoconf automake libtool libluajit-5.1-dev libluajit-5.1-common \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /opt +RUN git clone https://github.com/microsoft/vcpkg --depth=1 \ + && ./vcpkg/bootstrap-vcpkg.sh + +WORKDIR /opt/vcpkg +COPY vcpkg.json /opt/vcpkg/ +RUN VCPKG_FORCE_SYSTEM_BINARIES=1 /opt/vcpkg/vcpkg --feature-flags=binarycaching,manifests,versions install + +# Stage 2: create build +FROM dependencies AS build + +COPY . /srv/ +WORKDIR /srv + +RUN export VCPKG_ROOT=/opt/vcpkg/ && VCPKG_FORCE_SYSTEM_BINARIES=1 cmake --preset linux-release && cmake --build --preset linux-release + +# Stage 3: load data and execute +FROM ubuntu:22.04 + +VOLUME [ "/data" ] + +COPY --from=build /srv/build/linux-release/bin/canary /bin/canary +COPY LICENSE *.sql key.pem /canary/ +COPY data /canary/data +COPY data-canary /canary/data-canary +COPY data-otservbr-global /canary/data-otservbr-global +COPY config.lua.dist /canary/config.lua + +WORKDIR /canary + +RUN apt-get update && apt-get install -y --no-install-recommends \ + mariadb-client libluajit-5.1-dev libluajit-5.1-common wget curl \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +COPY docker/data/01-test_account.sql 01-test_account.sql +COPY docker/data/02-test_account_players.sql 02-test_account_players.sql +COPY docker/data/start.sh start.sh + +ENTRYPOINT ["/canary/start.sh"] diff --git a/docker/server/Dockerfile b/docker/Dockerfile.x86 similarity index 72% rename from docker/server/Dockerfile rename to docker/Dockerfile.x86 index 68a0725e029..bc7835a313f 100644 --- a/docker/server/Dockerfile +++ b/docker/Dockerfile.x86 @@ -8,8 +8,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends cmake git \ && rm -rf /var/lib/apt/lists/* WORKDIR /opt -RUN git clone https://github.com/microsoft/vcpkg --depth=1 -RUN ./vcpkg/bootstrap-vcpkg.sh +RUN git clone https://github.com/microsoft/vcpkg --depth=1 \ + && ./vcpkg/bootstrap-vcpkg.sh WORKDIR /opt/vcpkg COPY vcpkg.json /opt/vcpkg/ @@ -25,19 +25,24 @@ RUN export VCPKG_ROOT=/opt/vcpkg/ && cmake --preset linux-release && cmake --bui # Stage 3: load data and execute FROM ubuntu:22.04 +VOLUME [ "/data" ] COPY --from=build /srv/build/linux-release/bin/canary /bin/canary COPY LICENSE *.sql key.pem /canary/ COPY data /canary/data +COPY data-canary /canary/data-canary +COPY data-otservbr-global /canary/data-otservbr-global COPY config.lua.dist /canary/config.lua WORKDIR /canary RUN apt-get update && apt-get install -y --no-install-recommends \ - mariadb-client \ + mariadb-client curl \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* -COPY docker/server/start.sh start.sh +COPY docker/data/01-test_account.sql 01-test_account.sql +COPY docker/data/02-test_account_players.sql 02-test_account_players.sql +COPY docker/data/start.sh start.sh ENTRYPOINT ["/canary/start.sh"] diff --git a/docker/data/download-myaac.sh b/docker/data/download-myaac.sh deleted file mode 100755 index e02b9588553..00000000000 --- a/docker/data/download-myaac.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash - -wget https://github.com/slawkens/myaac/archive/master.zip -O myaac.zip -unzip -o myaac.zip -d . - -mv myaac-master/* ./web -rm myaac.zip myaac-master -rf - -wget https://github.com/opentibiabr/myaac-tibia12-login/archive/refs/heads/develop.zip -O myaac-otbr-plugin.zip -unzip -o myaac-otbr-plugin.zip -d . - -cp -r myaac-tibia12-login-develop/* ./web -rm -rf myaac-otbr-plugin.zip myaac-tibia12-login-develop \ No newline at end of file diff --git a/docker/data/login.py b/docker/data/login.py deleted file mode 100755 index 5aaccb3f8db..00000000000 --- a/docker/data/login.py +++ /dev/null @@ -1,183 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -""" -This is python script to simulate the login functions used by the Tibia client +11! -""" - -from flask import Flask -from flask import jsonify -from flask import request -import mysql.connector as mariadb -from mysql.connector import Error -import time -import os - -app = Flask(__name__) - -def do_login(data): - - try: - connection = mariadb.connect(host=os.getenv('DB_IP', 'mysql'), - database=os.getenv('DB_DATABASE', 'canary'), - user=os.getenv('DB_USER', 'canary'), - password=os.getenv('DB_PASSWORD', 'canary')) - - sql_select_Query = "SELECT id, premdays, lastday FROM accounts WHERE name = '" + data['email'].replace('@','') + "'" - - print("Loading account information!") - cursor = connection.cursor() - cursor.execute(sql_select_Query) - records = cursor.fetchall() - for row in records: - print("Id = ", row[0]) - account_id = row[0] - account_premdays = row[1] - account_lastday = row[2] - - session = { - 'sessionkey': data['email'] + '\n' + data['password'], - 'lastlogintime': 0, - 'ispremium': True if account_premdays > 0 else False, - 'premiumuntil': 0 if account_premdays == 0 else int(time.time()) + (account_premdays * 86400), - 'status': 'active', - 'returnernotification': False, - 'showrewardnews': True, - 'isreturner': True, - 'fpstracking': False, - 'optiontracking': False, - 'tournamentticketpurchasestate': 0, - 'emailcoderequest': False - }; - print(session) - - sql_select_Query = "SELECT name, level, sex, vocation, looktype, lookhead, lookbody, looklegs, lookfeet, lookaddons, lastlogin from players where account_id = '" + str(account_id) + "'" - - cursor = connection.cursor() - cursor.execute(sql_select_Query) - records = cursor.fetchall() - print(records) - - players = [] - vocations = ['None', 'Sorcerer', 'Druid', 'Paladin', 'Knight', 'Master Sorcerer', 'Elder Druid', 'Royal Paladin', 'Elite Knight', 'Sorcerer Dawnport', 'Druid Dawnport', 'Paladin Dawnport', 'Knight Dawnport'] - print("Loading account players information!") - for (name, level, sex, vocation, looktype, lookhead, lookbody, looklegs, lookfeet, lookaddons, lastlogin) in records: - player = { - 'worldid': 0, - 'name': name, - 'level': level, - 'ismale': True if sex == 1 else False, - 'vocation': vocations[vocation], - 'outfitid': looktype, - 'headcolor': lookhead, - 'torsocolor': lookbody, - 'legscolor': looklegs, - 'detailcolor': lookfeet, - 'addonsflags': lookaddons, - 'tutorial': False, # True will make the client crash as it will try to auto connect - 'ishidden': False, - 'istournamentparticipant': False, - 'remainingdailytournamentplaytime': 0 - } - players.append(player) - print(players) - - playdata = { - 'worlds': [ - { - 'id': 0, - 'name': os.getenv('SERVER_NAME', 'Canary'), - 'externaladdressprotected': os.getenv('PROXY_IP', '127.0.0.1'), - 'externalportprotected': int(os.getenv('SERVER_GAME_PORT', 7172)), - 'externaladdressunprotected': os.getenv('PROXY_IP', '127.0.0.1'), - 'externalportunprotected': int(os.getenv('SERVER_GAME_PORT', 7172)), - 'previewstate': 0, - 'location': 'BRA', - 'anticheatprotection': False, - 'pvptype': 'pvp', - 'istournamentworld': False, - 'restrictedstore': False, - 'currenttournamentphase': 2 - } - ], - "characters": players - } - - answer = {'session': session, 'playdata': playdata} - print(answer) - return jsonify(answer) - - except Error as e: - print("Error reading data from MySQL table", e) - - finally: - if (connection.is_connected()): - connection.close() - cursor.close() - print("MySQL connection is closed") - - -def news(data): - - answer = [] - - return jsonify(answer) - - -@app.route('/login.php', methods=['GET', 'POST', 'PUT']) -def action(): - - data = request.get_json() - print(data) - - if(data['type'] == 'cacheinfo'): - return jsonify({ - 'playersonline': 5, - 'twitchstreams': 0, - 'twitchviewer': 0, - 'gamingyoutubestreams': 0, - 'gamingyoutubeviewer': 0 - }) - if(data['type'] == 'news'): - return jsonify({}) - - # The client has a cache of the events on it so it will ask for the events only when it see that last sync was made some time X ago - if(data['type'] == 'eventschedule'): - return jsonify({ - 'lastupdatetimestamp': time.time(), - 'eventlist': [ - { - 'startdate': int(time.time()), - 'enddate': int(time.time()) + 36600 * 20, - 'colorlight': '#64162b', - 'colordark': '#7a1b34', - 'name': 'First Event', - 'description': 'Canary Event 1', - 'isseasonal': False - }, - { - 'startdate': int(time.time()), - 'enddate': int(time.time()) + 36600 * 20, - 'colorlight': '#8B6D05', - 'colordark': '#735D10', - 'name': 'Second Event', - 'description': 'Canary Event 2', - 'isseasonal': False - } - ] - }) - - if(data['type'] == 'boostedcreature'): - return jsonify({ - 'boostedcreature': True, - 'raceid': 39 - }) - - if(data['type'] == 'login'): - return do_login(data) - - - if(data['type'] == 'news'): - return news(data) - -app.run(debug=True, host='0.0.0.0', port=8080) diff --git a/docker/data/start.sh b/docker/data/start.sh new file mode 100755 index 00000000000..db688b488d0 --- /dev/null +++ b/docker/data/start.sh @@ -0,0 +1,173 @@ +#!/bin/bash -e + +OT_DB_HOST="${OT_DB_HOST:-127.0.0.1}" +OT_DB_PORT="${OT_DB_PORT:-3306}" +OT_DB_USER="${OT_DB_USER:-canary}" +OT_DB_PASSWORD="${OT_DB_PASSWORD:-canary}" +OT_DB_DATABASE="${OT_DB_DATABASE:-canary}" +OT_SERVER_IP="${OT_SERVER_IP:-127.0.0.1}" +OT_SERVER_LOGIN_PORT="${OT_SERVER_LOGIN_PORT:-7171}" +OT_SERVER_GAME_PORT="${OT_SERVER_GAME_PORT:-7172}" +OT_SERVER_STATUS_PORT="${OT_SERVER_STATUS_PORT:-7171}" +OT_SERVER_TEST_ACCOUNTS="${OT_SERVER_TEST_ACCOUNTS:-false}" +OT_SERVER_DATA="${OT_SERVER_DATA:-data-canary}" +OT_SERVER_MAP="${OT_SERVER_MAP:-https://github.com/opentibiabr/otservbr-global/releases/download/v1.5.0/otservbr.otbm}" + +echo "" +echo "===== Print Variables =====" +echo "" + +echo "OT_DB_HOST:[$OT_DB_HOST]" +echo "OT_DB_PORT:[$OT_DB_PORT]" +echo "OT_DB_USER:[$OT_DB_USER]" +echo "OT_DB_PASSWORD:[$OT_DB_PASSWORD]" +echo "OT_DB_DATABASE:[$OT_DB_DATABASE]" +echo "OT_SERVER_IP:[$OT_SERVER_IP]" +echo "OT_SERVER_LOGIN_PORT:[$OT_SERVER_LOGIN_PORT]" +echo "OT_SERVER_GAME_PORT:[$OT_SERVER_GAME_PORT]" +echo "OT_SERVER_STATUS_PORT:[$OT_SERVER_STATUS_PORT]" +echo "OT_SERVER_TEST_ACCOUNTS:[$OT_SERVER_TEST_ACCOUNTS]" +echo "OT_SERVER_DATA:[$OT_SERVER_DATA]" +echo "OT_SERVER_MAP:[$OT_SERVER_MAP]" + +echo "" +echo "================================" +echo "" + +echo "" +echo "===== OTBR Global Data Pack =====" +echo "" + +if [ "$OT_SERVER_DATA" = "data-otservbr-global" ] && [ ! -f data-otservbr-global/world/otservbr.otbm ]; then + echo "YES" + + echo "Downloading OTBR Map..." + wget --no-check-certificate "$OT_SERVER_MAP" -O data-otservbr-global/world/otservbr.otbm + + echo "Done" + +else + echo "Not Using OTBR Data pack" +fi + +echo "" +echo "================================" +echo "" + +echo "" +echo "===== Wait For The DB To Be Up =====" +echo "" + +until mysql -u "$OT_DB_USER" -p"$OT_DB_PASSWORD" -h "$OT_DB_HOST" --port="$OT_DB_PORT" -e "SHOW DATABASES;"; do + echo "DB offline, trying again" + sleep 5s +done + +echo "" +echo "================================" +echo "" + +echo "" +echo "===== Check If DB Already Exists =====" +echo "" +if mysql -u "$OT_DB_USER" -p"$OT_DB_PASSWORD" -h "$OT_DB_HOST" --port="$OT_DB_PORT" -e "use $OT_DB_DATABASE"; then + echo "Creating Database Backup" + echo "Saving database to all_databases.sql" + mysqldump -u "$OT_DB_USER" -p"$OT_DB_PASSWORD" -h "$OT_DB_HOST" --port="$OT_DB_PORT" --all-databases >/data/all_databases.sql +else + echo "Creating Database" + mysql -u "$OT_DB_USER" -p"$OT_DB_PASSWORD" -h "$OT_DB_HOST" --port="$OT_DB_PORT" -e "CREATE DATABASE $OT_DB_DATABASE;" + mysql -u "$OT_DB_USER" -p"$OT_DB_PASSWORD" -h "$OT_DB_HOST" --port="$OT_DB_PORT" -e "SHOW DATABASES;" +fi +echo "" +echo "================================" +echo "" + +echo "" +echo "===== Check If We Need To Import Schema.sql =====" +echo "" + +if [[ $(mysql -u "$OT_DB_USER" -p"$OT_DB_PASSWORD" -h "$OT_DB_HOST" -e 'SHOW TABLES LIKE "server_config"' -D "$OT_DB_DATABASE") ]]; then + echo "Table server_config exists so we don't need to import" +else + echo "Import Canary-Server Schema" + mysql -u "$OT_DB_USER" -p"$OT_DB_PASSWORD" -h "$OT_DB_HOST" --port="$OT_DB_PORT" -D "$OT_DB_DATABASE"