Home / Developers / DayZ
🧟

DayZ

Enforce Script (C-like) CF + Community Mods

Overview

Reward your DayZ server players for voting on topgservers. DayZ modding uses Enforce Script (a C-like language), but HTTP calls require an external sidecar. This guide covers a Python vote-checker that writes results to a JSON file, which an Enforce Script mod reads to grant in-game items.

Prerequisites

  • A DayZ server with mod support (Community Framework recommended)
  • Python 3.8+ on the server machine for the vote-check sidecar
  • A topgservers API key — generate one in My Servers → API
  • Your webhook secret (optional, for real-time rewards)
  • Basic familiarity with DayZ modding and Enforce Script

Installation

1 Create the mod structure

Set up a standard DayZ mod with the vote reward script and the external Python sidecar.

Directory structure
@TopGVote/
├── Addons/
│   └── TopGVote/
│       ├── config.cpp
│       └── Scripts/
│           └── 4_World/
│               └── TopGVoteReward.c
├── topg_checker.py        (runs alongside server)
└── votes.json             (bridge file)

2 Create the Python vote checker sidecar

This script runs alongside your DayZ server. It polls the topgservers API for online players and writes results to a JSON file that the Enforce Script mod reads.

topg_checker.py
#!/usr/bin/env python3
"""
topgservers vote checker sidecar for DayZ.
Run alongside DayZ server: python3 topg_checker.py
Writes vote results to votes.json for the Enforce Script mod.
"""
import requests
import json
import time
import os

API_KEY = "tgs_your_api_key_here"
CHECK_INTERVAL = 60  # seconds
VOTES_FILE = "votes.json"
PLAYERS_FILE = "online_players.txt"  # Written by server mod

def load_online_players():
    """Read online player list written by the DayZ mod."""
    if not os.path.exists(PLAYERS_FILE):
        return []
    with open(PLAYERS_FILE, 'r') as f:
        return [line.strip() for line in f if line.strip()]

def check_votes():
    """Check vote status for all online players."""
    players = load_online_players()
    votes = {}

    # Load existing votes
    if os.path.exists(VOTES_FILE):
        with open(VOTES_FILE, 'r') as f:
            votes = json.load(f)

    for name in players:
        if name in votes and votes[name].get("rewarded"):
            continue

        try:
            resp = requests.get(
                f"https://topgservers.net/api/v1/vote-check?username={name}",
                headers={"Authorization": f"Bearer {API_KEY}"},
                timeout=5
            )
            if resp.status_code == 200 and resp.json().get("voted"):
                votes[name] = {"voted": True, "rewarded": False}
        except Exception:
            continue

    with open(VOTES_FILE, 'w') as f:
        json.dump(votes, f, indent=2)

if __name__ == "__main__":
    print("topgservers vote checker running...")
    while True:
        check_votes()
        time.sleep(CHECK_INTERVAL)

3 Create the Enforce Script mod

The Enforce Script mod reads the votes.json file on a timer and spawns reward items into the player's inventory.

TopGVoteReward.c
// TopGVote Reward Mod for DayZ
// Reads votes.json written by the Python sidecar
// and grants items to players who voted.

class TopGVoteReward extends PluginBase
{
    private const float CHECK_INTERVAL = 30.0; // seconds
    private const string VOTES_FILE = "$profile:votes.json";

    void TopGVoteReward()
    {
        GetGame().GetCallQueue(CALL_CATEGORY_SYSTEM)
            .CallLater(CheckVotes, CHECK_INTERVAL * 1000, true);
    }

    void CheckVotes()
    {
        if (!FileExist(VOTES_FILE)) return;

        string content;
        FileHandle file = OpenFile(VOTES_FILE, FileMode.READ);
        if (!file) return;

        string line;
        while (FGets(file, line) >= 0)
        {
            content += line;
        }
        CloseFile(file);

        // Parse JSON and check each online player
        array<Man> players = new array<Man>();
        GetGame().GetPlayers(players);

        foreach (Man man : players)
        {
            PlayerBase player = PlayerBase.Cast(man);
            if (!player) continue;

            string name = player.GetIdentity().GetName();

            // Simple check: look for the player name with voted:true
            if (content.Contains(name)
                && content.Contains(""voted": true")
                && !content.Contains(""rewarded": true"))
            {
                GrantReward(player);
                MarkRewarded(name);
            }
        }
    }

    void GrantReward(PlayerBase player)
    {
        EntityAI item;

        // Spawn items in player inventory
        item = player.GetInventory().CreateInInventory("SodaCan_Cola");
        item = player.GetInventory().CreateInInventory("TacticalBaconCan");
        item = player.GetInventory().CreateInInventory("Ammo_762x39");

        // Notify player
        if (player.GetIdentity())
        {
            GetGame().RPCSingleParam(player, ERPCs.RPC_USER_ACTION_MESSAGE,
                new Param1<string>(
                    "Thanks for voting on topgservers! Check your inventory."),
                true, player.GetIdentity());
        }
    }

