Distribution des bases : script de release, et les 2 tables du Siege
Le depot fournissait deja des schemas auth et characters vierges, mais pas les bases de contenu : personne ne pouvait monter une copie conforme du royaume. Elles ne peuvent pas vivre dans l historique git (dc_world pese 880 Mo, ~79 Mo gzippe, et GitHub refuse au-dela de 100 Mo par fichier) : le canal correct est l asset de Release, celui qu utilise deja l amont. sylvania/scripts/db-release-github.sh dumpe dc_world et dc_hotfixes en clair, calcule les empreintes et depose le tout en Release BROUILLON, a relire avant publication. Deux precautions apres verification des dumps reels : - MariaDB 11.4 ecrit ses tables en utf8mb4_uca1400_ai_ci, collation inconnue de MySQL 8 : un import s y arretait sur "Unknown collation". Le script la reecrit en utf8mb4_unicode_ci, reconnue des deux moteurs et de meme semantique, et refuse de produire un dump ou il en resterait. - Les tables de travail bak_* et tmp_* laissees par d anciennes maintenances (7 tables) sont exclues : ce n est pas du contenu. Test de restauration complet passe : 248 tables, updates a 332 lignes (le core ne rejouera donc pas sql/updates/world), 110 483 creature_template et 29 013 quest_template, aucune erreur. Par ailleurs capital_siege_state et capital_siege_history n existaient que dans sql/sylvania/capital_siege.sql, hors du mecanisme de mise a jour : une installation neuve avait un schema characters incomplet et le module ecrivait dans des tables absentes. Le patch est repris tel quel en fichier d update. Enfin, les prerequis annoncaient MySQL 8.0 alors que le serveur tourne sous MariaDB 11.4. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -53,7 +53,7 @@ Au-delà du core amont, le royaume apporte ses propres systèmes :
|
||||
|
||||
- **CMake 3.31+**
|
||||
- **Boost 1.84.0**
|
||||
- **MySQL 8.0**
|
||||
- **MySQL 8.0** ou **MariaDB 10.6+** (le royaume tourne sur MariaDB 11.4)
|
||||
- **OpenSSL 3.x**
|
||||
- **GCC / Clang / MSVC** (Visual Studio 2022 recommandé)
|
||||
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
--
|
||||
-- Siege des Capitales : les deux tables d etat vivent dans la base
|
||||
-- characters, mais n existaient que dans sql/sylvania/capital_siege.sql,
|
||||
-- hors du mecanisme de mise a jour automatique. Une installation neuve se
|
||||
-- retrouvait donc avec un schema characters incomplet : le module ecrivait
|
||||
-- dans des tables absentes.
|
||||
--
|
||||
-- Ce fichier reprend le patch a l identique. Il est idempotent
|
||||
-- (CREATE TABLE IF NOT EXISTS + INSERT IGNORE) : sans effet sur une base ou
|
||||
-- le patch a deja ete passe a la main.
|
||||
--
|
||||
|
||||
--
|
||||
-- SylvaniaCore - Module "Siege des Capitales"
|
||||
-- Base : dc_characters (etat mutable ecrit par le worldserver, donc hors de la
|
||||
-- base de contenu dc_world qui est reimportee a chaque mise a jour).
|
||||
--
|
||||
-- Deux tables :
|
||||
-- capital_siege_state : ligne unique, l ordonnancement du module. Elle porte
|
||||
-- le verrou anti-rejeu quotidien et l alternance de
|
||||
-- faction, qui doivent survivre a un redemarrage.
|
||||
-- capital_siege_history : une ligne par evenement, ouverte au declenchement et
|
||||
-- refermee a la fin (ou au demarrage suivant du core
|
||||
-- si le serveur s est arrete en plein siege).
|
||||
--
|
||||
-- Toutes les ecritures passent par des requetes preparees declarees dans
|
||||
-- src/server/database/Database/Implementation/CharacterDatabase.{h,cpp}.
|
||||
--
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Etat de l ordonnanceur (une seule ligne, id = 1)
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS `capital_siege_state` (
|
||||
`id` TINYINT(3) UNSIGNED NOT NULL DEFAULT 1
|
||||
COMMENT 'Toujours 1 : la table ne contient qu une ligne',
|
||||
`last_event_day` INT(10) UNSIGNED NOT NULL DEFAULT 0
|
||||
COMMENT 'Jour serveur (epoch local / 86400) du dernier evenement consomme. Verrou anti-rejeu quotidien',
|
||||
`last_attacker_team` TINYINT(4) NOT NULL DEFAULT -1
|
||||
COMMENT 'Derniere faction attaquante : 0 = Alliance, 1 = Horde, -1 = aucune. Sert a l alternance stricte',
|
||||
`scheduled_day` INT(10) UNSIGNED NOT NULL DEFAULT 0
|
||||
COMMENT 'Jour serveur du tirage courant',
|
||||
`scheduled_time` INT(10) UNSIGNED NOT NULL DEFAULT 0
|
||||
COMMENT 'Horodatage unix du declenchement tire pour scheduled_day',
|
||||
`scheduled_team` TINYINT(4) NOT NULL DEFAULT -1
|
||||
COMMENT 'Faction attaquante tiree pour scheduled_day : 0 = Alliance, 1 = Horde, -1 = aucune',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci
|
||||
COMMENT='Siege des Capitales : ordonnancement persistant';
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Historique des evenements
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS `capital_siege_history` (
|
||||
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`start_time` INT(10) UNSIGNED NOT NULL DEFAULT 0
|
||||
COMMENT 'Horodatage unix du declenchement',
|
||||
`end_time` INT(10) UNSIGNED NOT NULL DEFAULT 0
|
||||
COMMENT 'Horodatage unix de la fin, 0 tant que l evenement est en cours',
|
||||
`attacker_team` TINYINT(4) NOT NULL DEFAULT -1
|
||||
COMMENT '0 = Alliance, 1 = Horde',
|
||||
`target_map` SMALLINT(5) UNSIGNED NOT NULL DEFAULT 0
|
||||
COMMENT 'Carte de la capitale assaillie (0 = Hurlevent, 1 = Orgrimmar)',
|
||||
`boss_entry` INT(10) UNSIGNED NOT NULL DEFAULT 0
|
||||
COMMENT 'creature_template du dirigeant vise',
|
||||
`outcome` TINYINT(4) NOT NULL DEFAULT 0
|
||||
COMMENT '0 = en cours, 1 = victoire, 2 = temps ecoule, 3 = annule GM, 4 = arret d urgence (charge), 5 = interrompu (arret du serveur)',
|
||||
`duration` INT(10) UNSIGNED NOT NULL DEFAULT 0
|
||||
COMMENT 'Duree effective en secondes',
|
||||
`bots_spawned` SMALLINT(5) UNSIGNED NOT NULL DEFAULT 0
|
||||
COMMENT 'Nombre de bots effectivement deployes',
|
||||
`bots_lost` SMALLINT(5) UNSIGNED NOT NULL DEFAULT 0
|
||||
COMMENT 'Nombre de bots tues pendant l assaut',
|
||||
`triggered_by` VARCHAR(32) NOT NULL DEFAULT 'auto'
|
||||
COMMENT 'auto = ordonnanceur, sinon nom du GM declencheur',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_outcome` (`outcome`),
|
||||
KEY `idx_start_time` (`start_time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci
|
||||
COMMENT='Siege des Capitales : historique des evenements';
|
||||
|
||||
-- Ligne d etat initiale. Aucune faction n a encore attaque : le premier
|
||||
-- evenement sera donc mene par l Alliance.
|
||||
INSERT IGNORE INTO `capital_siege_state`
|
||||
(`id`, `last_event_day`, `last_attacker_team`, `scheduled_day`, `scheduled_time`, `scheduled_team`)
|
||||
VALUES (1, 0, -1, 0, 0, -1);
|
||||
Executable
+189
@@ -0,0 +1,189 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Publie les bases de contenu du royaume (dc_world + dc_hotfixes) comme assets
|
||||
# d une Release GitHub sur BlaMacfly/SylvaniaCore.
|
||||
#
|
||||
# Pourquoi une Release et pas le depot : dc_world pese ~880 Mo en base (~78 Mo
|
||||
# une fois dumpe et gzippe) et dc_hotfixes ~126 Mo. Git ne sait pas differencier
|
||||
# une archive gzip : chaque rafraichissement alourdirait l historique de ~80 Mo
|
||||
# a jamais, et GitHub refuse tout fichier de plus de 100 Mo. Les assets de
|
||||
# Release, eux, vivent hors de l historique et montent a 2 Go piece.
|
||||
#
|
||||
# Contrairement a ~/scripts/db-backup-world.sh (sauvegarde chiffree, depot
|
||||
# prive), ce script produit des dumps EN CLAIR destines a etre publics. Il ne
|
||||
# touche jamais a dc_characters ni a dc_auth : ces bases contiennent des donnees
|
||||
# de comptes et de personnages, et leurs schemas vierges sont deja fournis dans
|
||||
# sql/base/ du depot.
|
||||
#
|
||||
# Prerequis : un jeton GitHub a portee fine (Contents: Read and write sur le
|
||||
# seul depot SylvaniaCore) depose dans ~/.config/sylvania-github-token, en 600.
|
||||
#
|
||||
# Usage :
|
||||
# db-release-github.sh --dry-run # dumpe et verifie, ne publie rien
|
||||
# db-release-github.sh # dumpe et publie la Release
|
||||
# db-release-github.sh --tag DB-SYLVANIA-20260901
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
REPO_SLUG="${SYLVANIA_REPO_SLUG:-BlaMacfly/SylvaniaCore}"
|
||||
TOKEN_FILE="${SYLVANIA_GH_TOKEN_FILE:-$HOME/.config/sylvania-github-token}"
|
||||
WORKDIR="${SYLVANIA_RELEASE_WORKDIR:-$HOME/db-release}"
|
||||
MIN_FREE_MB=2048
|
||||
|
||||
DATE="$(date '+%Y%m%d')"
|
||||
TAG="DB-SYLVANIA-${DATE}"
|
||||
DRY_RUN=0
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--dry-run) DRY_RUN=1; shift ;;
|
||||
--tag) TAG="${2:?--tag attend une valeur}"; shift 2 ;;
|
||||
-h|--help) sed -n '2,24p' "$0"; exit 0 ;;
|
||||
*) echo "Option inconnue : $1" >&2; exit 2 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
die() { echo "ERREUR: $*" >&2; exit 1; }
|
||||
|
||||
# --- Verifications preliminaires ---------------------------------------------
|
||||
command -v mysqldump >/dev/null || die "mysqldump introuvable"
|
||||
command -v curl >/dev/null || die "curl introuvable"
|
||||
command -v gzip >/dev/null || die "gzip introuvable"
|
||||
|
||||
mkdir -p "$WORKDIR"
|
||||
free_mb=$(df -Pm "$WORKDIR" | awk 'NR==2 {print $4}')
|
||||
[ "$free_mb" -ge "$MIN_FREE_MB" ] || die "espace disque insuffisant sur $WORKDIR : ${free_mb} Mo libres, ${MIN_FREE_MB} Mo requis"
|
||||
|
||||
if [ "$DRY_RUN" -eq 0 ]; then
|
||||
[ -s "$TOKEN_FILE" ] || die "jeton GitHub absent : $TOKEN_FILE (voir l en-tete de ce script)"
|
||||
perms=$(stat -c '%a' "$TOKEN_FILE")
|
||||
[ "$perms" = "600" ] || die "$TOKEN_FILE doit etre en 600 (actuellement $perms)"
|
||||
fi
|
||||
|
||||
# --- Dumps --------------------------------------------------------------------
|
||||
# Flags alignes sur ~/scripts/db-backup-world.sh, deja eprouves sur le serveur
|
||||
# en production. Les tables `updates` et `updates_include` sont volontairement
|
||||
# conservees : elles portent l historique deja applique, ce qui evite au core de
|
||||
# rejouer les ~330 fichiers de sql/updates/world sur une base qui les contient
|
||||
# deja.
|
||||
declare -A DUMPS=( [world]=dc_world [hotfixes]=dc_hotfixes )
|
||||
ASSETS=()
|
||||
|
||||
for name in world hotfixes; do
|
||||
src="${DUMPS[$name]}"
|
||||
out="${WORKDIR}/sylvania_${name}_${DATE}.sql.gz"
|
||||
echo "==> dump ${src} -> $(basename "$out")"
|
||||
|
||||
# Les tables de travail laissees par d anciennes maintenances (bak_*, tmp_*)
|
||||
# ne sont pas du contenu : inutile de les publier.
|
||||
ignore=()
|
||||
while IFS= read -r t; do
|
||||
[ -n "$t" ] && ignore+=( "--ignore-table=${src}.${t}" )
|
||||
done < <(sudo mysql -N -B -e "select table_name from information_schema.tables \
|
||||
where table_schema='${src}' \
|
||||
and (table_name like 'bak\\_%' or table_name like 'tmp\\_%');" 2>/dev/null)
|
||||
[ ${#ignore[@]} -gt 0 ] && echo " ${#ignore[@]} table(s) de travail exclue(s)"
|
||||
|
||||
# Portabilite MySQL : le serveur tourne sous MariaDB 11.4, dont la collation
|
||||
# par defaut (utf8mb4_uca1400_*) n existe pas sous MySQL 8 -- un import s y
|
||||
# arreterait sur "Unknown collation". utf8mb4_unicode_ci est reconnue par les
|
||||
# deux moteurs et partage la meme semantique (UCA, insensible a la casse et
|
||||
# aux accents).
|
||||
if ! sudo mysqldump --single-transaction --quick --no-tablespaces \
|
||||
${ignore[@]+"${ignore[@]}"} "$src" \
|
||||
| sed -E 's/utf8mb4_uca1400_[a-z_]+/utf8mb4_unicode_ci/g' \
|
||||
| gzip -c > "$out"; then
|
||||
rm -f "$out"; die "le dump de ${src} a echoue"
|
||||
fi
|
||||
[ -s "$out" ] || die "dump vide pour ${src}"
|
||||
# Un dump tronque (mysqldump interrompu) ne porte pas sa ligne de cloture.
|
||||
if ! gzip -dc "$out" | tail -5 | grep -q "Dump completed"; then
|
||||
rm -f "$out"; die "dump de ${src} tronque : ligne de cloture absente"
|
||||
fi
|
||||
if gzip -dc "$out" | grep -q "uca1400"; then
|
||||
rm -f "$out"; die "collation MariaDB residuelle dans le dump de ${src}"
|
||||
fi
|
||||
ASSETS+=("$out")
|
||||
echo " $(du -h "$out" | cut -f1)"
|
||||
done
|
||||
|
||||
# --- Empreintes ---------------------------------------------------------------
|
||||
SUMS="${WORKDIR}/SHA256SUMS-${DATE}.txt"
|
||||
( cd "$WORKDIR" && sha256sum "$(basename "${ASSETS[0]}")" "$(basename "${ASSETS[1]}")" ) > "$SUMS"
|
||||
ASSETS+=("$SUMS")
|
||||
cat "$SUMS"
|
||||
|
||||
# --- Corps de la Release ------------------------------------------------------
|
||||
BODY_FILE="${WORKDIR}/body-${DATE}.md"
|
||||
cat > "$BODY_FILE" <<BODYEOF
|
||||
Bases de contenu du royaume **La Legion de Sylvania**, en date du ${DATE}.
|
||||
|
||||
Ce sont les bases \`world\` et \`hotfixes\` telles qu elles tournent en production :
|
||||
la base amont DestinyCore augmentee de tous les correctifs de contenu du royaume
|
||||
(campagnes, donjons, butin, localisation frFR, modules Mercenaires et Siege des
|
||||
Capitales). Elles remplacent la release DB amont si vous voulez une copie
|
||||
conforme du royaume plutot qu une installation DestinyCore de base.
|
||||
|
||||
Les bases \`auth\` et \`characters\` ne sont pas publiees : elles contiennent des
|
||||
comptes et des personnages. Leurs schemas vierges sont dans \`sql/base/\` du depot.
|
||||
|
||||
### Import
|
||||
|
||||
\`\`\`bash
|
||||
gunzip -c sylvania_world_${DATE}.sql.gz | mysql -u trinity -p world
|
||||
gunzip -c sylvania_hotfixes_${DATE}.sql.gz | mysql -u trinity -p hotfixes
|
||||
\`\`\`
|
||||
|
||||
Ces dumps ne contiennent ni \`CREATE DATABASE\` ni \`USE\` : creez les bases
|
||||
d abord (\`sql/create/create_mysql.sql\`) et choisissez librement leurs noms.
|
||||
|
||||
La table \`updates\` est incluse et deja renseignee : le worldserver n aura donc
|
||||
pas a rejouer les fichiers de \`sql/updates/world\`. Laissez malgre tout
|
||||
\`Updates.EnableDatabases = 31\` et \`Updates.AutoSetup = 1\` pour que les
|
||||
mises a jour ulterieures s appliquent seules.
|
||||
|
||||
Verifiez les archives avec \`sha256sum -c SHA256SUMS-${DATE}.txt\`.
|
||||
BODYEOF
|
||||
|
||||
if [ "$DRY_RUN" -eq 1 ]; then
|
||||
echo
|
||||
echo "--- MODE --dry-run : rien n a ete publie ---"
|
||||
echo "Assets prets dans ${WORKDIR} :"
|
||||
printf ' %s\n' "${ASSETS[@]}"
|
||||
echo "Tag qui serait cree : ${TAG}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- Publication --------------------------------------------------------------
|
||||
TOKEN="$(cat "$TOKEN_FILE")"
|
||||
API="https://api.github.com/repos/${REPO_SLUG}"
|
||||
UPLOAD="https://uploads.github.com/repos/${REPO_SLUG}"
|
||||
auth=(-H "Authorization: Bearer ${TOKEN}" -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28")
|
||||
|
||||
existing=$(curl -sf "${auth[@]}" "${API}/releases/tags/${TAG}" | sed -n 's/.*"id": \([0-9]*\).*/\1/p' | head -1 || true)
|
||||
[ -n "$existing" ] && die "la release ${TAG} existe deja (id ${existing}) : supprimez-la ou passez --tag"
|
||||
|
||||
echo "==> creation de la release ${TAG}"
|
||||
payload=$(python3 - "$TAG" "$BODY_FILE" <<'PYEOF'
|
||||
import json, sys, io
|
||||
tag = sys.argv[1]
|
||||
body = io.open(sys.argv[2], encoding="utf-8").read()
|
||||
print(json.dumps({"tag_name": tag, "name": "Bases Sylvania " + tag.split("-")[-1],
|
||||
"body": body, "draft": True, "prerelease": False}))
|
||||
PYEOF
|
||||
)
|
||||
release_id=$(curl -sf "${auth[@]}" -X POST "${API}/releases" -d "$payload" \
|
||||
| sed -n 's/.*"id": \([0-9]*\).*/\1/p' | head -1)
|
||||
[ -n "$release_id" ] || die "creation de la release impossible"
|
||||
|
||||
for a in "${ASSETS[@]}"; do
|
||||
echo "==> envoi de $(basename "$a")"
|
||||
curl -sf "${auth[@]}" -H "Content-Type: application/octet-stream" \
|
||||
--data-binary @"$a" \
|
||||
"${UPLOAD}/releases/${release_id}/assets?name=$(basename "$a")" >/dev/null \
|
||||
|| die "envoi de $(basename "$a") echoue"
|
||||
done
|
||||
|
||||
echo
|
||||
echo "Release ${TAG} creee en BROUILLON : https://github.com/${REPO_SLUG}/releases"
|
||||
echo "Relisez-la puis publiez-la depuis l interface GitHub."
|
||||
Reference in New Issue
Block a user