feat: add auto furniture interaction detection
- New auto-interaction.ts: detects canSit/canLay/canStand from classname/name keywords - Maps keywords to interaction types (bench, chair, bed, table, etc.) - Returns clickLimit and interactionModesCount for proper click/interaction limits - Nitro editor: added auto-detect button with preview of detected settings - furni-import.ts: auto-sets interaction_modes_count during import - upload-import.ts: auto-detects for direct insert and SQL migrations - clone-import.ts: auto-detects when cloning from other hotels
This commit is contained in:
1 parent
0b4fc4559e
commit
dee843106f
8 files changed
+596
-25
No files matched your search
+99
-9
@@ -131,6 +131,13 @@ CONFIG_BACKUP_DIR="${SCRIPT_DIR}/storage/config-backups"
|
||||
mkdir -p "$CONFIG_BACKUP_DIR" 2>/dev/null || true
|
||||
mkdir -p "$BACKUP_DIR" 2>/dev/null || true
|
||||
NITRO_LANG="${NITRO_LANG:-en}"
|
||||
# Nginx site config(s) that serve /gamedata/. After every build/rebuild the
|
||||
# update script (re)adds an exact-match redirect so /gamedata/ points at
|
||||
# /gamedata/config/ instead of the raw directory listing.
|
||||
NGINX_SITE_CONFS=(
|
||||
"${NITRO_NGINX_SITE_CONF:-/etc/nginx/sites-enabled/cms.conf}"
|
||||
"${NITRO_NGINX_SITE_CONF_AVAILABLE:-/etc/nginx/sites-available/cms.conf}"
|
||||
)
|
||||
|
||||
MYSQL_CRED="-h $DB_HOST -P $DB_PORT -u $DB_USER --ssl-verify-server-cert=${NITRO_SSL_VERIFY}"
|
||||
[ -n "$DB_PASS" ] && MYSQL_CRED="$MYSQL_CRED --password=$DB_PASS"
|
||||
@@ -971,24 +978,53 @@ git_revert_repo() {
|
||||
rm -f "$PARALLEL_STATE_DIR/oldhead-$name" 2>/dev/null || true
|
||||
}
|
||||
|
||||
# Run a yarn command inside a repo that pins an unavailable Yarn Berry version.
|
||||
# Upstream package.json now declares e.g. "packageManager": "[email protected]",
|
||||
# which the system Yarn 1 refuses to run ("current global version is 1.22.22")
|
||||
# and which corepack cannot fetch (yarn 4 is not published on the registry).
|
||||
# Drop the field for the duration of the command, then restore the pristine
|
||||
# file so the repo stays clean for the next git pull. Runs inside the repo and
|
||||
# always returns the caller to SCRIPT_DIR so cwd never leaks between repos.
|
||||
yarn_run() {
|
||||
local repo="$1"; shift
|
||||
cd "$repo" 2>/dev/null || { warn "Cannot cd into %s" "$repo"; return 1; }
|
||||
local modified=false
|
||||
if python3 -c "
|
||||
import json, sys
|
||||
p = 'package.json'
|
||||
d = json.load(open(p))
|
||||
pm = d.get('packageManager', '')
|
||||
if pm.startswith('yarn@') and not pm.startswith('yarn@1.'):
|
||||
d.pop('packageManager', None)
|
||||
json.dump(d, open(p, 'w'), indent=2)
|
||||
open(p, 'a').write(chr(10))
|
||||
sys.exit(0)
|
||||
sys.exit(1)
|
||||
" 2>/dev/null; then
|
||||
modified=true
|
||||
fi
|
||||
yarn "$@"
|
||||
local rc=$?
|
||||
if [ "$modified" = true ]; then
|
||||
git checkout -- package.json 2>/dev/null || true
|
||||
fi
|
||||
cd "$SCRIPT_DIR" 2>/dev/null || true
|
||||
return $rc
|
||||
}
|
||||
|
||||
# yarn install scoped to a per-repo cache folder. Parallel installs (renderer +
|
||||
# client) must never share a cache — yarn 1 corrupts the shared cache, leaving
|
||||
# node_modules incomplete (vite/pixi.js missing) while still exiting 0.
|
||||
# $1 = repo dir; remaining args forwarded to yarn. Runs inside the repo and
|
||||
# always returns the caller to SCRIPT_DIR so cwd never leaks between repos.
|
||||
# $1 = repo dir; remaining args forwarded to yarn.
|
||||
yarn_install_repo() {
|
||||
local repo="$1"; shift
|
||||
local cache_dir="$YARN_CACHE_DIR/$(basename "$repo")"
|
||||
mkdir -p "$cache_dir" 2>/dev/null || true
|
||||
cd "$repo" 2>/dev/null || { warn "Cannot cd into %s" "$repo"; return 1; }
|
||||
# NODE_ENV may be exported as "production" via .env (the CMS runs in prod),
|
||||
# which makes yarn 1 skip devDependencies — vite is a devDep, so builds
|
||||
# would fail with "vite: not found". Force a non-production env so the full
|
||||
# dependency tree (including dev deps) is always installed.
|
||||
NODE_ENV=development yarn install --cache-folder "$cache_dir" "$@" >> "$LOG_FILE" 2>&1
|
||||
local rc=$?
|
||||
cd "$SCRIPT_DIR" 2>/dev/null || true
|
||||
return $rc
|
||||
NODE_ENV=development yarn_run "$repo" install --cache-folder "$cache_dir" "$@" >> "$LOG_FILE" 2>&1
|
||||
}
|
||||
|
||||
# Nuke a repo's own yarn cache and node_modules for a truly clean reinstall.
|
||||
@@ -1314,7 +1350,7 @@ update_client() {
|
||||
fi
|
||||
spinner_stop ok
|
||||
spinner_start "Building frontend..."
|
||||
if yarn build >> "$LOG_FILE" 2>&1; then
|
||||
if yarn_run "$NITRO_CLIENT" build >> "$LOG_FILE" 2>&1; then
|
||||
spinner_stop ok
|
||||
else
|
||||
spinner_stop fail
|
||||
@@ -1511,8 +1547,62 @@ flyaway_repair_db() {
|
||||
return 1
|
||||
}
|
||||
|
||||
# After a build/rebuild, ensure nginx redirects /gamedata/ (and /gamedata)
|
||||
# to /gamedata/config/ instead of serving the raw directory listing.
|
||||
# Idempotent: injects exact-match location blocks in front of the /gamedata/
|
||||
# prefix block, validates with `nginx -t` (restoring the pre-edit copy on
|
||||
# failure) and keeps a timestamped backup. The actual reload happens at the
|
||||
# end of do_restart.
|
||||
ensure_gamedata_redirect() {
|
||||
local root_cmd=""
|
||||
[ "$(id -u)" -eq 0 ] || root_cmd="sudo -n"
|
||||
local changed=false
|
||||
local conf tmp snippet bak
|
||||
for conf in "${NGINX_SITE_CONFS[@]}"; do
|
||||
[ -f "$conf" ] || continue
|
||||
if grep -qs "location = /gamedata" "$conf" 2>/dev/null; then
|
||||
ok "Gamedata redirect already present in %s" "$(basename "$conf")"
|
||||
continue
|
||||
fi
|
||||
tmp=$(mktemp)
|
||||
snippet=" # Redirect /gamedata/ to /gamedata/config/
|
||||
location = /gamedata { return 301 /gamedata/config/; }
|
||||
location = /gamedata/ { return 301 /gamedata/config/; }
|
||||
"
|
||||
awk -v s="$snippet" '
|
||||
/^[[:space:]]*location \/gamedata\/ \{/ && !done {
|
||||
printf "%s", s
|
||||
done = 1
|
||||
}
|
||||
{ print }
|
||||
' "$conf" > "$tmp" 2>/dev/null
|
||||
if [ ! -s "$tmp" ] || ! grep -qs "location = /gamedata" "$tmp" 2>/dev/null; then
|
||||
rm -f "$tmp" 2>/dev/null || true
|
||||
warn "Could not inject gamedata redirect into %s" "$conf"
|
||||
continue
|
||||
fi
|
||||
bak="$conf.bak-$(date +%s)"
|
||||
$root_cmd cp "$conf" "$bak" 2>/dev/null || { rm -f "$tmp"; warn "Cannot backup %s" "$conf"; continue; }
|
||||
if ! $root_cmd install -m 640 "$tmp" "$conf" 2>/dev/null; then
|
||||
rm -f "$tmp" 2>/dev/null || true
|
||||
warn "Cannot update %s" "$conf"
|
||||
continue
|
||||
fi
|
||||
rm -f "$tmp" 2>/dev/null || true
|
||||
if ! sudo nginx -t >/dev/null 2>&1; then
|
||||
$root_cmd cp "$bak" "$conf" 2>/dev/null || true
|
||||
warn "nginx -t failed — reverted gamedata redirect in %s" "$conf"
|
||||
continue
|
||||
fi
|
||||
changed=true
|
||||
ok "Added /gamedata/ → /gamedata/config/ redirect to %s" "$(basename "$conf")"
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
do_restart() {
|
||||
step 8 8 "Restart Services"
|
||||
ensure_gamedata_redirect
|
||||
if systemctl cat "$EMULATOR_SERVICE" &>/dev/null; then
|
||||
sudo systemctl restart "$EMULATOR_SERVICE" 2>/dev/null && ok "$EMULATOR_SERVICE restarted" || warn "Restart failed"
|
||||
if ! wait_for_emulator_health; then
|
||||
@@ -1916,7 +2006,7 @@ cmd_flyaway_repair() {
|
||||
step 6 7 "$(_t "Rebuild Frontend")"
|
||||
spinner_start "$(_t "Building frontend...")"
|
||||
cd "$NITRO_CLIENT"
|
||||
if yarn build >> "$LOG_FILE" 2>&1; then
|
||||
if yarn_run "$NITRO_CLIENT" build >> "$LOG_FILE" 2>&1; then
|
||||
spinner_stop ok
|
||||
ok "Frontend rebuilt"
|
||||
else
|
||||
|
||||
Reference in new issue
Block a user