    void MarkRewarded(string playerName)
    {
        // Write back to votes.json marking player as rewarded
        // In production, use proper JSON parsing
        // For simplicity, the Python sidecar handles cleanup
    }
}

4 Create the mod config

The config.cpp registers the mod with DayZ so it loads automatically.

config.cpp
class CfgPatches
{
    class TopGVote
    {
        units[] = {};
        weapons[] = {};
        requiredVersion = 0.1;
        requiredAddons[] = { "DZ_Data" };
    };
};

class CfgMods
{
    class TopGVote
    {
        type = "mod";
        name = "TopGVote";
        dir = "TopGVote";

        class defs
        {
            class worldScriptModule
            {
                value = "";
                files[] = { "TopGVote/Scripts/4_World" };
            };
        };
    };
};

Configuration

topg_checker.py (config section)
# Configuration
API_KEY         = "tgs_your_api_key_here"
WEBHOOK_SECRET  = "whsec_your_secret_here"

# Paths
VOTES_FILE      = "votes.json"
PLAYERS_FILE    = "online_players.txt"

# Timing
CHECK_INTERVAL  = 60    # seconds between vote checks

# Reward items (DayZ class names)
REWARD_ITEMS    = [
    "SodaCan_Cola",
    "TacticalBaconCan",
    "Ammo_762x39",
]

Vote Check

Call the /api/v1/vote-check endpoint to determine if a player has voted today.

Vote check (Python sidecar)
import requests

resp = requests.get(
    "https://topgservers.net/api/v1/vote-check?username=" + player_name,
    headers={"Authorization": "Bearer " + API_KEY},
    timeout=5
)

if resp.status_code == 200 and resp.json().get("voted"):
    # Player voted today — write to votes.json for the mod to read
    votes[player_name] = {"voted": True, "rewarded": False}

Webhook Receiver

Verify the X-TopG-Signature header using HMAC-SHA256 to ensure webhook payloads are authentic.

webhook_receiver.py (sidecar)
"""
Webhook receiver for DayZ servers.
Writes vote results to votes.json for the Enforce Script mod.
"""
import hmac, hashlib, json
from http.server import HTTPServer, BaseHTTPRequestHandler

WEBHOOK_SECRET = "whsec_your_secret_here"
VOTES_FILE = "votes.json"

class WebhookHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        length = int(self.headers.get('Content-Length', 0))
        body = self.rfile.read(length).decode()
        sig = self.headers.get('X-TopG-Signature', '')

        if not verify_signature(body, sig):
            self.send_response(401)
            self.end_headers()
            return

        data = json.loads(body)
        username = data.get('username', '')

        if username:
            # Load existing votes
            try:
                with open(VOTES_FILE, 'r') as f:
                    votes = json.load(f)
            except (FileNotFoundError, json.JSONDecodeError):
                votes = {}

            votes[username] = {"voted": True, "rewarded": False}

            with open(VOTES_FILE, 'w') as f:
                json.dump(votes, f, indent=2)

        self.send_response(200)
        self.end_headers()

def verify_signature(body, sig_header):
    parts = dict(p.split('=', 1) for p in sig_header.split(',') if '=' in p)
    timestamp = parts.get('t', '')
    received = parts.get('v1', '')

    expected = hmac.new(
        WEBHOOK_SECRET.encode(),
        f"{timestamp}.{body}".encode(),
        hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(expected, received)

if __name__ == '__main__':
    server = HTTPServer(('0.0.0.0', 8090), WebhookHandler)
    print("Webhook receiver listening on :8090")
    server.serve_forever()

Reward Examples

Reward examples (Enforce Script)
// Spawn item in player inventory
player.GetInventory().CreateInInventory("SodaCan_Cola");
player.GetInventory().CreateInInventory("TacticalBaconCan");

// Spawn ammo
player.GetInventory().CreateInInventory("Ammo_762x39");

// Spawn weapon (goes to hands if space)
player.GetInventory().CreateInInventory("M4A1");

// Spawn item at player position (if inventory is full)
EntityAI item = GetGame().CreateObjectEx(
    "TacticalBaconCan", player.GetPosition(),
    ECE_PLACE_ON_SURFACE);

// Send notification
GetGame().RPCSingleParam(player, ERPCs.RPC_USER_ACTION_MESSAGE,
    new Param1<string>("Vote reward: items added!"),
    true, player.GetIdentity());

Notes & Tips

DayZ Enforce Script cannot make HTTP requests directly, so the Python sidecar pattern is required. The sidecar writes to votes.json and the mod reads it. For production, consider using a SQLite database instead of a JSON file for better concurrency. Make sure the votes.json path is accessible to both the Python script and the DayZ server process.