The #182 merge resolution left buildScoutReport() defined but never called,
while the original inline scout-report block was kept at the call site — so
the method was dead code and the scout-report logic was duplicated.
This wires it up: the inline block in the `if (!empty($scout))` branch is
replaced by a single `$info_spy = $this->buildScoutReport(...)` call. The
method already exists and its body is identical to the removed inline block,
so behaviour is unchanged — this just removes the duplication and makes the
extraction actually take effect. Brace balance even (634/634).
Co-authored-by: TravianZ Patcher <patcher@localhost>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
The merge of #180 (applyBounty) and #181 (buildScoutReport) — both of which
inserted a new private method just before sendunitsComplete() — dropped the
closing brace of buildScoutReport(). As a result applyBounty() was declared
INSIDE buildScoutReport(), producing:
PHP Parse error: syntax error, unexpected token "private"
in GameEngine/Automation.php
This crashes Automation.php entirely (HTTP 500), so the whole game automation
stops: troop movements never resolve, buildings never finish, etc.
Fix: restore the missing `}` closing buildScoutReport() before the applyBounty()
docblock. Brace balance is now even again (634/634). One-character structural
fix, no logic change.
Co-authored-by: TravianZ Patcher <patcher@localhost>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Catalin Novgorodschi <cata7007@gmail.com>
Phase B — pure behaviour-preserving extraction (issue #155).
buildScoutReport(): extracts the scout-report (info_spy) HTML assembly
(~25 lines) into a helper returning the info_spy string. Handles both
spy modes: resources (spy=1) and defence/buildings (spy=2). The block's
body is moved verbatim (multi-line strings with their exact embedded
whitespace preserved). The reassigned $walllevel/$residencelevel/
$palacelevel were local to this block and never read downstream. No
logic change.
Co-authored-by: TravianZ Patcher <patcher@localhost>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Catalin Novgorodschi <cata7007@gmail.com>
The profile already had a language selector (Templates/Profile/preference.tpl)
that saved the choice into users.lang and $_SESSION['lang'], but the saved
preference was never used to actually load the language: every page loads
include("Lang/".LANG.".php") with the server-wide LANG constant, so changing
the language in the profile had no visible effect.
This wires it up:
- Introduce SERVER_LANG (the server default) and make LANG the EFFECTIVE
display language, resolved from the player's saved preference
($_SESSION['lang']) with a fallback to SERVER_LANG
(install/data/constant_format.tpl).
SECURITY: the value is sanitized to [a-z_] and the target Lang/<x>.php
file must exist, otherwise we fall back to the server default. This
prevents Local File Inclusion via include("Lang/".LANG.".php").
- Seed $_SESSION['lang'] from users.lang on login (GameEngine/Session.php,
PopulateVar), so the chosen language applies right after logging in.
- Keep the SERVER default intact when an admin saves settings: the admin
config regenerators and the "Server Settings"/config displays now use
SERVER_LANG (the server default) instead of the per-user LANG, so an
admin browsing in their own language can't accidentally overwrite the
server default (6 Admin/Mods/edit*.php + editServerSet.tpl + config.tpl).
Note: existing installs must also add SERVER_LANG + the LANG resolution to
their generated GameEngine/config.php (and the Admin/Mods/constant_format.tpl
copy) since config is generated at install time.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The admin panel had a "Create System Message" page (admin.php?p=sysmessage
-> Admin/Templates/sysmessage.tpl) whose form posts to
GameEngine/Admin/Mods/sysmessage.php, but that backend file never existed,
so submitting returned a 404 (Not Found).
Add the handler implementing the prepare -> confirm -> execute flow used by
the template. On execute it displays a global system message to all players
using the existing mechanism (writes Templates/text.tpl from
text_format.tpl and sets users.ok = 1), same as the legacy sysmsg.php.
%TEKST% is escaped for the PHP double-quoted string context to avoid
breakage/injection.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The timezone lists are hardcoded. Add "Europe (Switzerland)" =
Europe/Zurich to:
- Admin/Templates/editServerSet.tpl (admin: edit server settings)
- install/templates/config.tpl (install wizard, index 14)
- install/index.php (install wizard tz index->name mapping, case 14)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The language dropdowns are hardcoded (they don't scan GameEngine/Lang/),
so the existing fr.php never appeared. Add a French option to:
- install/templates/config.tpl (install wizard)
- Admin/Templates/editServerSet.tpl (admin: edit server settings)
- Admin/Templates/config.tpl (admin: server config display)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace GameEngine/Lang/fr.php with a complete, reviewed French
translation:
- Full coverage: all 1439 language keys present (matches en.php), none
missing or extra.
- Valid PHP: all French apostrophes properly escaped, no unterminated
strings.
- Months localized, quest tutorial numbering kept consistent with en.php.
- Fixed gender agreement on EMAIL_TAKEN ("Cet e-mail ... utilisé").
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Addresses the five bugs found on master (6e139a1b) during a fresh
Docker install and admin testing:
1. Missing `details` column in gold_fin_log (HTTP 500 on finishing
construction with gold, buying Gold Club, admin giving gold):
- Add `details varchar(255)` to the gold_fin_log schema, matching
every INSERT and the a2b2.php reader that already use it.
- Fix the broken positional INSERT in Logging::goldFinLog() (it sent
3 values for a 7-column table) which 500'd on the same gold path.
2. Admin "View Player Info" fatal error: `<? php` -> `<?php` in
Admin/Templates/playerinfo.tpl.
3. "Reset Server" leaving the DB corrupted (Duplicate key name
'idx_ft_bonus_xy'): move the croppers indexes inline into the
CREATE TABLE IF NOT EXISTS so structure recreation is idempotent,
and add `croppers` to the reset truncate list.
4. Install wizard crash on failed DB connection (mysqli_error(false)):
use mysqli_connect_error() and show a friendly, actionable message
(incl. the Docker "db" hostname hint).
5. PHP exposing errors/stack traces to end users: ship a production
php.ini baseline + docker/php/zz-travianz.ini that turns off
display_errors and logs to stderr instead.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>