Sunucun burada olabilir Haftalık açık artırmada teklif ver Sunucu tanitimi

Add 4 tutorials (4 files)

Browse Source
Daemon666 committed parent 7cb0476f40 commit 43154d68f0bd5f14b5507f8119115b4085dafeca
4 changed files with 223 additions and 0 deletions
+112 -0 build-vip-plugin/en.md A
@@ -0,0 +1,112 @@
1 +---
2 +title: "Build a VIP System Plugin (Flags, Menu, MySQL)"
3 +excerpt: "Design a real VIP plugin for AMX Mod X: gate benefits behind an admin flag, give spawn bonuses, add a /vip menu, and store expiring VIP in MySQL with threaded SQLx queries."
4 +category: "plugin-dev"
5 +tags: "vip, tutorial"
6 +image: ""
7 +read_time: "10 min read"
8 +---
9 +<p>A VIP plugin is a good exercise because it touches every subsystem an admin plugin uses: access flags, spawn hooks, a menu, and persistent storage. This walks through a clean design — flag-gated benefits first, then an optional MySQL layer for VIP that expires. The goal is a plugin you can actually run, not a toy. It targets AMX Mod X 1.9+ and Ham Sandwich for the spawn hook.</p>
10 +
11 +<h2>1. Pick the VIP flag</h2>
12 +<p>Do not invent an auth system — reuse the AMXX flag model. VIP conventionally maps to a custom level flag, most commonly <code>t</code> (<code>ADMIN_LEVEL_H</code>). A user with <code>t</code> in <a href="/tutorials/users-ini-explained">users.ini</a> is a VIP. Read the flag once at load:</p>
13 +<pre>#include &lt;amxmodx&gt;
14 +#include &lt;amxmisc&gt;
15 +#include &lt;hamsandwich&gt;
16 +#include &lt;fun&gt;
17 +
18 +new const VIP_FLAG = ADMIN_LEVEL_H
19 +
20 +bool:is_vip(id) {
21 + return (get_user_flags(id) &amp; VIP_FLAG) ? true : false
22 +}</pre>
23 +
24 +<h2>2. Give the benefits on spawn</h2>
25 +<p>Hook <code>Ham_Spawn</code> and apply bonuses after the engine has finished spawning the player (post = 1):</p>
26 +<pre>public plugin_init() {
27 + register_plugin("CSB VIP", "1.0", "CSB")
28 + RegisterHam(Ham_Spawn, "player", "OnSpawnPost", 1)
29 +}
30 +
31 +public OnSpawnPost(id) {
32 + if (!is_user_alive(id) || !is_vip(id))
33 + return
34 + set_user_health(id, 125)
35 + set_user_armor(id, 100)
36 + client_print_color(id, print_team_default, "^x04[VIP]^x01 Bonus health and armor applied")
37 +}</pre>
38 +<p><code>client_print_color</code> makes this 1.9+; see <a href="/tutorials/colored-chat-messages">colored chat messages</a> for the color codes.</p>
39 +
40 +<h2>3. Add a /vip menu</h2>
41 +<p>Register a say handler and build a menu with the AMXX menu API:</p>
42 +<pre>public plugin_init() {
43 + // ...
44 + register_clcmd("say /vip", "CmdVipMenu")
45 +}
46 +
47 +public CmdVipMenu(id) {
48 + new menu = menu_create("\\rVIP Menu", "VipMenuHandler")
49 + menu_additem(menu, "\\wExtra Health", "1")
50 + menu_additem(menu, "\\wDrop Grenade", "2")
51 + menu_display(id, menu)
52 + return PLUGIN_HANDLED
53 +}
54 +
55 +public VipMenuHandler(id, menu, item) {
56 + if (item == MENU_EXIT) {
57 + menu_destroy(menu)
58 + return PLUGIN_HANDLED
59 + }
60 + if (!is_vip(id)) {
61 + client_print(id, print_chat, "[VIP] You are not a VIP.")
62 + } else if (item == 0) {
63 + set_user_health(id, get_user_health(id) + 25)
64 + }
65 + menu_destroy(menu)
66 + return PLUGIN_HANDLED
67 +}</pre>
68 +<p>For a fuller, ready-made version see <a href="/plugins/csb-vip-menu">CSB VIP Menu</a>.</p>
69 +
70 +<h2>4. Persist expiring VIP in MySQL</h2>
71 +<p>Flag-based VIP is permanent and manual. For paid, time-limited VIP you want a database. Use the <code>sqlx</code> module (install it via <a href="/tutorials/install-mysql-module-amxx">the MySQL module guide</a>) and <strong>always</strong> use threaded queries — a blocking query freezes the whole server on a slow database.</p>
72 +<pre>#include &lt;sqlx&gt;
73 +
74 +new Handle:g_tuple
75 +
76 +public plugin_cfg() {
77 + g_tuple = SQL_MakeDbTuple("127.0.0.1", "csb", "secret", "csb_vip")
78 + SQL_ThreadQuery(g_tuple, "IgnoreHandler",
79 + "CREATE TABLE IF NOT EXISTS vips (steamid VARCHAR(32) PRIMARY KEY, expires INT)")
80 +}
81 +
82 +public client_authorized(id) {
83 + new sid[32], q[128]
84 + get_user_authid(id, sid, charsmax(sid))
85 + formatex(q, charsmax(q), "SELECT expires FROM vips WHERE steamid='%s'", sid)
86 + new data[1]
87 + data[0] = id
88 + SQL_ThreadQuery(g_tuple, "OnVipLookup", q, data, 1)
89 +}
90 +
91 +public OnVipLookup(failstate, Handle:query, error[], errnum, data[], size, Float:qtime) {
92 + if (failstate != TQUERY_SUCCESS) {
93 + log_amx("VIP query failed: %s", error)
94 + return
95 + }
96 + new id = data[0]
97 + if (SQL_NumResults(query) &amp;&amp; SQL_ReadResult(query, 0) &gt; get_systime())
98 + set_user_flags(id, VIP_FLAG) // grant runtime VIP
99 +}</pre>
100 +<p>Storing the SteamID as the key means VIP follows the player, not a slot. The <code>expires</code> column is a Unix timestamp compared against <code>get_systime()</code>, so lapsed VIP simply never gets the flag set.</p>
101 +
102 +<h2>Common errors</h2>
103 +<ul>
104 +<li><strong>Server hitches every time a VIP connects</strong> — you used <code>SQL_Execute</code> (blocking) instead of <code>SQL_ThreadQuery</code>. Always thread player-facing queries.</li>
105 +<li><strong>Benefits never apply</strong> — you hooked <code>Ham_Spawn</code> with post = 0. Health set pre-spawn is overwritten by the engine. Use post = 1.</li>
106 +<li><strong>Everyone is a VIP</strong> — your flag check used <code>|</code> instead of <code>&amp;</code>, or you compared to <code>ADMIN_ALL</code> (which is 0). Use <code>get_user_flags(id) &amp; VIP_FLAG</code>.</li>
107 +<li><strong>Module failed to load: sqlx</strong> — the MySQL module is not enabled in <code>modules.ini</code>. See <a href="/tutorials/install-amxx-modules">installing AMXX modules</a>.</li>
108 +<li><strong>VIP granted at runtime is lost on map change</strong> — expected: <code>set_user_flags</code> is per-session. Re-run the lookup on <code>client_authorized</code> every map, as above.</li>
109 +</ul>
110 +
111 +<h2>Verification</h2>
112 +<p>Give yourself flag <code>t</code> in users.ini, run <code>amx_reloadadmins</code>, and respawn — you should get the health/armor bonus and the <code>[VIP]</code> line. Type <code>say /vip</code> to open the menu. For the MySQL layer, insert a row with a future <code>expires</code>, reconnect, and confirm the flag is set with <code>amx_who</code>. A row with a past timestamp must leave you as a normal player. Once all three paths behave, compile cleanly per <a href="/tutorials/compile-sma-to-amxx">the compile guide</a> and ship it.</p>
+42 -0 cs16-masterserver-vdf/en.md A
@@ -0,0 +1,42 @@
1 +---
2 +title: "Fix: No Servers in the Browser (masterserver.vdf)"
3 +excerpt: "The internet server list is empty. The cause is usually an outdated master-server list, a blocked UDP query port, or a client that is too new. Here is how to get servers back."
4 +category: "client"
5 +tags: "masterserver.vdf, browser"
6 +image: ""
7 +read_time: "7 min read"
8 +---
9 +<p>You open the internet tab, hit refresh, and nothing appears — or a handful of servers show and then vanish. The server browser works by asking a <em>master server</em> for the current list of game servers, then querying each one directly over UDP. If the master address your client uses is dead, or the query traffic is blocked, the list comes back empty. Non-Steam builds make this worse because they ship their own master-server list file (often named <code>masterserver.vdf</code> or similar) that goes stale over time.</p>
10 +
11 +<h2>1. Refresh correctly and check the filters first</h2>
12 +<p>Before touching files, rule out the obvious. In the internet tab, clear every filter — a lingering "map", "not full", or "has users" filter hides the whole list. Then click <em>Refresh</em> (not <em>Add server</em>) and give it 20–30 seconds; the first query pass to the master is slow. If a full unfiltered refresh still returns nothing, move on.</p>
13 +
14 +<h2>2. Update the master-server list on non-Steam clients</h2>
15 +<p>Non-Steam distributions embed a list of master servers in a config file rather than using Steam's live master. When those hardcoded masters go offline, the internet tab is permanently empty. Look for a file such as:</p>
16 +<pre>cstrike\masterserver.vdf
17 +platform\config\masterservers.vdf</pre>
18 +<p>These point the client at one or more master hosts. If yours references dead addresses, replace the file with a current one from the community build you are running, or update it to a live master your servers actually heartbeat to. Do <strong>not</strong> paste addresses from a random forum — a hostile master can feed you a list of malicious servers. Use the file that ships with a reputable, current client.</p>
19 +
20 +<h2>3. Roll the Steam client back to steam_legacy</h2>
21 +<p>On the official Steam client, the 2023 25th Anniversary update changed enough that many players saw an empty or unstable internet list afterward. Rolling back fixes it for a large share of people. Right-click Counter-Strike in Steam, <em>Properties → Betas</em>, and select:</p>
22 +<pre>steam_legacy</pre>
23 +<p>Let it update, restart, and refresh the internet tab. Legacy behaves like the pre-2023 client the master infrastructure was tuned for.</p>
24 +
25 +<h2>4. Unblock the query traffic</h2>
26 +<p>The browser has to reach the master and then send a UDP query to each server. A firewall or restrictive router that blocks outbound UDP kills both. Allow the CS 1.6 client through Windows Firewall (it usually prompts once — people click Cancel), and if you are on a locked-down network, note that server queries and master traffic use UDP, not TCP. On mobile hotspots and some corporate NATs this is blocked outright and there is no client-side fix.</p>
27 +
28 +<h2>5. Use Favorites and direct connect as a reliable fallback</h2>
29 +<p>Even with a broken master list you can reach any server whose IP you know. In the <em>Favorites</em> tab, <em>Add a server</em> by <code>IP:port</code>, or from the console:</p>
30 +<pre>connect 203.0.113.10:27015</pre>
31 +<p>This bypasses the master entirely — it queries that one server directly. If direct connect works but the internet tab is empty, the fault is master-list discovery, which confirms steps 2 and 3 are where to look. Community server lists (like this site's) let you copy a working <code>connect</code> line for any live server.</p>
32 +
33 +<h2>Common errors</h2>
34 +<ul>
35 +<li><strong>Internet tab empty, direct connect works</strong> — master-list discovery is broken. Non-Steam: update the master file (step 2). Steam: try steam_legacy (step 3).</li>
36 +<li><strong>Servers appear then all disappear</strong> — a filter is culling them after the query pass, or your client is timing out the UDP replies. Clear filters; check the firewall.</li>
37 +<li><strong>Only a few servers ever show</strong> — you are reaching one live master out of several dead ones. A current master file returns the full list.</li>
38 +<li><strong>LAN tab has servers, internet does not</strong> — normal; LAN uses broadcast, internet uses the master. Nothing is wrong with the game.</li>
39 +</ul>
40 +
41 +<h2>Verification</h2>
42 +<p>After the fix, an unfiltered internet refresh should return hundreds to thousands of servers within about half a minute. Sort by <em>Players</em> to push the list to the top. As a definitive discovery test, pick any server from a community list and paste its <code>connect IP:port</code> into the console — if you join, your query path is healthy and only the master file or client branch needed attention. If you also run a server that will not appear for <em>anyone</em>, that is the opposite problem: see <a href="/tutorials/get-server-in-master-list">getting your server listed</a> and <a href="/tutorials/fix-server-not-in-master-list">why a server is missing from the list</a>.</p>
+59 -0 motd-txt-html-guide/en.md A
@@ -0,0 +1,59 @@
1 +---
2 +title: "motd.txt: Writing an HTML MOTD That Actually Renders"
3 +excerpt: "How the CS 1.6 MOTD window loads motd.txt, the size limit that truncates it, the URL mode, and how to write HTML that renders in the in-game browser."
4 +category: "administration"
5 +tags: "motd, html"
6 +image: ""
7 +read_time: "7 min read"
8 +---
9 +<p>The message-of-the-day box that pops up when a player connects is rendered by <code>motd.txt</code> in your <code>cstrike/</code> folder, shown in the game client's embedded HTML control. It is one of the few places you can put branding and rules in front of every visitor, and it is also one of the easiest to get subtly wrong — because the renderer is not a modern browser, and the file has a hard size limit that silently truncates anything too large.</p>
10 +
11 +<h2>1. Where it lives and what points at it</h2>
12 +<p>The file is <code>cstrike/motd.txt</code>, and the engine finds it through the <code>motdfile</code> cvar (default <code>motd.txt</code>). You can host multiple and switch:</p>
13 +<pre>// server.cfg
14 +motdfile "motd.txt"</pre>
15 +<p>The window opens automatically on connect and can be re-opened by the client bind <code>motd</code>. Plugins frequently override it (a custom rules menu, a store panel), so if your file is ignored, check whether an AMXX plugin is calling <code>show_motd</code> with its own content.</p>
16 +
17 +<h2>2. Respect the size limit</h2>
18 +<p>The MOTD is delivered over the game channel and the classic engine truncates it at roughly <strong>1500 bytes</strong>. Go over and the tail of your page simply never arrives, which looks like broken HTML — an unclosed table, a cut-off paragraph. Two rules follow:</p>
19 +<ul>
20 +<li>Keep the file lean. Strip comments, collapse whitespace, do not paste a 40 KB exported web page into it.</li>
21 +<li>If you need a real page — images, longer copy, styling — use URL mode instead of stuffing it inline.</li>
22 +</ul>
23 +
24 +<h2>3. URL mode: point the window at a web page</h2>
25 +<p>If <code>motd.txt</code> contains nothing but a single URL, the client treats it as an address and loads that page in the MOTD window instead of rendering the file as HTML:</p>
26 +<pre>https://your-domain.example/motd.html</pre>
27 +<p>This sidesteps the size limit entirely and lets you use a normal, cacheable web page. The trade-off: the client must be able to reach that URL, so it must be public HTTP(S) and reasonably fast, or the window hangs on connect. Do not point it at something that can go down — a broken MOTD URL greets every player with a blank or error box.</p>
28 +
29 +<h2>4. Write for the embedded renderer, not for Chrome</h2>
30 +<p>The in-game HTML control supports a small, old subset of HTML. Treat it like a very old browser:</p>
31 +<ul>
32 +<li>Use inline styles and simple tags — <code>&lt;body&gt;</code>, <code>&lt;table&gt;</code>, <code>&lt;font&gt;</code>, <code>&lt;b&gt;</code>, <code>&lt;br&gt;</code>, <code>&lt;a&gt;</code>, <code>&lt;img&gt;</code>. Do not rely on external CSS files or JavaScript.</li>
33 +<li>Set a background and text color explicitly; the default is not guaranteed.</li>
34 +<li>Reference images by absolute <code>https://</code> URL — the client fetches them over the network, they do not come from your game files.</li>
35 +</ul>
36 +<pre>&lt;body bgcolor="#111111" text="#dddddd"&gt;
37 +&lt;table width="100%"&gt;
38 + &lt;tr&gt;&lt;td align="center"&gt;
39 + &lt;font size="5" color="#66ccff"&gt;&lt;b&gt;My CS 1.6 Server&lt;/b&gt;&lt;/font&gt;&lt;br&gt;
40 + &lt;font size="2"&gt;No cheating. No spawn-camping the hostages. Have fun.&lt;/font&gt;
41 + &lt;/td&gt;&lt;/tr&gt;
42 +&lt;/table&gt;
43 +&lt;/body&gt;</pre>
44 +<p>Keep links to a couple; the window is small and players close it fast.</p>
45 +
46 +<h2>5. Encoding and line endings</h2>
47 +<p>Save the file as plain ASCII/UTF-8 without a byte-order mark. A BOM or exotic encoding can make the first line render as garbage or push you over the byte limit unexpectedly. Windows editors that add a <code>.txt</code> a second time (so you end up with <code>motd.txt.txt</code>) are a recurring cause of "my MOTD does not show" — turn on file-extension display, the same trap that breaks <a href="/tutorials/fix-server-cfg-not-executing">server.cfg execution</a>.</p>
48 +
49 +<h2>Common errors</h2>
50 +<ul>
51 +<li><strong>Bottom of the MOTD is cut off</strong> — you exceeded the ~1500-byte limit. Trim the file or switch to URL mode.</li>
52 +<li><strong>Blank window on connect</strong> — URL mode pointing at an unreachable or slow page, or an AMXX plugin overriding the MOTD with empty content.</li>
53 +<li><strong>Images do not load</strong> — you used a relative path or <code>http://</code> to a host that is down. Use absolute <code>https://</code> URLs to a reliable host.</li>
54 +<li><strong>File is ignored entirely</strong> — a plugin is calling its own <code>show_motd</code>, or <code>motdfile</code> points somewhere else. Check the cvar and your plugin list.</li>
55 +<li><strong>First line renders as symbols</strong> — the file has a UTF-8 BOM. Re-save without it.</li>
56 +</ul>
57 +
58 +<h2>Verification</h2>
59 +<p>Connect from a real client — the MOTD window must open on join and render top to bottom with nothing truncated. Check the byte size on disk (<code>wc -c cstrike/motd.txt</code>); if it is near or over 1500, assume truncation and move to URL mode. If you edited it live, a reconnect is enough to reload it; no map change is required. To surface rules again during play, pair it with an <a href="/plugins/csb-adverts">adverts plugin</a> that prints a short reminder in chat.</p>
+10 -0 stable-1000-fps-linux-server/en.md A
@@ -0,0 +1,10 @@
1 +---
2 +title: "Getting Stable 500/1000 FPS on a Linux CS 1.6 Server"
3 +excerpt: "sys_ticrate, -pingboost and the CPU are the three things that decide whether your server holds a high tick rate. Here is how they fit together on Linux, and why ReHLDS is the real fix."
4 +category: "optimization"
5 +tags: "fps, linux"
6 +image: ""
7 +read_time: "9 min read"
8 +---
9 +<p>A high, <em>stable</em> server FPS is what makes hit registration feel honest. The number itself is set by <code>sys_ticrate</code>, but whether the server actually holds it depends on the engine's timing, the <code>-pingboost</code> mode you launch with, and how much CPU headroom that single core has. Chasing 1000 FPS on stock HLDS with a busy server is often a losing battle; the same box on ReHLDS holds it comfortably. This guide walks the levers in the order that matters.</p><p>First, measure honestly — do not tune blind. Read <a href="/tutorials/measure-server-fps">how to measure real server FPS</a> and get a baseline empty and under load.</p><h2>1. Set the target with sys_ticrate</h2><p><code>sys_ticrate</code> is the requested main-loop rate. Set it on the command line or in the launch script:</p><pre>./hlds_run -game cstrike -pingboost 1 +sys_ticrate 1000 \
10 + +map de_dust2 +maxplayers 20 +sv_lan 0</pre><p>Common targets are 500 and 1000. There is no point setting 1000 if the box can only hold 400 — a rock-steady 500 beats a jittery 1000 every time. Start at 1000, measure, and drop the target if it will not hold.</p><h2>2. Choose the -pingboost mode deliberately</h2><p><code>-pingboost</code> selects how the server waits between frames on Linux. The modes trade CPU for timing precision:</p><table><thead><tr><th>Mode</th><th>Behaviour</th></tr></thead><tbody><tr><td><code>-pingboost 0</code></td><td>Default timing. Relies on <code>sys_ticrate</code>; lightest, least precise.</td></tr><tr><td><code>-pingboost 1</code></td><td>Alternative wait method, tighter timing than 0. A common sweet spot.</td></tr><tr><td><code>-pingboost 2</code></td><td>Another timing method; behaviour varies by kernel.</td></tr><tr><td><code>-pingboost 3</code></td><td>Most aggressive; can pin the core and may cap the effective FPS rather than raise it.</td></tr></tbody></table><p>There is no single correct mode — it depends on the kernel and hardware. The honest method is to test: launch with <code>-pingboost 1</code>, measure with <code>stats</code> under load, then try <code>-pingboost 0</code> and compare. Do not assume a higher number is better; <code>-pingboost 3</code> frequently produces <em>worse</em>, more CPU-hungry results than 1.</p><h2>3. Give the process a full, fast core</h2><p>HLDS is single-threaded, so one saturated core caps your FPS regardless of <code>sys_ticrate</code>. On a Linux host you control:</p><p>Set the CPU governor to performance so the core does not clock down:</p><pre>sudo cpupower frequency-set -g performance</pre><p>Give the server process priority (run as a normal user, renice as root):</p><pre>sudo renice -n -5 -p $(pgrep -f hlds_linux)</pre><p>On a box running several servers, pin each to its own core so they do not fight:</p><pre>taskset -c 1 ./hlds_run -game cstrike ...</pre><p>If the core hits 100% under load, no launch flag will save you — see <a href="/tutorials/fix-hlds-100-cpu">HLDS at 100% CPU</a>.</p><h2>4. Switch to ReHLDS — this is the real fix</h2><p>Stock HLDS timing is imprecise, which is exactly why "stable 1000 FPS" is so hard on it. ReHLDS reworked the frame loop and holds high tick rates far more consistently for the same CPU. If you are serious about a stable high FPS, the engine swap does more than every other step combined. Follow <a href="/tutorials/install-rehlds-on-linux">install ReHLDS on Linux</a>, then the ReHLDS-specific tuning in <a href="/tutorials/rehlds-performance-cvars">ReHLDS performance cvars</a>.</p><h2>5. Keep the plugin load light</h2><p>Every AMX Mod X plugin runs inside that single frame. A plugin doing heavy work each frame — a badly written stats or anti-cheat plugin — will drag FPS down under load even on a fast core. If FPS is fine empty and collapses with players, suspect a plugin before the engine; <a href="/tutorials/fix-low-server-fps-linux">low server FPS on Linux</a> covers isolating it.</p><h2>Common errors</h2><ul><li><strong>FPS caps at exactly 100 or exactly your <code>sys_ticrate</code>-minus-something</strong> — usually a <code>-pingboost</code> mode fighting the kernel. Try a different mode.</li><li><strong>1000 empty, 300 full</strong> — CPU-bound. Faster core, fewer plugins, or a lighter target.</li><li><strong>FPS swings wildly</strong> — the governor is scaling the clock, or another process shares the core. Pin the core and set the performance governor.</li><li><strong>Setting <code>sys_ticrate</code> higher does nothing</strong> — you are already CPU-bound, or on stock HLDS whose timing cannot hold it. Measure, then move to ReHLDS.</li><li><strong>Higher FPS but players still lag</strong> — FPS was never the problem; check rates and choke via <a href="/tutorials/sv-maxrate-maxupdaterate-values">the rate cvars guide</a>.</li></ul><h2>Verification</h2><p>Load the server with bots or players, run <code>stats</code> several times during a firefight, and confirm the FPS sits close to your <code>sys_ticrate</code> target with the <code>CPU</code> column comfortably under 100. Change <code>-pingboost</code> and re-measure to prove your chosen mode is genuinely the best on this box. A server that holds 500 rock-steady under a full load is finished; one that holds 1000 is a bonus, not a requirement.</p>
0 11