Skip to content
Ricklayer
RUEN
← All work

02 · EloStore ecosystem

CS2 servers

Skin changer, match engine and broadcast

Our own game servers running our own code: skins picked in the site dashboard appear in game by SteamID, tournaments load from the admin, the broadcast gets a live killfeed. 3 own C# plugins, 1,755 lines with no third-party plugins and 0 weapon switches for a skin to apply.

Skins from the dashboard

A player picks a finish in the dashboard on the site, joins the server, and it is already in their hands. These are the same renders the player sees in the dashboard.

Renders from the elostore.ru dashboard

AK-47 | Asiimov
01AK-47 | Asiimov
AWP | Dragon Lore
02AWP | Dragon Lore
M4A1-S | Printstream
03M4A1-S | Printstream
M4A4 | Howl
04M4A4 | Howl
AK-47 | Fire Serpent
05AK-47 | Fire Serpent
AWP | Gungnir
06AWP | Gungnir
M4A1-S | Black Lotus
07M4A1-S | Black Lotus
USP-S | Kill Confirmed
08USP-S | Kill Confirmed
AK-47 | Neon Rider
09AK-47 | Neon Rider
M4A4 | Temukau
10M4A4 | Temukau
AWP | Chromatic Aberration
11AWP | Chromatic Aberration
AK-47 | Head Shot
12AK-47 | Head Shot

Knives and gloves

The knife model and its finish are applied at the moment the item is given, before the first frame: no weapon switching.

Karambit | Fade
Karambit | Fade
Butterfly Knife | Fade
Butterfly Knife | Fade
M9 Bayonet | Lore
M9 Bayonet | Lore
Sport Gloves | Vice
Sport Gloves | Vice
Specialist Gloves | Crimson Kimono
Specialist Gloves | Crimson Kimono

A paint engine of our own

There was no ready way to bake a CS2 finish onto a model for the web, so we spent about a month building the skin changer and our own engine from scratch: the model and the paint come from the game files, the paint formulas repeat the CS2 shader, and every result is checked against the Valve icon.

The interface is recreated: the model and pattern come from the game files, the shader from the engine viewer, the terminal numbers are illustrative

0

finishes built by the engine

0

weapon models from the game files

8

paint styles following the shader formulas

The task

EloStore tournaments and skins needed a server of their own, not someone else's plugins with closed behaviour.

The task: connect the site and the game. A player sets everything up on the site, joins the server, and it is all already there: skins, roster, match phases, broadcast.

Slice by layer

Interfacethe pixel
Skins dashboard on the site, tournament brackets, match admin, an OBS overlay
Logicmoney and rules
Match phases, map veto, Single Elimination and Round Robin brackets, a broadcast event director
Dataschema and migrations
Loadouts by SteamID, a catalogue of skins, agents and stickers, match stats in Postgres
Serverdeploy and operations
A dedicated CS2 server under systemd with its own user, RCON closed to the outside
Securitythe kernel
A token in the GSI config against forged state, a roster whitelist, token-protected server API

EloSkins skin changer

Players choose weapon skins, knives, gloves, agents and stickers in the site dashboard, and they appear in game.

  1. 01On player authorization the plugin pulls the loadout by SteamID from the site API, with separate skins for T and CT
  2. 02Paint is applied at entity creation (OnEntitySpawned) and in the GiveNamedItem hook, before the first frame: knife model and paint land without switching
  3. 03Paint is set through the native CAttributeList_SetOrAddAttributeValueByName via a gamedata signature
  4. 04Agent models are precached at map start, otherwise SetModel is unsafe
  5. 05The !ws command refreshes skins after edits on the site without reconnecting

Result

A skin from the dashboard is in your hands from the very first frame.

EloMatch match engine

Our own port of MatchZy onto EloStore infrastructure: a tournament match is driven from the site.

  1. 01A match loads from the site with css_eloload: roster, maps, series
  2. 02Phases: warmup → knife → side pick → live → break → next map of the series
  3. 03A quiet roster whitelist: outsiders move to spectators without chat spam
  4. 04The break between maps is set in the admin, every match event feeds the admin timeline

EloDM deathmatch

DM in the style of top public servers, entirely on our own code.

  1. 01A custom spawn system: teleport to a point where enemies are beyond a threshold, against spawn kills
  2. 02Instant respawn with spawn protection, +HP per frag, ammo refill
  3. 03A weapon menu with a saved loadout
  4. 04Skin changer compatible: DM never touches the knife, only EloSkins issues it

OBS broadcast overlay

Tournament streams get a live killfeed, multikill banners and round recaps.

  1. 01CS2 sends Game State Integration to the site, the server keeps the last snapshot, the overlay reads a stream
  2. 02A director compares snapshots and detects kills, aces, clutches, the bomb, round end
  3. 03GSI does not say who killed whom: pairs are rebuilt from the killer's kills delta and the victim's alive → dead transition
  4. 04Events fade on their own timers even if the game stops sending data

Stories from production

Incident 01 · open

A knife in slow motion

Swapping the skin broke weapon animation speed: draw and reload played in slow motion.

Incident 02 · open

Skins applied only after a switch

Paint was applied after the weapon spawned, so players had to switch weapons to see the skin.

Stack

C# · .NET · CounterStrikeSharp · Source 2 · GSI · RCON · Next.js API · PostgreSQL · SSE · systemd