Discover the best Metin2 private servers. Vote for your favorite servers, explore new communities, and find your next gaming adventure.
Easy, Free & Reliable Voting Rewards for Your Metin2 Private Server
Our Vote Verification System is a modern and innovative solution designed specifically for Metin2 Private Servers. It provides an engaging way for players to vote for their favorite servers while receiving in-game benefits.
The system is both easy to implement and highly reliable, making it an excellent choice for server owners looking to increase player engagement and server visibility.
Our goal is to create a win-win situation for both players and server owners. Players get rewarded for their loyalty with in-game benefits, while servers benefit from increased visibility and higher player engagement.
Complete In-Game Voting & Reward System with Custom UI
Vote4Buff is our premium all-in-one voting solution that includes a beautiful in-game UI, WebSocket communication, and complete server integration. Players can vote, select from multiple bonus pools, and receive instant rewards without ever leaving the game!
The Vote4Buff system consists of three main components:
Perfect for: Server owners who want a professional, ready-to-use solution without spending weeks on custom development. Simply configure the bonus pools, integrate the files, and you're ready to go!
Get all the files you need for client and server integration
Vote4Buff is designed for martysama0134 v5.8 source base. If you're using a different source, some modifications may be required.
Includes libcurl.dll (32-bit included, 64-bit available)
All necessary C++ source modifications included
Please login to download Vote4Buff files.
Configure bonus pools, item rewards, and API settings
All Vote4Buff configuration is done in the char.h file on your server. Below are detailed examples of each configuration option.
First, you'll need to configure your Server ID and API Token (found in your dashboard):
// API SETTINGS from Metin2 Server List
static const std::string s_VOTE4BUFF_SERVER_ID = "YOUR_SERVER_ID"; // From dashboard
static const std::string s_VOTE4BUFF_API_TOKEN = "YOUR_API_TOKEN"; // From dashboard
static const int s_VOTE4BUFF_DURATION = 86400; // seconds (1 day) DO NOT MODIFY THIS !!!
You can define up to 3 bonus pools that players can choose from. Each pool can contain multiple bonuses:
// Bonuses must be set with its APPLY_ declaration.
// You can add as many bonuses as you want per slot.
static std::vector<std::vector<std::pair<int, int>>> s_VOTE4BUFF_BONUSES =
{
{ // Bonus Pool 1: PvP Focused
{ APPLY_ATTBONUS_HUMAN, 5 }, // +5% vs Players
{ APPLY_DEF_GRADE_BONUS, 50 }, // +50 Defense
// Add more bonuses if wanted
},
{ // Bonus Pool 2: PvE Focused
{ APPLY_ATTBONUS_MONSTER, 5 }, // +5% vs Monsters
{ APPLY_ATTBONUS_INSECT, 5 }, // +5% vs Insects
{ APPLY_HP_REGEN, 10 }, // +10 HP Regen
},
{ // Bonus Pool 3: Farm Focused
{ APPLY_ITEM_DROP_BONUS, 10 }, // +10% Drop Rate
{ APPLY_EXP_DOUBLE_BONUS, 10 }, // +10% EXP
{ APPLY_GOLD_FIND, 15 }, // +15% Gold
},
};
Common bonus types: APPLY_ATTBONUS_HUMAN, APPLY_ATTBONUS_MONSTER, APPLY_DEF_GRADE_BONUS, APPLY_ITEM_DROP_BONUS, APPLY_EXP_DOUBLE_BONUS, APPLY_GOLD_FIND, APPLY_MAX_HP, APPLY_MAX_SP, APPLY_HP_REGEN, APPLY_SP_REGEN, APPLY_CRITICAL_PCT, APPLY_PENETRATE_PCT, and many more!
Configure items that players receive automatically upon voting:
static std::vector<std::pair<DWORD, int>> s_VOTE4BUFF_ITEM_REWARDS =
{
// Leave empty if you don't want to give any items as rewards
// Format: { vnum, count }
{ 27007, 5 }, // 5x Red Potion (XXL)
{ 50084, 1 }, // 1x Gold Bar
{ 71027, 10 }, // 10x Dragon Coin
};
Control cooldown and pricing when players want to switch between bonus pools:
// Cooldown when changing bonus (does not apply when choosing right after voting)
static const int s_VOTE4BUFF_CHANGE_BONUS_COOLDOWN = 300; // seconds (5 minutes)
// Price when changing bonus (does not apply when choosing right after voting)
static const int s_VOTE4BUFF_CHANGE_BONUS_PRICE = 15000; // yang (0 = free)
Note: After players vote, they can choose a bonus pool for FREE. The cooldown and price only apply when they want to switch pools later without voting again.
Step-by-step instructions for integrating Vote4Buff
Make sure you have backups of your client and server files! File naming convention: Files with __ prefix need modifications, files without prefix can be copied directly.
Open Source/Server/__char.h from the downloaded package.
class CBuffOnAttributes; and add the configuration code above it (see Configuration section)s_VOTE4BUFF_SERVER_ID and s_VOTE4BUFF_API_TOKENbool DragonSoul_RefineWindow_CanRefine(); and add the public method declarationsIntegrate the server-side files from the package:
__affect.h - Modify your existing affect.h with the provided changes__chat_affect.cpp - Add Vote4Buff affect handling__cmd_general.cpp - Add command processing__desc_client.cpp - Client descriptor modificationsNote: Files with __ prefix indicate you need to merge the changes into your existing files.
Compile your game server with the new modifications.
make clean && make
From the Client/root/ folder:
uivote4buff.py to your client's root/ folder
__constInfo.py__game.py__interfaceModule.py__uiAffectShower.pyClient/ui/game/vote4buff/ folder to your pack's ui/game/ directory
Client/uiscript/vote4buffwindow.py to your uiscript folder
Add locale strings for your supported languages from Client/locale/:
__locale_game.txt content to your locale_game.txt
__locale_interface.txt content to your locale_interface.txt
Available languages: EN, DE, ES, PL, TR, RO, IT, PT, HU, GR, CZ
From Source/Client/UserInterface/:
M2WebSocket.cpp and M2WebSocket.h to your UserInterface folder
__ prefix to your existing files
libcurl.dll is in your client directory (32-bit included, download 64-bit if needed)
Vote4Buff doesn't add a default button. You need to call ToggleVote4Buff() from somewhere in your UI. For example:
Or use the included Vote4BuffButton class which creates a draggable icon button
Rebuild your client executable with the new modifications.
Test the integration:
Your players can now vote and receive rewards automatically. The Vote4Buff UI will show them when they can vote, let them choose bonus pools, and display countdown timers for active affects.
Most new players discover servers through toplists, making it an essential marketing tool
Detailed documentation and step-by-step guides make setup a breeze
Straightforward REST API integration process
Client-side vote verification ensures minimal server load
Battle-tested system with built-in fraud prevention
Ensure players really voted for your server before rewards
The system features a clean and intuitive flow that players can easily understand. Best of all, vote checking happens via our API, ensuring you can verify legitimate votes!
From your website or in-game interface
Player is redirected to your server's voting page on our toplist
Player completes CAPTCHA and submits vote
Your server queries our API to verify the vote
Your server grants the in-game reward
Choose your integration method based on your needs:
Complete all-in-one solution with custom UI, WebSocket communication, and automatic reward system.
Build your own implementation using our REST API for maximum flexibility and control.
Create an account and add your server to our toplist at https://metin2-toplist.net/servers/create
Find your unique Server ID and API Token in your server dashboard. These are required for authentication.
Download Vote4Buff for a ready-to-use solution, or integrate our API for custom implementation.
Test the voting system thoroughly, then deploy to your live server.
If you're using the Vote4Buff System (recommended), this API is already integrated! This section is for server owners who want to build custom implementations.
https://metin2-toplist.net/api/check-vote
| Parameter | Type | Required | Description |
|---|---|---|---|
api_token |
string | Yes | Your server's unique API token |
ip |
string | Optional* | Player's IP address (IPv4 or IPv6) |
account_id |
string | Optional* | Player's account ID/username for more accurate tracking |
For best results, use <code>account_id</code> for accurate player tracking. The <code>ip</code> method can be less reliable if players use VPNs or play from different locations.
Direct players to vote using this URL structure:
https://metin2-toplist.net/vote.{lang}/{server_id}-{server_slug}/{account_id}
Examples:
https://metin2-toplist.net/vote.en/123-awesome-server/PlayerName
https://metin2-toplist.net/vote.de/123-awesome-server/PlayerName
https://metin2-toplist.net/vote.tr/123-awesome-server/PlayerName
Supported languages: en, de, es, pl, tr, ro, it, pt, hu, gr, cz
The API returns a JSON response with the following structure:
{
"success": true,
"voted": true,
"last_vote": "2025-11-11T14:30:00Z",
"next_vote_in": 0,
"message": "Vote verified successfully"
}
{
"success": true,
"voted": false,
"message": "No recent vote found"
}
{
"success": false,
"message": "Invalid API token"
}
| Field | Type | Description |
|---|---|---|
success |
boolean | Whether the API request was successful |
voted |
boolean | Whether a valid vote was found (only present if success=true) |
last_vote |
string | ISO 8601 timestamp of the last vote (only if voted=true) |
next_vote_in |
integer | Seconds until next vote is allowed (only if voted=true) |
message |
string | Human-readable message describing the result |
<?php
function checkVote($apiToken, $playerIP) {
$url = "https://metin2-toplist.net/api/check-vote";
$params = http_build_query([
'api_token' => $apiToken,
'ip' => $playerIP
]);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url . '?' . $params);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
return ['success' => false, 'message' => 'API request failed'];
}
return json_decode($response, true);
}
// Usage Example
$apiToken = 'YOUR_API_TOKEN_HERE';
$playerIP = $_SERVER['REMOTE_ADDR']; // Or get from your game server
$result = checkVote($apiToken, $playerIP);
if ($result['success'] && $result['voted']) {
// Player has voted! Give reward
echo "Vote verified! Rewarding player...";
giveReward($playerName); // Your reward function
} else {
echo "No valid vote found. Please vote first!";
}
?>
import requests
import json
def check_vote(api_token, player_ip):
"""
Check if a player has voted for the server
"""
url = "https://metin2-toplist.net/api/check-vote"
params = {
'api_token': api_token,
'ip': player_ip
}
try:
response = requests.get(url, params=params, timeout=10)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
return {'success': False, 'message': f'API request failed: {str(e)}'}
# Usage Example
api_token = 'YOUR_API_TOKEN_HERE'
player_ip = '123.456.789.012'
result = check_vote(api_token, player_ip)
if result.get('success') and result.get('voted'):
print("Vote verified! Rewarding player...")
# Give reward to player
else:
print("No valid vote found. Please vote first!")
#include <curl/curl.h>
#include <string>
#include <sstream>
// Callback function for cURL
static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp) {
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
bool CheckVote(const std::string& apiToken, const std::string& playerIP) {
CURL* curl;
CURLcode res;
std::string readBuffer;
curl = curl_easy_init();
if(curl) {
std::ostringstream url;
url << "https://metin2-toplist.net/api/check-vote"
<< "?api_token=" << apiToken
<< "&ip=" << playerIP;
curl_easy_setopt(curl, CURLOPT_URL, url.str().c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
if(res == CURLE_OK) {
// Parse JSON response (you'll need a JSON library like nlohmann/json)
// Check if readBuffer contains "\"voted\":true"
return readBuffer.find("\"voted\":true") != std::string::npos;
}
}
return false;
}
// Usage in your game server
void OnPlayerRequestReward(const std::string& playerName, const std::string& playerIP) {
std::string apiToken = "YOUR_API_TOKEN_HERE";
if(CheckVote(apiToken, playerIP)) {
// Give reward to player
GiveItemToPlayer(playerName, REWARD_ITEM_VNUM, REWARD_COUNT);
SendNotice("Vote verified! You received your reward!");
} else {
SendNotice("No valid vote found. Please vote first!");
}
}
async function checkVote(apiToken, playerIP) {
const url = new URL('https://metin2-toplist.net/api/check-vote');
url.searchParams.append('api_token', apiToken);
url.searchParams.append('ip', playerIP);
try {
const response = await fetch(url, {
method: 'GET',
headers: {
'Accept': 'application/json'
}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('API request failed:', error);
return { success: false, message: error.message };
}
}
const apiToken = 'YOUR_API_TOKEN_HERE';
const playerIP = '123.456.789.012';
checkVote(apiToken, playerIP).then(result => {
if (result.success && result.voted) {
console.log('Vote verified! Rewarding player...');
// Give reward to player
} else {
console.log('No valid vote found. Please vote first!');
}
});
Always store your API token securely and never expose it in client-side code. API calls should always be made from your server backend.
Add a vote button on your website or an in-game command that directs players to your server's vote page at https://metin2-toplist.net/servers/YOUR-SERVER-SLUG.
When a player requests their reward (via website or in-game command), check if they've voted:
voted is true, grant the rewardBest practices for reward handling:
Solution: Double-check that you're using the correct API token from your server dashboard. Make sure there are no extra spaces or characters.
Possible causes:
Solution: Ensure your server can make outbound HTTPS requests. Check your firewall settings. Implement retry logic with exponential backoff.
Solution: Implement local tracking of rewarded votes. Store the vote timestamp and ensure you only reward each vote once.
Solution: Ensure you're sending the full IPv6 address. Our API supports both IPv4 and IPv6.
Test your integration thoroughly with a test account before deploying to production. Make sure to handle all edge cases and error scenarios.