Dramatically improve podman support and provide step by step instructions

This commit is contained in:
Sirz Benjie 2025-09-16 13:17:05 -05:00
parent d73f761869
commit f01bc9aaf4
No known key found for this signature in database
GPG Key ID: 4A524B4D196C759E
7 changed files with 486 additions and 129 deletions

View File

@ -1,6 +1,6 @@
ARG GO_VERSION=1.22 ARG GO_VERSION=1.22
FROM golang:${GO_VERSION} AS builder FROM docker.io/library/golang:${GO_VERSION} AS builder
WORKDIR /src WORKDIR /src
@ -12,7 +12,7 @@ RUN go mod download && go mod verify
COPY . /src/ COPY . /src/
RUN CGO_ENABLED=0 \ RUN CGO_ENABLED=0 \
go build -o rogueserver go build -tags=devsetup -o rogueserver
RUN chmod +x /src/rogueserver RUN chmod +x /src/rogueserver

309
README.md
View File

@ -1,50 +1,237 @@
# rogueserver # rogueserver
# Hosting in Docker ## Table of Contents
It is advised that you host this in a docker container as it will be much easier to manage.
There is a sample docker-compose file for setting up a docker container to setup this server.
# Self Hosting outside of Docker: - [Quickstart (Linux, Podman/Docker)](#quickstart-linuxwsl-podmandocker)
## Required Tools: - [Quickstart (Windows, Podman)](#quickstart-windows-podman)
- [Running without Podman/Docker](#running-without-podmandocker)
- [On Linux](#on-linux)
- [Self Hosting](#self-hosting)
- [Podman/Docker Mini Primer](#primer-images-containers-and-compose)
## Quickstart (Linux/WSL, Podman/Docker)
These are the exact steps to get this repo working from a fresh clone on a typical Linux system using Podman (a Docker alternative). This is the recommended way for development and local testing.
Note that you can also use Docker as a drop-in replacement for podman, though the steps are a bit different.
For hosting the server for purposes outside of aiding in the development of PokéRogue, see [Self Hosting outside of Docker](#self-hosting-outside-of-docker)
#### 1. Install Required Packages
You will need the following packages:
- **Podman** ([install guide](https://podman.io/getting-started/installation))
- **Podman Compose** ([install guide](https://github.com/containers/podman-compose#installation))
You do not need Go (Golang) installed on your host system for this setup—the container image will handle all Go builds internally.
Install dependencies using your system's package manager:
**Using apt (Debian/Ubuntu and derivatives):**
```sh
sudo apt update
sudo apt install -y podman podman-compose
```
**Using dnf (Fedora and derivatives):**
```sh
sudo dnf install -y podman podman-compose
```
If your distribution does not provide podman-compose as a package, you can install it with pipx or pip:
**First, install [pipx](https://pipx.pypa.io/stable/):**
```sh
# Using apt
sudo apt install pipx
# Or using dnf
sudo dnf install pipx
# Or, with pip (if not available as a package):
python3 -m pip install --user pipx
python3 -m pipx ensurepath
```
**Then, install podman-compose:**
```sh
# Using pipx (recommended for isolated installs)
pipx install podman-compose
# Or, using pip (installs to user site-packages)
pip install --user podman-compose
```
#### 2. Clone the Repository
```sh
git clone <this-repo-url>
cd rogueserver
```
#### 3. Build the Go Server Image
```sh
podman build -t rogueserver:dev .
```
#### 4. Start the Development Environment
```sh
podman-compose -f docker-compose.Development.yml up
```
This will start both the MariaDB database and the Go server. The first startup will initialize the database schema automatically (dev only).
#### 5. Access the Server
- The API will be available at: http://localhost:8001
- The game server (if running) will be at: http://localhost:8000
#### 6. (Optional) Stopping and Cleaning Up
To stop the services:
```sh
podman-compose -f docker-compose.Development.yml down
```
To remove all containers and volumes:
```sh
podman-compose -f docker-compose.Development.yml down -v
```
---
## Quickstart (Windows, Podman/Docker)
These are the steps to get this repo working from a fresh clone on Windows using Podman Desktop and podman-compose. This is the recommended way for development and local testing on Windows.
Docker can also be used instead of Podman.
#### 1. Install Required Software
- **Podman Desktop** ([download here](https://podman-desktop.io/))
- **podman-compose** (included with Podman Desktop, or install via pipx/pip if needed)
#### 2. Clone the Repository
Open PowerShell or Command Prompt and run:
```powershell
git clone <this-repo-url>
cd rogueserver
```
#### 3. Build the Go Server Image
Open a terminal in the project directory and run:
```powershell
podman build -t rogueserver:dev .
```
#### 4. Start the Development Environment
```powershell
podman-compose -f docker-compose.Development.yml up
```
This will start both the MariaDB database and the Go server. The first startup will initialize the database schema automatically (dev only).
#### 5. Access the Server
- The API will be available at: http://localhost:8001
- The game server (if running) will be at: http://localhost:8000
#### 6. (Optional) Stopping and Cleaning Up
To stop the services:
```powershell
podman-compose -f docker-compose.Development.yml down
```
To remove all containers and volumes:
```powershell
podman-compose -f docker-compose.Development.yml down -v
```
## Running without Podman/Docker
### Required Tools:
- Golang - Golang
- Node: **18.3.0** - mariadb [how to install](https://mariadb.org/download/)
- npm: [how to install](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)
## Installation: You must install and configure MariaDB yourself when not using Podman/Docker.
The docker compose file should automatically implement a container with mariadb with an empty database and the default user and password combo of pokerogue:pokerogue
### src/utils.ts:224-225 (in pokerogue) #### Linux / WSL
Replace both URLs (one on each line) with the local API server address from rogueserver.go (0.0.0.0:8001) (or whatever port you picked) ```sh
sudo apt update
# If you are on Windows sudo apt install mariadb-server
sudo systemctl start mariadb
Now that all of the files are configured: start up powershell as administrator: sudo systemctl enable mariadb
``` ```
Then, secure your installation and set up the database and user:
```sh
sudo mysql_secure_installation
sudo mysql -u root -p
```
In the MariaDB shell, run:
```sql
CREATE DATABASE pokerogue;
CREATE USER 'pokerogue'@'localhost' IDENTIFIED BY 'pokerogue';
GRANT ALL PRIVILEGES ON pokerogue.* TO 'pokerogue'@'localhost';
FLUSH PRIVILEGES;
EXIT;
```
#### Windows
- Download and install MariaDB from the [official site](https://mariadb.org/download/).
- Use the MariaDB command line or a GUI tool to create a database named `pokerogue` and a user `pokerogue` with password `pokerogue`, and grant that user all privileges on the database.
You can use different credentials, but you must update your server's configuration/flags accordingly.
---
### Buliding and Running
Now that all of the files and dependencies are configured, the next step is to build the server and then run it.
##### Windows
```powershell
cd C:\api\server\location\ cd C:\api\server\location\
go build . go build . -tags=devsetup
.\rogueserver.exe --debug --dbuser yourusername --dbpass yourpassword .\rogueserver.exe
``` ```
The other available flags are located in rogueserver.go:34-43. You may need to adjust environment variables to adjust things like the database user and password, and setup debug mode.
See [rogueserver.go](./rogueserver.go)
Then in another run this the first time then run `npm run start` from the rogueserver location from then on: ### Linux
In whatever shell you prefer, run the following:
```sh
go build . -tags=devsetup
dbuser=pokerogue dbpass=pokerogue debug=1 ./rogueserver &
``` ```
## Self Hosting
You can host your own rogueserver and allow other machines to connect to it.
You will need npm: [how to install](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)
The first steps are the same as the above section, but have an additional step to expose the server to outside connections.
### Windows
##### The following step is only necessary to host the server for external use, and is unnecessary for development
Then in another run this the first time then run `npm run start` from the rogueserver location from then on:
```powershell
powershell -ep bypass powershell -ep bypass
cd C:\server\location\ cd C:\server\location\
npm install npm install
npm run start npm run start
``` ```
You will need to allow the port youre running the API (8001) on and port 8000 to accept inbound connections through the [Windows Advanced Firewall](https://www.youtube.com/watch?v=9llH5_CON-Y). You will need to allow the port you're running the API (8001) on and port 8000 to accept inbound connections through the [Windows Advanced Firewall](https://www.youtube.com/watch?v=9llH5_CON-Y).
# If you are on Linux ### Linux
In whatever shell you prefer, run the following: In whatever shell you prefer, run the following:
```sh
go build -tags=devsetup
dbuser=pokerogue dbpass=pokerogue debug=1 ./rogueserver &
``` ```
cd /api/server/location/ you can replace the dbuser=..., etc., with whatever authentication you chose for mariadb. These just set the environment variables for the running process. Alternatively, load them into their own environment variables before running `./rogueserver`.
go build . `debug` is obviously optional.
./rogueserver --debug --dbuser yourusername --dbpass yourpassword &
cd /server/location/
npm run start
```
If you have a firewall running such as ufw on your linux machine, make sure to allow inbound connections on the ports youre running the API and the pokerogue server (8000,8001). If you have a firewall running such as ufw on your linux machine, make sure to allow inbound connections on the ports youre running the API and the pokerogue server (8000,8001).
An example to allow incoming connections using UFW: An example to allow incoming connections using UFW:
@ -54,11 +241,11 @@ sudo ufw allow 8000,8001/tcp
This should allow you to reach the game from other computers on the same network. This should allow you to reach the game from other computers on the same network.
## Tying to a Domain ### Tying to a Domain
If you want to tie it to a domain like I did and make it publicly accessible, there is some extra work to be done. If you want to tie it to a domain and make it publicly accessible, there is some extra work to be done.
I setup caddy and would recommend using it as a reverse proxy. It is recommended to setup caddy and use it as a reverse proxy.
[caddy installation](https://caddyserver.com/docs/install) [caddy installation](https://caddyserver.com/docs/install)
once its installed setup a config file for caddy: once its installed setup a config file for caddy:
@ -72,12 +259,66 @@ pokeapi.exampledomain.com {
``` ```
Preferably set up caddy as a service from [here.](https://caddyserver.com/docs/running) Preferably set up caddy as a service from [here.](https://caddyserver.com/docs/running)
Once this is good to go, take your API url (https://pokeapi.exampledomain.com) and paste it on Once this is good to go, take your API url (https://pokeapi.exampledomain.com) and paste it in the apprporiate `.env` file for PokéRogue in place of the previous address.
### src/utils.ts:224-225
in place of the previous 0.0.0.0:8001 address
Make sure that both 8000 and 8001 are portforwarded on your router. Make sure that both 8000 and 8001 are portforwarded on your router.
Test that the server's game and game authentication works from other machines both in and outside of the network. Once this is complete, enjoy! Test that the server's game and game authentication works from other machines both in and outside of the network. Once this is complete, enjoy!
## Podman/Docker Mini Primer
### What are Images, Containers, and Compose?
- **Image:** A snapshot or template of an application and its environment (e.g., `mariadb:11`, `rogueserver:dev`). You build or pull images, and then run containers from them. Think of an image as a "blueprint" for a program. Images can be sourced from an existing provider (like docker.io) or built locally.
- **Container:** A running instance of an image. Its isolated from your host system, but can be allowed to connect to networks and volumes. Containers are temporary by default, but you can persist data using named volumes.
- **Compose:** A tool and YAML file format (e.g., `docker-compose.Development.yml`) for defining and running multi-container applications. Compose lets you start, stop, and manage groups of containers (services), their networks, and volumes with a single command. The compose file provides instructions for how to run the images and what commands to take.
### Why are the steps above needed?
1. **Build the image:**
- You only need to do this when the code or Dockerfile changes, or when setting up for the first time. This creates the `rogueserver:dev` image locally.
2. **Create the network:**
- This is needed once, unless you delete the network. It allows your containers to communicate securely and privately.
3. **Start the environment (compose up):**
- This launches the containers as defined in your compose file. You do this every time you want to start the server/database.
4. **Stop the environment (compose down):**
- This stops and removes the containers, but keeps your data (unless you use `-v`).
5. **Rebuilding:**
- If you change your code or Dockerfile, rebuild the image and restart the environment.
### Which steps do I repeat?
- **Daily development:**
- Run `podman-compose up` to start, and `podman-compose down` to stop.
- **If rogueserver changes:**
- Rebuild the image (`podman build -t rogueserver:dev .`), then restart the environment.
- **If you want to reset everything:**
- See below for clearing out all Podman data.
### How do I clear out all Podman containers, images, and volumes?
**Warning:** This will delete all containers, images, and volumes managed by Podman on your system!
```sh
podman stop --all
podman rm --all
podman rmi --all
podman volume rm --all
```
To only remove the ones for rogueserver, pass explicit names. You can see the images, for example, via
```sh
podman ps
```
To delete everything at once, do
```sh
podman system prune -a
```
This is useful if you want to start completely fresh or reclaim disk space.
---
In short: **Images** are blueprints, **containers** are running apps, and **compose** is how you manage multi-container setups easily. The steps above help you build, run, and manage your development environment in a repeatable and isolated way.

View File

@ -48,92 +48,11 @@ func Init(username, password, protocol, address, database string) error {
s3client = s3.NewFromConfig(cfg) s3client = s3.NewFromConfig(cfg)
} }
/*conns := 64 // Conditionally run DB setup (devsetup build tag controls behavior)
err = MaybeSetupDb(handle)
handle.SetMaxOpenConns(conns)
handle.SetMaxIdleConns(conns)*/
/*tx, err := handle.Begin()
if err != nil { if err != nil {
log.Fatal(err) return err
} }
err = setupDb(tx)
if err != nil {
tx.Rollback()
log.Fatal(err)
}
err = tx.Commit()
if err != nil {
log.Fatal(err)
}*/
return nil return nil
} }
/*func setupDb(tx *sql.Tx) error {
queries := []string{
// MIGRATION 000
`CREATE TABLE IF NOT EXISTS accounts (uuid BINARY(16) NOT NULL PRIMARY KEY, username VARCHAR(16) UNIQUE NOT NULL, hash BINARY(32) NOT NULL, salt BINARY(16) NOT NULL, registered TIMESTAMP NOT NULL, lastLoggedIn TIMESTAMP DEFAULT NULL, lastActivity TIMESTAMP DEFAULT NULL, banned TINYINT(1) NOT NULL DEFAULT 0, trainerId SMALLINT(5) UNSIGNED DEFAULT 0, secretId SMALLINT(5) UNSIGNED DEFAULT 0)`,
`CREATE INDEX IF NOT EXISTS accountsByActivity ON accounts (lastActivity)`,
`CREATE TABLE IF NOT EXISTS sessions (token BINARY(32) NOT NULL PRIMARY KEY, uuid BINARY(16) NOT NULL, active TINYINT(1) NOT NULL DEFAULT 0, expire TIMESTAMP DEFAULT NULL, CONSTRAINT sessions_ibfk_1 FOREIGN KEY (uuid) REFERENCES accounts (uuid) ON DELETE CASCADE ON UPDATE CASCADE)`,
`CREATE INDEX IF NOT EXISTS sessionsByUuid ON sessions (uuid)`,
`CREATE TABLE IF NOT EXISTS accountStats (uuid BINARY(16) NOT NULL PRIMARY KEY, playTime INT(11) NOT NULL DEFAULT 0, battles INT(11) NOT NULL DEFAULT 0, classicSessionsPlayed INT(11) NOT NULL DEFAULT 0, sessionsWon INT(11) NOT NULL DEFAULT 0, highestEndlessWave INT(11) NOT NULL DEFAULT 0, highestLevel INT(11) NOT NULL DEFAULT 0, pokemonSeen INT(11) NOT NULL DEFAULT 0, pokemonDefeated INT(11) NOT NULL DEFAULT 0, pokemonCaught INT(11) NOT NULL DEFAULT 0, pokemonHatched INT(11) NOT NULL DEFAULT 0, eggsPulled INT(11) NOT NULL DEFAULT 0, regularVouchers INT(11) NOT NULL DEFAULT 0, plusVouchers INT(11) NOT NULL DEFAULT 0, premiumVouchers INT(11) NOT NULL DEFAULT 0, goldenVouchers INT(11) NOT NULL DEFAULT 0, CONSTRAINT accountStats_ibfk_1 FOREIGN KEY (uuid) REFERENCES accounts (uuid) ON DELETE CASCADE ON UPDATE CASCADE)`,
`CREATE TABLE IF NOT EXISTS accountCompensations (id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, uuid BINARY(16) NOT NULL, voucherType INT(11) NOT NULL, count INT(11) NOT NULL DEFAULT 1, claimed BIT(1) NOT NULL DEFAULT b'0', CONSTRAINT accountCompensations_ibfk_1 FOREIGN KEY (uuid) REFERENCES accounts (uuid) ON DELETE CASCADE ON UPDATE CASCADE)`,
`CREATE INDEX IF NOT EXISTS accountCompensationsByUuid ON accountCompensations (uuid)`,
`CREATE TABLE IF NOT EXISTS dailyRuns (date DATE NOT NULL PRIMARY KEY, seed CHAR(24) CHARACTER SET ascii COLLATE ascii_bin NOT NULL)`,
`CREATE INDEX IF NOT EXISTS dailyRunsByDateAndSeed ON dailyRuns (date, seed)`,
`CREATE TABLE IF NOT EXISTS dailyRunCompletions (uuid BINARY(16) NOT NULL, seed CHAR(24) CHARACTER SET ascii COLLATE ascii_bin NOT NULL, mode INT(11) NOT NULL DEFAULT 0, score INT(11) NOT NULL DEFAULT 0, timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (uuid, seed), CONSTRAINT dailyRunCompletions_ibfk_1 FOREIGN KEY (uuid) REFERENCES accounts (uuid) ON DELETE CASCADE ON UPDATE CASCADE)`,
`CREATE INDEX IF NOT EXISTS dailyRunCompletionsByUuidAndSeed ON dailyRunCompletions (uuid, seed)`,
`CREATE TABLE IF NOT EXISTS accountDailyRuns (uuid BINARY(16) NOT NULL, date DATE NOT NULL, score INT(11) NOT NULL DEFAULT 0, wave INT(11) NOT NULL DEFAULT 0, timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (uuid, date), CONSTRAINT accountDailyRuns_ibfk_1 FOREIGN KEY (uuid) REFERENCES accounts (uuid) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT accountDailyRuns_ibfk_2 FOREIGN KEY (date) REFERENCES dailyRuns (date) ON DELETE NO ACTION ON UPDATE NO ACTION)`,
`CREATE INDEX IF NOT EXISTS accountDailyRunsByDate ON accountDailyRuns (date)`,
`CREATE TABLE IF NOT EXISTS systemSaveData (uuid BINARY(16) PRIMARY KEY, data LONGBLOB, timestamp TIMESTAMP, FOREIGN KEY (uuid) REFERENCES accounts (uuid) ON DELETE CASCADE ON UPDATE CASCADE)`,
`CREATE TABLE IF NOT EXISTS sessionSaveData (uuid BINARY(16), slot TINYINT, data LONGBLOB, timestamp TIMESTAMP, PRIMARY KEY (uuid, slot), FOREIGN KEY (uuid) REFERENCES accounts (uuid) ON DELETE CASCADE ON UPDATE CASCADE)`,
// ----------------------------------
// MIGRATION 001
`ALTER TABLE sessions DROP COLUMN IF EXISTS active`,
`CREATE TABLE IF NOT EXISTS activeClientSessions (uuid BINARY(16) NOT NULL PRIMARY KEY, clientSessionId VARCHAR(32) NOT NULL, FOREIGN KEY (uuid) REFERENCES accounts (uuid) ON DELETE CASCADE ON UPDATE CASCADE)`,
// ----------------------------------
// MIGRATION 002
`DROP TABLE accountCompensations`,
// ----------------------------------
// MIGRATION 003
`ALTER TABLE accounts ADD COLUMN IF NOT EXISTS discordId VARCHAR(32) UNIQUE DEFAULT NULL`,
`ALTER TABLE accounts ADD COLUMN IF NOT EXISTS googleId VARCHAR(32) UNIQUE DEFAULT NULL`,
// ----------------------------------
// MIGRATION 004
`ALTER TABLE accounts ADD COLUMN IF NOT EXISTS isInLocalDb TINYINT(1) NOT NULL DEFAULT 1`,
// ----------------------------------
// MIGRATION 005
`ALTER TABLE accounts DROP COLUMN IF EXISTS isInLocalDb`,
}
for _, q := range queries {
_, err := tx.Exec(q)
if err != nil {
return fmt.Errorf("failed to execute query: %w, query: %s", err, q)
}
}
return nil
}*/

139
db/db_setup.go Normal file
View File

@ -0,0 +1,139 @@
//go:build devsetup
// +build devsetup
package db
import (
"database/sql"
"fmt"
"os"
)
// MaybeSetupDb is called by db.go and runs setupDb only in devsetup builds.
func MaybeSetupDb(db *sql.DB) error {
tx, err := db.Begin()
if err != nil {
return err
}
err = setupDb(tx)
if err != nil {
tx.Rollback()
return err
}
err = tx.Commit()
if err != nil {
return err
}
return nil
}
func setupDb(tx *sql.Tx) error {
queries := []string{
`CREATE TABLE IF NOT EXISTS accounts (
uuid BINARY(16) NOT NULL PRIMARY KEY,
username VARCHAR(16) UNIQUE NOT NULL,
hash BINARY(32) NOT NULL,
salt BINARY(16) NOT NULL,
registered TIMESTAMP NOT NULL,
lastLoggedIn TIMESTAMP DEFAULT NULL,
lastActivity TIMESTAMP DEFAULT NULL,
banned TINYINT(1) NOT NULL DEFAULT 0,
trainerId SMALLINT(5) UNSIGNED DEFAULT 0,
secretId SMALLINT(5) UNSIGNED DEFAULT 0,
discordId VARCHAR(32) UNIQUE DEFAULT NULL,
googleId VARCHAR(32) UNIQUE DEFAULT NULL
)`,
`CREATE INDEX IF NOT EXISTS accountsByActivity ON accounts (lastActivity)`,
`CREATE TABLE IF NOT EXISTS sessions (
token BINARY(32) NOT NULL PRIMARY KEY,
uuid BINARY(16) NOT NULL,
expire TIMESTAMP DEFAULT NULL,
CONSTRAINT sessions_ibfk_1 FOREIGN KEY (uuid) REFERENCES accounts (uuid) ON DELETE CASCADE ON UPDATE CASCADE
)`,
`CREATE INDEX IF NOT EXISTS sessionsByUuid ON sessions (uuid)`,
`CREATE TABLE IF NOT EXISTS accountStats (
uuid BINARY(16) NOT NULL PRIMARY KEY,
playTime INT(11) NOT NULL DEFAULT 0,
battles INT(11) NOT NULL DEFAULT 0,
classicSessionsPlayed INT(11) NOT NULL DEFAULT 0,
sessionsWon INT(11) NOT NULL DEFAULT 0,
highestEndlessWave INT(11) NOT NULL DEFAULT 0,
highestLevel INT(11) NOT NULL DEFAULT 0,
pokemonSeen INT(11) NOT NULL DEFAULT 0,
pokemonDefeated INT(11) NOT NULL DEFAULT 0,
pokemonCaught INT(11) NOT NULL DEFAULT 0,
pokemonHatched INT(11) NOT NULL DEFAULT 0,
eggsPulled INT(11) NOT NULL DEFAULT 0,
regularVouchers INT(11) NOT NULL DEFAULT 0,
plusVouchers INT(11) NOT NULL DEFAULT 0,
premiumVouchers INT(11) NOT NULL DEFAULT 0,
goldenVouchers INT(11) NOT NULL DEFAULT 0,
CONSTRAINT accountStats_ibfk_1 FOREIGN KEY (uuid) REFERENCES accounts (uuid) ON DELETE CASCADE ON UPDATE CASCADE
)`,
`CREATE TABLE IF NOT EXISTS dailyRuns (
date DATE NOT NULL PRIMARY KEY,
seed CHAR(24) CHARACTER SET ascii COLLATE ascii_bin NOT NULL
)`,
`CREATE INDEX IF NOT EXISTS dailyRunsByDateAndSeed ON dailyRuns (date, seed)`,
`CREATE TABLE IF NOT EXISTS dailyRunCompletions (
uuid BINARY(16) NOT NULL,
seed CHAR(24) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
mode INT(11) NOT NULL DEFAULT 0,
score INT(11) NOT NULL DEFAULT 0,
timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (uuid, seed),
CONSTRAINT dailyRunCompletions_ibfk_1 FOREIGN KEY (uuid) REFERENCES accounts (uuid) ON DELETE CASCADE ON UPDATE CASCADE
)`,
`CREATE INDEX IF NOT EXISTS dailyRunCompletionsByUuidAndSeed ON dailyRunCompletions (uuid, seed)`,
`CREATE TABLE IF NOT EXISTS accountDailyRuns (
uuid BINARY(16) NOT NULL,
date DATE NOT NULL,
score INT(11) NOT NULL DEFAULT 0,
wave INT(11) NOT NULL DEFAULT 0,
timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (uuid, date),
CONSTRAINT accountDailyRuns_ibfk_1 FOREIGN KEY (uuid) REFERENCES accounts (uuid) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT accountDailyRuns_ibfk_2 FOREIGN KEY (date) REFERENCES dailyRuns (date) ON DELETE NO ACTION ON UPDATE NO ACTION
)`,
`CREATE INDEX IF NOT EXISTS accountDailyRunsByDate ON accountDailyRuns (date)`,
`CREATE TABLE IF NOT EXISTS sessionSaveData (
uuid BINARY(16),
slot TINYINT,
data LONGBLOB,
timestamp TIMESTAMP,
PRIMARY KEY (uuid, slot),
FOREIGN KEY (uuid) REFERENCES accounts (uuid) ON DELETE CASCADE ON UPDATE CASCADE
)`,
`CREATE TABLE IF NOT EXISTS activeClientSessions (
uuid BINARY(16) NOT NULL PRIMARY KEY,
clientSessionId VARCHAR(32) NOT NULL,
FOREIGN KEY (uuid) REFERENCES accounts (uuid) ON DELETE CASCADE ON UPDATE CASCADE
)`,
}
// Conditionally add systemSaveData table if AWS_ENDPOINT_URL_S3 is not set
if os.Getenv("AWS_ENDPOINT_URL_S3") == "" {
queries = append(queries, `CREATE TABLE IF NOT EXISTS systemSaveData (
uuid BINARY(16) PRIMARY KEY,
data LONGBLOB,
timestamp TIMESTAMP,
FOREIGN KEY (uuid) REFERENCES accounts (uuid) ON DELETE CASCADE ON UPDATE CASCADE
)`)
}
for _, q := range queries {
_, err := tx.Exec(q)
if err != nil {
return fmt.Errorf("failed to execute query: %w, query: %s", err, q)
}
}
return nil
}

11
db/db_setup_stub.go Normal file
View File

@ -0,0 +1,11 @@
//go:build !devsetup
// +build !devsetup
package db
import "database/sql"
// MaybeSetupDb is called by db.go and does nothing in non-devsetup builds.
func MaybeSetupDb(db *sql.DB) error {
return nil
}

View File

@ -1,14 +1,60 @@
services: services:
server:
image: rogueserver:dev
restart: unless-stopped
environment:
debug: true
dbaddr: db
dbuser: pokerogue
dbpass: pokerogue
dbname: pokeroguedb
gameurl: http://localhost:8000
callbackurl: http://localhost:8001
# Uncomment these to use AWS S3 for storage in development
# AWS_ACCESS_KEY_ID: <access>
# AWS_SECRET_ACCESS_KEY: <secret>
# AWS_REGION: <region>
# AWS_ENDPOINT_URL_S3: <endpoint>
depends_on:
db: db:
image: mariadb:11 condition: service_healthy
container_name: pokerogue-db-local networks:
restart: on-failure - internal
ports:
- "8001:8001"
db:
image: docker.io/library/mariadb:11
restart: unless-stopped
healthcheck:
test:
[
"CMD",
"healthcheck.sh",
"--su-mysql",
"--connect",
"--innodb_initialized",
]
start_period: 10s
start_interval: 10s
interval: 1m
timeout: 5s
retries: 3
environment: environment:
MYSQL_ROOT_PASSWORD: admin MYSQL_ROOT_PASSWORD: admin
MYSQL_DATABASE: pokeroguedb MYSQL_DATABASE: pokeroguedb
MYSQL_USER: pokerogue MYSQL_USER: pokerogue
MYSQL_PASSWORD: pokerogue MYSQL_PASSWORD: pokerogue
volumes:
- database:/var/lib/mysql
networks:
- internal
ports: ports:
- "3306:3306" - "3306:3306"
volumes:
- ./.data/db:/var/lib/mysql volumes:
database:
networks:
internal:

View File

@ -10,10 +10,11 @@ services:
dbname: pokeroguedb dbname: pokeroguedb
gameurl: http://localhost:8000 gameurl: http://localhost:8000
callbackurl: http://localhost:8001 callbackurl: http://localhost:8001
AWS_ACCESS_KEY_ID: <access> # Uncomment these to use AWS S3, which is what is used in our production environment
AWS_SECRET_ACCESS_KEY: <secret> # AWS_ACCESS_KEY_ID: <access>
AWS_REGION: <region> # AWS_SECRET_ACCESS_KEY: <secret>
AWS_ENDPOINT_URL_S3: <endpoint> # AWS_REGION: <region>
# AWS_ENDPOINT_URL_S3: <endpoint>
depends_on: depends_on:
db: db: