.NET Rewrite
📅 Updated 2026-05-16 (rev 18)--run-now flags--geoip)
act_map, map_started, map_changeshlstats_Trend)lastAddress written on disconnect (for nightly GeoIP batch)| Perl Sub | .NET Handler | DB Tables Written | Status |
|---|---|---|---|
doEvent_Connect | ConnectHandler | Events_Connects, PlayerUniqueIds, Players, PlayerNames, Livestats | ✅ Done |
doEvent_EnterGame | EnterGameHandler | Events_Entries | ✅ Done |
doEvent_Disconnect | DisconnectHandler | Events_Disconnects, Players, PlayerNames, Livestats (delete) | ✅ Done |
doEvent_Clan | ClanService (via connect/name-change) | Clans, Players.clan | ✅ Done |
doEvent_Frag | FragHandler | Events_Frags, Weapons, Maps_Counts | ✅ Done |
doEvent_Teamkill | FragHandler (TK branch) | Events_Teamkills | ✅ Done |
doEvent_Suicide | SuicideHandler | Events_Suicides | ✅ Done |
doEvent_TeamSelection | ChangeTeamHandler | Events_ChangeTeam | ✅ Done |
doEvent_RoleSelection | ChangeRoleHandler | Events_ChangeRole, Roles | ✅ Done |
doEvent_ChangeName | ChangeNameHandler | PlayerNames, clan re-match | ✅ Done |
doEvent_Chat | ChatHandler | Events_Chat | ✅ Done |
doEvent_PlayerAction | PlayerActionHandler | Events_PlayerActions, GameActions | ✅ Done |
doEvent_PlayerPlayerAction | PlayerPlayerActionHandler | Events_PlayerPlayerActions | ✅ Done |
doEvent_TeamAction | TeamBonusHandler | Events_PlayerActions (per team member) | ✅ Done |
doEvent_WorldAction | EventRouter (inline) | GameActions, Events_PlayerActions | ✅ Done |
doEvent_ChangeMap | MapChangeHandler | Servers (act_map, map_started, map_changes) | ✅ Done |
doEvent_Statsme | StatsmeHandler | Events_Statsme, Weapons | ✅ Done |
doEvent_Rcon | — | Events_Rcon | ❌ Deferred |
doEvent_Admin | — | Events_Admin | ❌ Deferred |
doEvent_Statsme2 | — | Events_Statsme2 | ❌ Deferred |
doEvent_Statsme_Latency | — | Events_Latency | ❌ Deferred |
doEvent_Statsme_Time | — | Events_StatsmeTime | ❌ Deferred |
| Feature | PHP Reference | Gap / Notes | Completeness |
|---|---|---|---|
| In-Game Pages — All 19 Pages | ingame/ (21 files) | 🆕 NEW. InGameController + 19 views at /ingame/*. Lightweight no-chrome HTML for Half-Life in-game MOTD browser: motd (top players/clans), players, clans, claninfo, statsme, kills, weapons, accuracy, targets, maps, servers, status, bans, help, weaponinfo, mapinfo, actions, actioninfo, load. footer.php + header.php are layout partials handled by _InGameLayout.cshtml. | 90% |
| Livestats Standalone Page | livestats.php | Full PHP parity: live players table, team footer with round wins (MapCtWins/MapTsWins from Server entity), auto-refresh, dedicated URL for in-game MOTD iframe integration. No gaps. | 97% |
| Chat Log — Server Chat + Player History | chat.php, chathistory.php | Full PHP parity: Chat/Index: server chat log with server dropdown, text filter, sortable table, pagination, team/squad prefix. Chat/PlayerHistory: per-player chat history, "Last N Days" header qualifier (DeleteDays), text filter, sortable table, back-link. PHP chat.php has no top chatters section. | 98% |
| Player Bans | bans.php | Full PHP parity. All 10 columns: Player (flag + profile link), Ban Date, Skill Points, Activity bar graph, Kills, Deaths, Headshots, K:D, HS:K, Accuracy. Sortable, paginated, "Find a player" search form, minKills filter. | 95% |
| Player Leaderboard (total + period filters) | players.php | PHP has inline Autocompleter.js live search — omitted in .NET (Search page instead). Added last_skill_change trend indicator (▲/▼) next to Points matching PHP's skill_change=1 column attribute. | 97% |
| Player Profile — all tabs | playerinfo.php + sub-files | PHP profile header shows a rank-change arrow (rank movement since last visit). Per-server playtime history in General tab not confirmed in .NET. | 95% |
| Player Event History | playerhistory.php | All 16 event types: Connect, Disconnect, Entry, Kill, Kill (HS), Death, Team Kill, Friendly Fire, Suicide, Role, Team, Action, Action+, Action-, Team Bonus, Name Change. Sortable, paginated, "Last N Days" header. Previously missing TeamBonus and ChangeName events added. | 97% |
| Player Forum Signature PNG | sig.php | PHP reads per-game SigBackground option. .NET SkiaSharp mirrors this; minor gradient rendering differences. | 95% |
| Player Steam Avatar | Steam Web API | Steam API integration works. PHP falls back to default_avatar.jpg if unavailable; .NET fallback not verified. | 90% |
| Player Sessions Page | playersessions.php | Full 12-column parity: Date, Skill Change (▲/▼ coloured arrows), Points, Time (Xd HH:MM:SSh), Kills, Deaths, K:D, HS, HS:K, Suicides, TKs, Kill Streak. Sortable, paginated, DeleteDays footer, back link. | 95% |
| Player Awards History | playerawards.php | Full PHP parity: all columns, awardId drill-down mode (per-day occurrences), sort, pagination, back-link. No gaps. | 98% |
| Clan Leaderboard | clans.php | PHP includes inline Autocompleter.js clan search — omitted in .NET (Search page instead). Added AVG(last_skill_change) trend indicator (▲/▼) next to Avg. Points matching PHP's skill_change=1 column attribute. | 95% |
| Clan Profile — all tabs | claninfo.php + sub-files | No gaps identified — tag_style column does not exist in PHP source, DB schema, or live site output. | 95% |
| Weapon Leaderboard | weapons.php | Per-row weapon image in Weapon column; onerror tries .png then falls back to bold weapon name — matches PHP weaponimg fallback. No gaps identified. | 95% |
| Weapon Detail — Player Leaderboard | weaponinfo.php | Full PHP parity: player leaderboard (kills, headshots, HpK), weapon image, total kills/headshots with "Last N Days" qualifier, back link, sortable, paginated. | 95% |
| Map Leaderboard | maps.php | PHP shows a map screenshot thumbnail beside each row. .NET omits per-row map images on the list page. | 90% |
| Map Detail — Player Leaderboard + Heatmap | mapinfo.php | Full PHP parity: player leaderboard, overhead map image, "Last N Days" qualifier. Interactive Canvas heatmap (Kills/Deaths tabs + zoom/pan) exceeds PHP. Map download link absent (optional map_dlurl option). | 95% |
| Server List | servers.php | Added steam://connect/ join link per row matching PHP. Live server pinging (A2S_INFO) is deferred to daemon feature. DB-based status (act_players, IsActive flag) is updated in real-time by the daemon. | 93% |
| Server Detail — Historical Load Graphs | servers.php | 🆕 Upgraded to full parity. Live players table, daily awards, per-server load chart with 4 time ranges (24h / 1 Week / 1 Month / 1 Year). Range tab buttons AJAX-fetch /Servers/LoadChart and update Chart.js in-place. Down-sampling matches PHP show_graph.php avg_step constants. Status: 85% → 95%. | 95% |
| Game Dashboard — All Sections | game.php | Servers table, global stats header, aggregate trend chart, per-server load charts with 4 time ranges (24h/week/month/year), VoiceComm block (hlstats_Servers_VoiceComm), Leaflet player location map, Livestats live players, Daily Awards. Google Maps replaced with Leaflet/OSM — functionally equivalent. | 95% |
| Awards — Daily Awards | awards.php, awards_daily.php | Added daily awards date header ("Daily Awards (Monday 12 May)") from awards_d_date option matching PHP section title. Added award.png fallback when game-specific award image is missing. Column count (awarddailycols/awardglobalcols) not configurable — minor cosmetic gap. | 95% |
| Awards — Global Awards | awards_global.php | Award image fallback fixed. Column count from awardglobalcols option not configurable — minor cosmetic gap. | 95% |
| Awards — Ranks Listing | awards_ranks.php | Grid layout, player counts ("Achieved by N players"), links to RankDetail when players exist. Column count fixed (not driven by awardrankscols option). | 95% |
| Awards — Ribbons Listing | awards_ribbons.php | Ribbon Classes grouped by awardCount value, grid layout, player counts, links to RibbonDetail. Column count fixed (not driven by awardribbonscols option). | 95% |
| Rank Detail (Players at a Rank) | rankinfo.php | Paginated player table (flag, name, kills, skill), sortable columns, pagination, back-link to Awards. | 95% |
| Ribbon Detail — Player Leaderboard | ribboninfo.php | Full PHP parity: ribbon image/name header, award threshold filter (awardCount), paginated sortable player table (rank, flag, player link, daily-award count, award name), back-link to Awards. No gaps. | 97% |
| Daily Award Detail History | dailyawardinfo.php | Full PHP parity: award image (with onerror fallback), date, player with flag, verb-suffixed count, sort, pagination, back-link. No gaps. | 97% |
| Player Search | search.php | PHP shows live Autocompleter.js suggestions. .NET is plain form submission — functional parity, no real-time autocomplete. | 90% |
| Actions Leaderboard | actions.php | Total earned header, action/earned/reward table, sortable, paginated, back link. Full PHP parity. | 95% |
| Action Detail (Achievers + Victims) | actioninfo.php | Achievers table (PlayerActions or PlayerPlayerActions) + Victims table for PvP actions, both with DeleteDays, separate sortable+paginated controls. Minor: TeamBonuses fallback omitted (edge case). | 95% |
| Roles Leaderboard | roles.php | Role images, Picked/%/ratio (meter bar), Kills/%/ratio (meter bar), Deaths/%/ratio (meter bar), K:D. All sortable. Back link. Full PHP parity. | 95% |
| Role Detail (Player Kill List) | rolesinfo.php | Role image, total kills/headshots, "Last N Days", player kill table, sortable, paginated, back link. Full PHP parity. | 95% |
| Country Leaderboard | countryclans.php | Full PHP parity: all columns (Avg Points, Members, Activity bar, Connection Time, Kills, Deaths, K:D), minMembers filter, activity filter (stored ActivityScore ≥ 0 equivalent to PHP per-player threshold), sort, pagination. No gaps. | 95% |
| Country Profile (Member List) | countryclansinfo.php | Full PHP parity: country stats header, paginated member table (Rank + MmRank columns), Leaflet member location map (lat/lng from GeoIP) replaces PHP Google Maps embed. GetMemberLocationsAsync in ICountryRepository/ICountryService. | 95% |
| Multi-Game Landing Page / Game Selector | contents.php, gameslist.php | Full PHP parity: Home/GamesList.cshtml: game cards (icon, name, players, top player/clan links), general stats (players/clans/servers/kills/last kill/"event history expires after N days"), game tab bar in nav, auto-selects single game. GameService fetches DeleteDays from hlstats_Options. | 98% |
| Help Page | help.php | HelpController + Help/Index.cshtml: weapons reference table, game actions reference table (tabbed by game), mode-conditional tracking text (NameTrack/LAN/Steam Normal) read from hlstats_Options via GetModeAsync. | 95% |
| Admin — Login / Logout | adminauth.php | Cookie-based claims authentication. Login/logout/access-denied flow complete. | 95% |
| Admin — Site Options | admintasks/options.php | Full GET/POST form covering all hlstats_Options rows. Minor: a few legacy option rows (Perl path) are N/A for .NET. | 95% |
| Admin — Games CRUD | admintasks/games.php | Full list/create/edit/delete for hlstats_Games. | 95% |
| Admin — Servers CRUD (including Create/Edit) | admintasks/newserver.php, serversettings.php | Full list/create/edit/delete including server settings form. Server creation now copies hlstats_Games_Defaults into hlstats_Servers_Config (ON DUPLICATE KEY UPDATE). | 95% |
| Admin — Clan Tags CRUD | admintasks/clantags.php | Full CRUD for auto-assignment rules. | 95% |
| Admin — Host Groups CRUD | admintasks/hostgroups.php | Full CRUD for server host group definitions. | 95% |
| Admin — Actions CRUD | admintasks/actions.php | Full CRUD for game action events and skill bonus configurations. | 95% |
| Admin — Teams CRUD | admintasks/teams.php | Full CRUD for team definitions. | 95% |
| Admin — Roles CRUD | admintasks/roles.php | Full CRUD for game role definitions. | 95% |
| Admin — Weapons CRUD | admintasks/weapons.php | Full CRUD for weapon definitions. | 95% |
| Admin — Ranks CRUD | admintasks/ranks.php | Full CRUD for rank tiers. | 95% |
| Admin — Ribbons CRUD + Trigger Conditions | admintasks/ribbons.php, ribbons_trigger.php | Full CRUD for ribbons and their trigger conditions. | 95% |
| Admin — Awards CRUD (Player / Weapon / Online) | admintasks/awards_*.php | Full CRUD for all three award types. | 95% |
| Admin — Player Edit Tools | admintasks/tools_editdetails_player.php | Full edit form (profile fields, IP list). Edit Details search page now returns player/clan matches with direct Edit links. PHP has no Merge player feature — gap was phantom. | 95% |
| Admin — Clan Edit Tools | admintasks/tools_editdetails_clan.php | Edit clan name, tag, tag style, and home URL. | 95% |
| Admin — Events Log | admintasks/tools_adminevents.php | Paginated audit log of admin actions. | 95% |
| Admin — DB Reset (per-game / global) | admintasks/tools_reset.php | Reset stats to zero with per-game or global scope and table checkboxes. | 95% |
| Admin — DB Optimize | admintasks/tools_optimize.php | Runs OPTIMIZE TABLE on all hlstatsx tables. | 95% |
| Admin — Copy Game Settings | admintasks/tools_settings_copy.php | Copies actions/teams/roles/weapons config from one game to another. | 95% |
| Admin — Cleanup Inactive | (tools_cleanup) | Removes players, clans, and servers below configurable activity thresholds. | 95% |
| Admin — IP Stats | admintasks/tools_ipstats.php | Connection frequency report from hlstats_Events_Connects. Two-level view: hostgroup list with meter bar + per-host drill-down. Sortable, paginated. | 95% |
| Admin — User Management | admintasks/adminusers.php | 🆕 Upgraded to full parity. List, create, edit (password + AccLevel dropdown: Administrator/Restricted/No Access matching PHP 0/80/100), delete. Access level descriptions and password note match PHP help text. | 95% |
| Admin — Dashboard | admin.php | 🆕 Full parity. 5 stat cards (Players, Clans, Active Servers, Total Servers, Games count); General Settings quick-links; per-game cards with links to Servers/Actions/Teams/Roles/Weapons/Ranks/Ribbons + all 4 award types pre-filled with ?game=; Tools section with 9 tools + descriptions; Servers summary table sorted by game+name. | 95% |
| Admin — VoiceComm Server Management | admintasks/voicecomm.php | 🆕 NEW. Full CRUD for hlstats_Servers_VoiceComm. List table (type/name/address/UDP port/query port/description), create form (serverType select: TeamSpeak=0 / Ventrilo=1), edit form, delete. | 95% |
| Admin — Daemon Control | admintasks/tools_perlcontrol.php | 🆕 NEW. Send RELOAD or KILL UDP control packets to Perl daemon or HLStatsX.NET.Daemon. Configurable host/port; 5-second receive timeout; displays bytes sent, packets received, and response text. | 95% |
| Admin — Reset DB Collations | admintasks/tools_resetdbcollations.php | 🆕 NEW. Converts all tables to utf8mb4/utf8mb4_unicode_ci. Two modes: run on DB (ALTER TABLE via raw ADO.NET) or print SQL statements for manual execution on large databases. | 95% |
| Feature | PHP Reference | Notes |
|---|---|---|
| Admin — DB Synchronize | admintasks/tools_synchronize.php | ⚠️ Obsolete. Connects to defunct ELstatsNEO/HLstatsX master servers. Not worth porting. |
| Teamspeak / Ventrilo | teamspeak.php, ventrilo.php | Displays connected users on legacy voice servers. Low priority — most communities use Discord. |
Empty — no known gaps remaining in implemented features.
All 19 functional in-game pages are now live at /ingame/*. Lightweight no-chrome HTML for the Half-Life MOTD browser: player/clan ranks, weapon/map stats, accuracy, kill targets, statsme, server status, bans, actions, and more.
Server list, aggregate trend chart, per-server load charts with 4 time ranges (24h/week/month/year), VoiceComm block, Leaflet player location map, live players table, and daily awards. game.php at 95%.
Feature-complete with 26+ concurrent DB queries covering all tabs: General, Teams & Actions, Weapons, Maps & Servers, Kill Stats. Matches PHP original.
All tabs implemented: Members (paginated), Weapons, Map Performance, Actions, Teams, Roles, and an interactive Leaflet member location widget.
Pagination, sortable columns, and game-parameter propagation are consistent across all 50+ implemented pages. Every table has a Rank column and sortable headers.
SkiaSharp PNG generation matches PHP GD implementation — same 11 backgrounds, per-background colour logic, rank + kill data overlay.
Weekly, monthly, and daily leaderboards pull from hlstats_Players_History with accurate period filtering and unified PlayerLeaderboardRow model.
Full CRUD for all entity types: users, games, servers, actions, teams, roles, weapons, ranks, ribbons + triggers, awards, and VoiceComm servers. Plus site-options, player/clan tools, events log, DB reset/optimize/copy, cleanup, IP Stats, daemon control, reset DB collations, and cookie auth. Only the obsolete VAC sync and legacy voice pages remain.
Steam avatar fetching via ISteamService is live. Player profiles show Steam Community avatars with graceful fallback on error.
Games list landing page is implemented. Game tab bar in the nav allows switching between all active games. Game param propagated throughout.
Kill/death heatmap on Map Detail exceeds the PHP original — Canvas-based interactive overlay with tabs, zoom/pan, and automatic calibration from DB config. Bonus feature.
Daily Awards, Global Awards, Ranks (grid with player counts + detail links), and Ribbons (class-grouped with player counts + detail links) — all implemented with full navigation to detail pages.
The hlstats.pl rewrite is production-capable: all 18 game-event handlers done, all 6 skill modes verified, clan tag matching, GeoIP on connect, Livestat lifecycle, trend tracking, and graceful shutdown. Full RCON subsystem implemented — Source (TCP) and GoldSrc (UDP) clients, broadcasting wired into all event handlers. 641 unit tests.
HLStatsX.NET.Awards is a fully operational .NET Worker Service replacing hlstats-awards.pl: award calculation, ribbon recalculation, clan membership, player activity marking, data pruning, and OPTIMIZE TABLE. Supports scheduled runs and on-demand CLI flags.