SA-MP eklentileri ve modülleri geliştirmek için modern, yalnızca başlık içeren ve yüksek seviyeli bir C++ SDK'sı.
- Português: README
- Deutsch: README
- English: README
- Español: README
- Français: README
- Italiano: README
- Polski: README
- Русский: README
- Svenska: README
- SA-MP SDK
- Diller
- İçindekiler
- 1. Giriş ve Tasarım Felsefesi
- 2. Kurulum ve Ortam
- 3. Kapsamlı API Kullanım Kılavuzu
- 3.1. Eklentinin Yaşam Döngüsü
- 3.2. Eklenti Fonksiyonlarını Dışa Aktarma
- 3.3.
Plugin_Public: Pawn Olaylarını Yakalama - 3.4.
Plugin_Native: C++'da Yerel Fonksiyonlar Oluşturma - 3.5.
Plugin_Native_Hook: Mevcut SA-MP Nativelerini Yakalama - 3.6.
Pawn_*Makroları: C++'dan Pawn Fonksiyonlarını Çağırma - 3.7.
Plugin_Module: Dinamik Modül Yönetimi - 3.8.
Plugin_Call: Eklentinin Dahili Nativelerini Çağırma - 3.9. SDK Yardımcı Fonksiyonları
- 4. Derleme ve Dağıtım
- Lisans
SA-MP eklenti API'si bir C programlama arayüzüdür. İşlevsel ve temel olmasına rağmen, düşük seviyeli programlamanın doğasında bulunan zorlukları sunar:
- Manuel Bellek Yönetimi:
amx_Allotveamx_Releasegibi fonksiyonlar, geliştiricinin AMX yığınında belleği açıkça ayırmasını ve serbest bırakmasını gerektirir. Bu, yaygın bir bellek sızıntısı ve çalışma zamanı hatası kaynağıdır. - Zayıf Türleme ve Manuel Dönüşümler: Parametreler bir
celldizisi olarak geçirilir, bu dacell,int,floatvechar*arasında açık (ve genellikle güvensiz) dönüşümleri zorunlu kılar. - Sözcük ve Tekrarlayan Kod: Bir
cell* paramsdizisinden birden çok parametre çıkarmak, string boyutlarıyla uğraşmak ve C++'dan Pawn'a geri çağrılar için AMX yığınını yönetmek tekrarlayan kod gerektirir. - Arayüzün Kırılganlığı: Derleme zamanı doğrulamasının (type safety) olmaması, parametre geçişindeki veya türlerdeki hataların yürütmeye kadar fark edilmeyebileceği, çökmelere veya tanımsız davranışlara neden olabileceği anlamına gelir.
SA-MP SDK bu sorunları güçlü bir C++ soyutlama katmanı sağlayarak ele alır:
- RAII (Resource Acquisition Is Initialization): AMX'de otomatik bellek yönetimi.
Amx_Scoped_Memory, ayrılan belleğin serbest bırakılmasını garanti eder. - Tip Güvenliği: Parametrelerin C++ ve Pawn arasında otomatik ve güvenli dönüşümü.
int,float,std::stringile doğrudan ilgilenirsiniz. - Kompakt ve İdiomatik Sözdizimi: Makrolar ve şablonlar, geleneksel C API'sinden çok modern C++'a benzeyen temiz bir API sağlar.
- Sağlam Yakalama: Gelişmiş bir hooking motoru, Pawn geri çağrılarının şeffaf bir şekilde yakalanmasını (
Plugin_Public), yeni nativelerin oluşturulmasını (Plugin_Native) ve mevcut SA-MP native fonksiyonlarının hooklanmasını ve zincirlenmesini (Plugin_Native_Hook) sağlar. - Yüksek Performans: Soyutlamaların ek yükünü en aza indirmek için derleme zamanı hashing'i (FNV1a), fonksiyon önbelleğe alma ve
thread_localoptimizasyonları yaygın olarak kullanılır.
SDK yalnızca başlık dosyalarından (.hpp, .h) oluşur.
- Avantajlar:
- Basitleştirilmiş Entegrasyon: Oluşturulacak, bağlanacak veya dağıtılacak kütüphaneler yoktur. Sadece başlıkları dahil edin.
- Derleyici Optimizasyonları: Derleyici, SDK ve eklentinizin kodunun tamamını görebilir, agresif inlining ve bağlama zamanı optimizasyonlarına izin verir, bu da daha hızlı ikili dosyalara yol açabilir.
- Etkileri:
- Derleme Süresi: Çok büyük projeler için, SDK kodunun tekrar tekrar dahil edilmesi nedeniyle derleme daha uzun sürebilir. Bu, dahil etme koruyucuları ve C++'ın "yalnızca ihtiyacınız olanı dahil et" doğası ile hafifletilir.
- Uygulama Makroları:
SAMP_SDK_IMPLEMENTATIONmakrosuna olan ihtiyaç, sembol yeniden tanımlarını önlemek için yalnızca başlık modelinin bir sonucudur.
- C++ Derleyicisi: C++17 veya üzeri ile uyumlu.
- GCC (sürüm 8+)
- Clang (sürüm 5+)
- MSVC (Visual Studio 2017+)
- Mimari: x86 (32-bit). SA-MP yalnızca bu mimaride çalışır. SDK, yanlış mimari tespit edildiğinde derleme hataları üretecek
platform.hppiçinde kontroller içerir. - İşletim Sistemi: Windows veya Linux.
Açıklık ve düzen için, SDK'yı bir samp-sdk alt klasöründe düzenlemek yaygındır.
meu_plugin/
├── samp-sdk/
│ ├── // Outros arquivos do SDK
│ └── samp_sdk.hpp // The main header to include
│
├── src/
│ ├── main.cpp // Where SAMP_SDK_IMPLEMENTATION is defined
│ └── my_custom_logic.cpp // Optional, to organize code
│
└── CMakeLists.txt (ou .vcxproj, Makefile)
Bu makroları her zaman samp_sdk.hpp'yi dahil etmeden önce tanımlayın.
- Amaç: Bu
.cppdosyasının eklentinin dışa aktarma fonksiyonlarının (Supports,Load,Unload,AmxLoad,AmxUnload,ProcessTick) uygulamalarını oluşturması gerektiğini derleyiciye bildirir. SDK, bu fonksiyonlar için.defdosyalarına (Windows'ta) veya__attribute__((visibility("default")))bildirimlerine (Linux'ta) gerek kalmadan bu fonksiyonların dışa aktarılmasını otomatik olarak halleder. - Teknik Etki: Bu makro olmadan, bağlayıcı gerekli dışa aktarmaları bulamaz ve SA-MP sunucusu eklentinizi yükleyemez.
- Temel Kural: Bu makroyu tüm projenizde SADECE BİR
.cppdosyasında tanımlayın. Birden fazla dosyada tanımlamak "çift sembol" bağlama hatasına neden olur.
// main.cpp
#define SAMP_SDK_IMPLEMENTATION // The macro makes the SDK export the necessary functions automatically.
#include "samp-sdk/samp_sdk.hpp"
// ... your plugin code ...- Amaç: Pawn komut dosyasının yaşam döngüsü geri çağrılarını (
OnAmxLoad,OnAmxUnload) ve C++'da yeni native'ler oluşturma işlevselliğini (Plugin_Native) etkinleştirir. - Etkinleştirilen İşlevler:
OnAmxLoad(AMX* amx)veOnAmxUnload(AMX* amx)geri çağrıları.Plugin_Nativekullanarak yeni C++ native'lerinin bildirimi ve kaydı.- Kendi eklentiniz içinde
Plugin_Nativeile oluşturulan native'leri çağırmak içinPlugin_Callmakrosu.
- Teknik Etki: Bu makro tanımlandığında, SDK tüm
Plugin_Native'lerinizi otomatik olarak toplar.Supports()fonksiyonunda, projenizde herhangi birPlugin_NativevarsaSUPPORTS_AMX_NATIVESbayrağı otomatik olarak eklenir. - Esneklik: Bu makroyu birden çok
.cppdosyasında tanımlayabilirsiniz. SDK'nın statik kayıt sistemi, farklı derleme birimlerindeki tüm native'leri tek bir global listede birleştirecektir.
// my_natives.cpp (can be a separate file from main.cpp)
#define SAMP_SDK_WANT_AMX_EVENTS // Only to enable Plugin_Native and the OnAmxLoad/OnAmxUnload callbacks
#include "samp-sdk/samp_sdk.hpp"
Plugin_Native(MyCustomNative, AMX* amx, cell* params) {
// ...
return 0;
}- Amaç: Sunucu tarafından düzenli olarak çağrılan
OnProcessTick()geri çağrısını etkinleştirir. - Teknik Etki:
SUPPORTS_PROCESS_TICKbayrağınıSupports()fonksiyonuna otomatik olarak ekler.
// main.cpp
#define SAMP_SDK_IMPLEMENTATION
#define SAMP_SDK_WANT_PROCESS_TICK
#include "samp-sdk/samp_sdk.hpp"
void OnProcessTick() {
// Logic executed every server "tick" (e.g., 20ms)
// Be careful with heavy operations here!
}Bu dosya, MAX_PLAYERS, INVALID_PLAYER_ID, PLAYER_STATE_ONFOOT, WEAPON_DEAGLE, DIALOG_STYLE_LIST gibi bilinen tüm SA-MP sabitlerini ve limitlerini sağlar. samp_sdk.hpp tarafından otomatik olarak dahil edilir ve kodun uyumluluğunu ve okunabilirliğini sağlamak için kullanılmalıdır.
Aşağıdaki fonksiyonlar, eklentinizin SDK tarafından otomatik olarak dışa aktarılan giriş ve çıkış noktalarıdır.
- Açıklama: SA-MP sunucusu tarafından eklentiniz belleğe başarıyla yüklendikten sonra çağrılan ilk fonksiyon.
- Kullanım: Herhangi bir sistemi başlatmak, yapılandırmaları yüklemek, veritabanı bağlantılarını açmak veya modülleri yüklemek (
Plugin_Module) için idealdir. - Dönüş Değeri:
true: Eklenti başarıyla başlatıldı ve yükleme devam ediyor.false: Eklenti başlatılırken bir hata oluştu. Yükleme iptal edilecek ve eklenti boşaltılacaktır.
// main.cpp
bool OnLoad() {
Samp_SDK::Log("Initializing MyPlugin v1.0...");
// Example: Load a module (more details in section 3.6)
if (!Plugin_Module("my_database_module", "plugins/db_connector", "Database Module loaded.")) {
Samp_SDK::Log("ERROR: Failed to load the database module!");
return false; // Aborts loading of the main plugin
}
return true;
}- Açıklama: SA-MP sunucusu tarafından eklentiniz bellekten boşaltılmadan önce çağrılan son fonksiyon.
- Kullanım: Kaynakları temizlemek, bağlantıları kapatmak, durumları kaydetmek ve hiçbir kaynağın sızdırılmamasını sağlamak için idealdir. SDK, modüllerin (
Plugin_Module) boşaltılmasını otomatik olarak yönetir.
// main.cpp
void OnUnload() {
Samp_SDK::Log("MyPlugin unloaded. Releasing resources...");
// No manual action is needed for modules loaded via Plugin_Module;
// the SDK handles it.
}- Açıklama: SA-MP sunucusuna eklentinizin hangi özellikleri desteklediğini ve kullanmak istediğini bildirir.
- Kullanım: Her zaman
SUPPORTS_VERSION(veyaSAMP_PLUGIN_VERSION) döndürün.SUPPORTS_AMX_NATIVESveSUPPORTS_PROCESS_TICKbayrakları, sırasıylaPlugin_Native'ler varsa ve/veyaSAMP_SDK_WANT_PROCESS_TICKmakrosu tanımlıysa SDK tarafından otomatik olarak eklenir. Bu, bakımı basitleştirir ve hataları önler.
// main.cpp
unsigned int GetSupportFlags() {
return SUPPORTS_VERSION; // The SDK automatically adds the necessary flags.
}- Gerektirir:
SAMP_SDK_WANT_AMX_EVENTS - Açıklama: Sunucuda yeni bir Pawn script (bir Gamemode veya Filterscript) yüklendiğinde ve başlatıldığında çağrılır.
- Kullanım: Her AMX scripti için belirli bir mantığa ihtiyacınız varsa veya script başına belirli verileri başlatıyorsanız.
// main.cpp (with SAMP_SDK_WANT_AMX_EVENTS defined)
void OnAmxLoad(AMX* amx) {
// amx represents the new loaded script instance.
Samp_SDK::Log("AMX script loaded: %p", (void*)amx);
}- Gerektirir:
SAMP_SDK_WANT_AMX_EVENTS - Açıklama: Bir Pawn scripti sunucudan boşaltıldığında çağrılır.
- Kullanım: O belirli
AMX*ile ayırdığınız veya ilişkilendirdiğiniz kaynakları temizlemek için.
// main.cpp (with SAMP_SDK_WANT_AMX_EVENTS defined)
void OnAmxUnload(AMX* amx) {
Samp_SDK::Log("AMX script unloaded: %p", (void*)amx);
}- Gerektirir:
SAMP_SDK_WANT_PROCESS_TICK - Açıklama: Sunucu "tick"i başına tekrar tekrar çağrılır (genellikle saniyede 20 kez veya her 50ms'de bir).
- Kullanım: Sürekli arka plan mantığı, zamanlayıcılar, oyuncu olaylarına bağlı olmayan durum güncellemeleri veya veri senkronizasyonu için.
- Dikkat: Sunucuda gecikmeye neden olabileceğinden, burada engelleme veya hesaplama açısından yoğun işlemlerden kaçının.
// main.cpp (with SAMP_SDK_WANT_PROCESS_TICK defined)
static int tick_count = 0;
void OnProcessTick() {
tick_count++;
if (tick_count % 200 == 0) // Every 10 seconds (20 ticks/sec * 10 sec = 200 ticks)
Samp_SDK::Log("Server active for %d seconds.", tick_count / 20);
}SA-MP sunucusunun eklentinizin fonksiyonlarını (Load, Supports, vb.) çağırabilmesi için, bunların DLL dosyasından (Windows) veya SO dosyasından (Linux) "dışa aktarılması" gerekir. SDK, standart yaşam döngüsü fonksiyonlarının dışa aktarılmasını otomatikleştirir, ancak diğer programlarla birlikte çalışabilirlik gerektiğinde kendi özel fonksiyonlarınızı dışa aktarmanız için de araçlar sağlar.
Fonksiyonları dışa aktarma yöntemi derleyiciye göre değişir.
Windows'ta MSVC ile özel fonksiyonları dışa aktarmanın en kolay yolu, exports.hpp içinde tanımlanan Export_Plugin makrosunu kullanmaktır.
- Sözdizimi:
Export_Plugin("Fonksiyon", "Yığın") Fonksiyon: Dışa aktarılacak fonksiyonun tam adı.Yığın: Fonksiyonun parametrelerinin yığında kapladığı toplam bayt miktarı.__stdcallkonvansiyonu için (Windows'ta SDK standardı) hesaplama4 * (Parametre Sayısı)şeklindedir.
#include "samp-sdk/exports.hpp"
// Örnek: İmzasını bilen başka bir program veya eklenti tarafından
// çağrılabilecek özel bir fonksiyonun dışa aktarılması.
const char* SAMP_SDK_CALL GetPluginVersion() {
return "1.0.0";
}
Export_Plugin("GetPluginVersion", "0");Warning
Export_Plugin Sınırlaması
Bu makro yalnızca MSVC derleyicisi (Visual Studio) ile çalışır. GCC ve Clang gibi diğer derleyiciler tarafından yok sayılan Microsoft'a özgü bir #pragma direktifi kullanır.
GCC ve Clang için (Windows veya Linux'ta), dışa aktarma platform.hpp içinde tanımlanan SAMP_SDK_EXPORT makrosu tarafından yönetilir. Bunu sadece fonksiyon tanımının önüne yerleştirirsiniz.
- Mekanizma: Linux'ta
__attribute__((visibility("default")))ekler. Windows'ta GCC/Clang ile__attribute__((dllexport))ekler. - Kullanım: SDK zaten tüm yaşam döngüsü fonksiyonlarına (
Load,Unload, vb.)SAMP_SDK_EXPORTuygular, dolayısıyla bunların dışa aktarılması bu derleyiciler için tamamen otomatiktir. Kendi özel fonksiyonlarınız için aynısını yapmanız yeterlidir.
// GCC/Clang için fonksiyonun SAMP_SDK_EXPORT ile tanımlanması yeterlidir.
SAMP_SDK_EXPORT const char* SAMP_SDK_CALL GetPluginVersion() {
return "1.0.0";
}Plugin_Public makrosu, Pawn geri çağrılarını C++ kodunuzda almak için birincil köprüdür.
Plugin_Public(PublicAdı, Tip1 Param1, Tip2 Param2, ...)- Bildirdiğiniz C++ fonksiyonunun adı, Pawn geri çağrısının adıyla aynı olmalıdır (ör:
OnPlayerConnect). - C++ parametre türleri (
int,float,std::string) SDK tarafından otomatik olarak dönüştürülür.
// Intercepts OnPlayerText(playerid, text[])
Plugin_Public(OnPlayerText, int playerid, std::string text) {
Samp_SDK::Log("Player %d said: %s", playerid, text.c_str());
return PUBLIC_CONTINUE;
}SDK, AMX'in cell stack'inden okuma ve belirtilen C++ türlerine dönüştürme işlemlerini otomatik olarak halleder:
int: Doğrudancell'den dönüştürülür.float:amx::AMX_CTOFkullanılarakcell'den dönüştürülür.std::string: SDK, AMX'deki string adresini okur, C++'da birstd::stringayırır ve içeriği kopyalar.
Plugin_Public fonksiyonunuz tarafından döndürülen değer çok önemlidir ve geri çağrının yürütme akışını belirler:
return PUBLIC_CONTINUE;(değer1): Geri çağrı yürütmesinin devam etmesi gerektiğini belirtir. Bu geri çağrıyı yakalayan başka eklentiler varsa, bunlar çağrılacaktır (ters yükleme sırasına göre). Ardından, Pawn scriptindeki orijinalpublicçağrılacaktır.return PUBLIC_STOP;(değer0): Geri çağrı yürütmesinin durdurulması gerektiğini belirtir. Bu olay için başka hiçbir eklenti (daha düşük öncelikli olanlar) veya Pawn scriptindeki orijinalpublicçağrılmayacaktır. Bu, SA-MP'nin varsayılan davranışını "geçersiz kılan" veya "engelleyen" bir sistem uygulamak için idealdir.
// main.cpp
Plugin_Public(OnPlayerCommandText, int playerid, std::string cmdtext) {
if (cmdtext == "/freeze") {
Pawn_Native(TogglePlayerControllable, playerid, 0); // Freezes the player
Pawn_Native(SendClientMessage, playerid, -1, Plugin_Format("Player %d frozen.", playerid));
return PUBLIC_STOP; // Prevents the command from being processed by other scripts.
}
return PUBLIC_CONTINUE; // Allows other commands to be processed.
}Plugin_Public'in gelişmiş bir özelliği "Hayalet Geri Çağrılar" desteğidir. Bu, Pawn geri çağrısını, gamemode veya filterscript'in .amx scriptinde mevcut olmasa bile yakalayabileceğiniz anlamına gelir. SDK, sunucuyu C++ hook'unuzu yine de çağırması için "kandırır". Bu, dahili geri çağrılar veya Pawn scriptinde bir public'in varlığına bağlı kalmadan yeni işlevler oluşturmak için kullanışlıdır.
// You can define a callback that the Pawn script does not have, but your plugin will hear it.
Plugin_Public(OnMyCustomInternalEvent, int data1, float data2) {
Samp_SDK::Log("Custom internal event received: %d, %.2f", data1, data2);
return PUBLIC_CONTINUE;
}
// To "trigger" this event from another point in your C++ code:
// Pawn_Public(OnMyCustomInternalEvent, 123, 45.67f);
// The call will go to your Plugin_Public above, even if there is no OnMyCustomInternalEvent in Pawn.Plugin_Native, Pawn işlevselliğini yüksek performanslı C++ koduyla genişletmenize olanak tanır.
Plugin_Native(NativeAdı, AMX* amx, cell* params)- C++ fonksiyonu tam olarak bu imzaya sahip olmalıdır:
cell NativeAdı(AMX* amx, cell* params). NativeAdı, Pawn scriptlerinin kullanacağı addır.
// Pawn: native GetPlayerPingAverage(playerid);
Plugin_Native(GetPlayerPingAverage, AMX* amx, cell* params) {
// ... Implementation ...
return 0;
}Note
amx_Register'ı manuel olarak çağırmanız gerekmez. SDK, tüm Plugin_Native'lerinizi (samp_sdk.hpp'yi dahil etmiş ve SAMP_SDK_WANT_AMX_EVENTS'i tanımlamış herhangi bir .cpp dosyasında) otomatik olarak algılar ve her yüklenen AMX scriptinde (OnAmxLoad) bunları otomatik olarak kaydeder.
- Açıklama: Birden çok parametreyi sırayla çıkarmak için daha basit bir yardımcı.
- Kullanım:
Register_Parameters(değişken1, değişken2, ...) - Sınırlamalar: Yalnızca girdi parametreleri içindir. İsteğe bağlı parametreleri veya dizine göre erişimi işlemez.
- Desteklenen Türler:
int,float,std::string.
// Pawn: native SetPlayerSkinAndMoney(playerid, skinid, money);
Plugin_Native(SetPlayerSkinAndMoney, AMX* amx, cell* params) {
int playerid, skinid, money;
Register_Parameters(playerid, skinid, money); // Extracts the 3 parameters
Pawn_Native(SetPlayerSkin, playerid, skinid);
Pawn_Native(GivePlayerMoney, playerid, money);
return 1;
}- Açıklama: Bir nativenin parametrelerine erişmek için nesne yönelimli bir arayüz sağlayan bir sarıcı sınıfı. Karmaşık senaryolar için daha güçlüdür.
- Oluşturma:
Native_Params p(amx, params);
- Açıklama: Native'e geçirilen parametre sayısını döndürür.
- Kullanım: İsteğe bağlı parametreleri işlemek için önemlidir.
- Açıklama: Dizine göre bir giriş parametresini çıkarır ve
Ttürüne dönüştürür. - Desteklenen Türler:
int,float,std::string.
// Pawn: native GetPlayerWeaponAmmo(playerid, weaponid = -1);
Plugin_Native(GetPlayerWeaponAmmo, AMX* amx, cell* params) {
Native_Params p(amx, params);
int playerid = p.Get<int>(0);
int weaponid = (p.Count() > 1) ? p.Get<int>(1) : Pawn_Native(GetPlayerWeapon, playerid);
return Pawn_Native(GetPlayerAmmo, playerid, weaponid);
}- Açıklama: Bir referans parametresinin (Pawn işaretçisi) değerini alır ve
out_value'ya depolar. - Kullanım: Pawn'dan referans yoluyla geçirilen değerleri okumak için.
- Dönüş Değeri: AMX adresi geçerliyse
true, aksi takdirdefalse.
// Pawn: native CheckPlayerStats(playerid, &Float:health, &money);
Plugin_Native(CheckPlayerStats, AMX* amx, cell* params) {
Native_Params p(amx, params);
int playerid = p.Get<int>(0);
float health = 0.0f;
int money = 0;
// Gets the values from references (Pawn passed addresses)
p.Get_REF(1, health); // Reads the value of Float:health
p.Get_REF(2, money); // Reads the value of money
Samp_SDK::Log("Player %d, Health: %.1f, Money: %d", playerid, health, money);
// Now, modify them
health = 50.0f;
money += 100;
// And writes them back to Pawn's memory
p.Set_REF(1, health);
p.Set_REF(2, money);
return 1;
}- Açıklama: Bir referans parametresini okumak için bir
std::optional<T>döndürür. C++17 ve üzeri için daha güvenlidir.
- Açıklama: Bir
Tdeğerini bir Pawn referans parametresine yazar (Pawn'ın geçirdiği adres). - Kullanım: Referans yoluyla geçirilen değerleri değiştirmek için, Pawn'ın değişikliği görmesini sağlar.
- Dönüş Değeri: Yazma başarılı olursa
true, aksi takdirdefalse.
Plugin_Nativefonksiyonunuz bircelldöndürmelidir.- Bir
intveyabooldöndürmek için,cell'e bir cast kullanın. - Bir
floatdöndürmek içinamx::AMX_FTOC(benim_float)kullanın.
// Returns a bool
Plugin_Native(IsPlayerSpawned, AMX* amx, cell* params) {
int playerid;
Register_Parameters(playerid);
return (Pawn_Native(GetPlayerState, playerid) == PLAYER_STATE_SPAWNED) ? 1 : 0;
}
// Returns a float
Plugin_Native(GetPlayerMaxHealth, AMX* amx, cell* params) {
return amx::AMX_FTOC(100.0f); // Returns 100.0f
}Plugin_Native_Hook makrosu, mevcut herhangi bir SA-MP native fonksiyonunun veya diğer eklentilerin davranışını yakalamanıza ve değiştirmenize olanak tanır. Bu, sunucunun varsayılan mantığını genişletmek veya değiştirmek için güçlü bir mekanizmadır.
Plugin_Native_Hook(NativeAdı, AMX* amx, cell* params)- C++ fonksiyonu tam olarak bu imzaya sahip olmalıdır:
cell NativeAdı(AMX* amx, cell* params). NativeAdı, hooklamak istediğiniz native'in tam adı olmalıdır (ör:SendClientMessage,SetPlayerPos).
// Intercepts the SendClientMessage native
Plugin_Native_Hook(SendClientMessage, AMX* amx, cell* params) {
// ...
return Call_Original_Native(SendClientMessage); // Important to call the original
}Note
Plugin_Native_Hook için amx_Register'ı manuel olarak çağırmanız veya SAMP_SDK_WANT_AMX_EVENTS'i özellikle tanımlamanız gerekmez. SDK, hook'larınızı otomatik olarak algılar ve kaydeder. Bir AMX scriptinin ilk yürütülmesinde, SDK, native tablosundaki native işaretçisini, Plugin_Native_Hook fonksiyonunuza yönlendiren bir "trampoline" ile değiştirir. Bu süreç, birden çok eklentinin güvenli hook zincirini garanti eder.
Plugin_Native_Hook fonksiyonunuz içinde, orijinal fonksiyonu (veya zincirdeki bir sonraki hook'u) çağırmak için Call_Original_Native(NativeAdı) makrosunu KULLANMALISINIZ. Bu, aşağıdakiler için hayati öneme sahiptir:
- İşlevselliği Korumak: Orijinalini çağırmazsanız, hook'lanan native diğer eklentiler veya sunucu için çalışmayı durdurur.
- Hook Zincirlemesi: Birden çok eklentinin aynı native'i hooklamasına ve tüm hook'ların sırayla yürütülmesine olanak tanır.
- Dönüş Değeri Manipülasyonu:
Call_Original_Native'in dönüş değerini, hook fonksiyonunuzdan döndürmeden önce inceleyebilir ve hatta değiştirebilirsiniz.
// Example: Blocking SendClientMessage if it contains a specific word
Plugin_Native_Hook(SendClientMessage, AMX* amx, cell* params) {
Native_Params p(amx, params);
// Extract parameters for analysis
int playerid = p.Get<int>(0);
// int color = p.Get<int>(1); // We don't need the color for this logic
std::string message = p.Get_String(2); // Get the message string
if (message.find("BADWORD") != std::string::npos) {
Samp_SDK::Log("MESSAGE BLOCKED for playerid %d: %s", playerid, message.c_str());
return 0; // Returns 0 (false) to Pawn, indicating the message was not sent.
// And most importantly, we DO NOT call Call_Original_Native, blocking the message.
}
// If the message does not contain the prohibited word, we call the original native
// and return its value, ensuring that the message is sent normally
// and that other hooks (if they exist) are executed.
return Call_Original_Native(SendClientMessage);
}#define SAMP_SDK_IMPLEMENTATION
// SAMP_SDK_WANT_AMX_EVENTS is not strictly necessary for hooks, but it's common to have OnAmxLoad/Unload
// #define SAMP_SDK_WANT_AMX_EVENTS
#include "samp-sdk/samp_sdk.hpp"
// Hook for the CreateVehicle native
Plugin_Native_Hook(CreateVehicle, AMX* amx, cell* params) {
Native_Params p(amx, params);
// Extract the CreateVehicle native parameters for inspection
int modelid = p.Get<int>(0);
float x = p.Get<float>(1);
float y = p.Get<float>(2);
float z = p.Get<float>(3);
float angle = p.Get<float>(4);
int color1 = p.Get<int>(5);
int color2 = p.Get<int>(6);
int respawn_delay = p.Get<int>(7);
bool addsiren = p.Get<bool>(8);
Samp_SDK::Log("HOOK: CreateVehicle called! Model: %d, Pos: (%.2f, %.2f, %.2f)", modelid, x, y, z);
// Example of how to *modify* an input parameter
// If the model is 400 (Landstalker), we change it to 401 (Bravura)
if (modelid == 400) {
// We directly modify the 'params' array for the original call
params[1] = static_cast<cell>(401); // The model is at position 0 of the parameter array (params[1])
Samp_SDK::Log(" -> Model 400 changed to 401 before creation.");
}
// We call the original native (or the next hook in the chain) with the potentially modified parameters
cell original_retval = Call_Original_Native(CreateVehicle);
Samp_SDK::Log("HOOK: CreateVehicle returned: %d (Vehicle ID)", (int)original_retval);
// You can modify the return value here before returning it to Pawn.
// Example: if vehicle creation failed, return a custom invalid ID.
if ((int)original_retval == INVALID_VEHICLE_ID) {
Samp_SDK::Log(" -> Vehicle creation failed in the original native.");
return -1; // Return a different value to Pawn.
}
return original_retval; // Return the value that the original native returned (or the modified one above).
}
unsigned int GetSupportFlags() {
return SUPPORTS_VERSION;
}
// Minimal implementations for the lifecycle
bool OnLoad() {
Samp_SDK::Log("Native Hook Example Plugin loaded!");
return true;
}
void OnUnload() {
Samp_SDK::Log("Native Hook Example Plugin unloaded!");
}
// These callbacks will only be present if SAMP_SDK_WANT_AMX_EVENTS is defined
/*void OnAmxLoad(AMX* amx) {
Samp_SDK::Log("AMX Load detected: %p", (void*)amx);
}
void OnAmxUnload(AMX* amx) {
Samp_SDK::Log("AMX Unload detected: %p", (void*)amx);
}*/Warning
Girdi parametrelerini değiştirmek için cell* params dizisini doğrudan değiştirmek dikkat gerektirir. Parametrelerin sırasını ve türünü anladığınızdan emin olun. Çoğu kullanım durumu için, incelemek için p.Get(...) ve zinciri devam ettirmek için Call_Original_Native(...) yeterlidir. params'ı doğrudan değiştirmek, yalnızca parametrenin bir değer olduğunu ve orijinal çağrı için değiştirilmesi gerektiğini bildiğinizde yapılmalıdır. Stringler ve diziler için, değişiklik daha karmaşıktır ve genellikle mevcut adrese yazmak veya yeniden tahsis etmek için amx::Set_String kullanmayı içerir; bu da yeni değerlerle Pawn_Native aracılığıyla native'i çağırmak ve orijinal çağrıyı iptal etmek için hook'unuzdan 0 döndürmekle yönetmek daha kolay olabilir.
Bu makrolar Plugin_Public ve Plugin_Native'in tersidir: C++ kodunuzun Pawn fonksiyonlarını çağırmasına izin verirler.
- Amaç: C++'dan SA-MP native fonksiyonlarını (veya diğer eklentilerin native'lerini) çağırmak için önerilen yol.
- Mekanizma: SDK'nın dahili önbelleğinde native işaretçisini arar (
Amx_Register_Detourtarafından doldurulur). Bulunursa, native'i birAmx_Sandboxortamında (sahte ve yalıtılmış bir AMX örneği) yürütür. - Performans: En verimli olanıdır, çünkü pahalı
publicaramasını önler ve doğrudan native işaretçisiyle etkileşime girer.
- Amaç: Bir Pawn scriptindeki belirli bir public fonksiyonu çağırır.
- Mekanizma:
Amx_Managertarafından yönetilenAMX*örnekleri arasında döner, adı ilepublic'i arar ve yürütür. - Performans: Arama ve gerçek
amx_ExecnedeniylePawn_Native'den daha az verimlidir. Genelliklepublic'lernative'lerden daha yavaştır. - Kullanım: Gamemode/Filterscript'lerinizde native olmayan özel olayları çağırmak için idealdir.
- Amaç: Fonksiyonun native mi yoksa public mi olduğunu tahmin etmeye çalışan bir kolaylık makrosu.
- Mekanizma: İlk olarak,
Pawn_Nativeolarak çağırmayı dener. Başarısız olursa (native bulunamazsa),Pawn_Publicolarak çağırmayı dener. - Performans: Fonksiyon native ise, çift arama denemesi nedeniyle
Pawn_Native'den biraz daha yavaş olabilir.public'ler için performansPawn_Publicile aynıdır. - Kullanım: Native mi yoksa public mi olduğundan emin olmadığınız fonksiyonlar için veya birini diğerinden sonra deneme tekrarlayan koddan kaçınmak için.
- Fonksiyon Adı: Her zaman Pawn fonksiyonunun adını doğrudan, tırnak işaretleri olmadan kullanın. SDK bunu dahili olarak string'e dönüştürecektir.
- Parametreler: C++ parametrelerini doğrudan geçirin.
// Correct:
Pawn_Native(SetPlayerPos, playerid, 100.0f, 200.0f, 300.0f);
// Incorrect (but would technically work due to hashing, avoid):
Pawn_Native("SetPlayerPos", playerid, 100.0f, 200.0f, 300.0f); SDK, C++ türlerinizi AMX'in cell formatına dönüştürür, gerektiğinde belleği yönetir:
int,bool,long,enum->cellfloat,double->cell(amx::AMX_FTOCkullanılarak)const char*,std::string,std::string_view(C++17+) ->cell(AMX'de bellek ayırır, string'i kopyalar veamx_addradresini geçirir)
void Send_Formatted_Message(int playerid, const std::string& msg) {
Pawn_Native(SendClientMessage, playerid, 0xFFFFFFFF, msg);
}Bu, kolaylık ve güvenlik için önemli bir anahtar işlevdir. Bir işaretçi (referans) bekleyen Pawn fonksiyonları için, SDK tüm bellek ayırma/serbest bırakma ve veri kopyalama sürecini otomatikleştirir.
- Nasıl kullanılır: Değişkeninizi referans yoluyla (
&) geçirin. - Mekanizma: SDK, AMX yığınında bellek ayırır, bu AMX adresini Pawn fonksiyonuna geçirir, Pawn fonksiyonunun bu adresi doldurmasını bekler, değeri geri okur ve AMX belleğini serbest bırakır. Hepsi şeffaf bir şekilde.
std::string&ile: SDK, string için AMX'de standart bir tampon (256 hücre) ayırır.
void Get_Player_Location(int playerid) {
float x, y, z;
int interiorid, worldid;
std::string name;
Pawn_Native(GetPlayerPos, playerid, x, y, z);
Pawn_Native(GetPlayerInterior, playerid, interiorid);
Pawn_Native(GetPlayerVirtualWorld, playerid, worldid);
Pawn_Native(GetPlayerName, playerid, name, MAX_PLAYER_NAME);
Samp_SDK::Log("Location of %s (ID:%d): Pos(%.2f, %.2f, %.2f) Interior:%d World:%d", name.c_str(), playerid, x, y, z, interiorid, worldid);
}Tüm Pawn_* çağrıları bir Callback_Result nesnesi döndürür. Bu nesne, Pawn çağrısının sonucu için güvenli bir sarıcıdır.
Callback_Result() noexcept: Varsayılan yapılandırıcı, başarısızlığı gösterir (success_ = false).Callback_Result(bool success, cell value) noexcept: Değeri ile başarı veya başarısızlık için yapılandırıcı.explicit operator bool() const: Çağrının başarılı olup olmadığını kontrol etmek içinif (result)kullanılmasına izin verir.operator cell() const: Değeri almak için sonucucell'e dönüştürmeye izin verir.float As_Float() const: Sonucufloatolarak almak için kolaylık.cell Value() const: Hamcelldeğerini döndürür.bool Success() const: Pawn çağrısı başarılı olursatruedöndürür.int Get_Amx_Error() const: Çağrı başarısız olursa AMX hata kodunu döndürür (başarılı için 0).
// Example: Getting a player's health.
// The native GetPlayerHealth(playerid, &Float:health) expects a playerid and a reference to health.
int playerid = 0; // Example player ID
float player_health = 0.0f;
// We call GetPlayerHealth, passing playerid and player_health by reference.
// The SDK will handle the marshalling for the 'health' output parameter.
Callback_Result result = Pawn_Native(GetPlayerHealth, playerid, player_health);
if (result) { // Checks if the call was successful (operator bool)
// The value returned by result.As_Float() or result (operator cell)
// would be the return value of the *native*, not the output parameter.
// The health value has already been updated in 'player_health' due to output parameter marshalling.
Samp_SDK::Log("Player %d has %.1f health.", playerid, player_health);
}
else {
// The call failed, perhaps the player does not exist or the native was not found.
Samp_SDK::Log("Error getting player %d health. AMX code: %d", playerid, result.Get_Amx_Error());
}
// For natives that return a value and use output parameters (less common, but possible),
// you would use both:
// Callback_Result other_result = Pawn_Native(SomeNative, param1, output_param, param2);
// if (other_result) {
// cell returned_value = other_result;
// // output_param is already updated
// }Plugin_Module makrosu, eklentinizin diğer eklentiler için bir "yükleyici" görevi görmesini sağlayarak modüler ve genişletilebilir bir mimari oluşturur. Bu şekilde yüklenen bir modül, kendi olay yaşam döngüsü ana eklenti tarafından yönetilen birinci sınıf bir eklenti olarak ele alınır.
Plugin_Module(const char* base_filename, const char* module_directory, const char* optional_success_message)base_filename: Modül dosyasının uzantısız temel adı (ör:my_module.dllveyamy_module.soiçin"my_module"kullanın). SDK otomatik olarak uygun.dllveya.souzantısını ekleyecektir.module_directory: Modül dosyasının bulunduğu dizinin yolu (ör:"plugins/my_custom_modules"). Dosya adını buraya eklemeyin. SDK tam yolu birleştirecektir (module_directory/base_filename.ext).optional_success_message: Modül başarıyla yüklenirse sunucu konsoluna günlüklenmek üzere isteğe bağlı bir mesaj.
// main.cpp, inside OnLoad()
// Loads the 'core_logic.dll' (or 'core_logic.so') module
// which is located in the server's 'modules/custom/' folder.
if (!Plugin_Module("core_logic", "modules/custom", "Core Logic Module loaded successfully!"))
return (Samp_SDK::Log("FATAL ERROR: Failed to load 'core_logic' module!"), false);
// Loads the 'admin_system.dll' (or 'admin_system.so') module
// which is located directly in the server's 'plugins/' folder.
if (!Plugin_Module("admin_system", "plugins", "Administration Module activated."))
Samp_SDK::Log("WARNING: Administration Module could not be loaded.");Bir modül, normal bir eklenti gibi Load, Unload ve Supports fonksiyonlarını dışa aktarmalıdır. SDK, modülün yaşam döngüsünü aşağıdaki gibi yönetir:
-
Yükleme:
Plugin_Moduleçağrıldığında, SDK:- Tam dosya yolunu oluşturur (ör:
modules/custom/core_logic.dll). - İkili dosyayı yüklemek için
Dynamic_Library(LoadLibrary/dlopen) kullanır. - Modülün TÜM yaşam döngüsü fonksiyonlarına yönelik işaretçileri alır:
- Zorunlu:
Load,Unload,Supports. Herhangi biri eksikse, modülün yüklenmesi başarısız olur. - İsteğe Bağlı:
AmxLoad,AmxUnload,ProcessTick.
- Zorunlu:
- Ana eklentinin
ppData'sını geçirerek modülünLoadfonksiyonunu çağırır. Loadtruedöndürürse, modül dahili yüklü modüller listesine eklenir.
- Tam dosya yolunu oluşturur (ör:
-
Olay Yönlendirme: Ana eklenti, olayları tüm yüklü modüllere otomatik olarak yönlendirir.
Important
Olayların doğru bir şekilde yönlendirilmesi için ana eklenti (Plugin_Module'ı çağıran eklenti) bu olayları alacak şekilde yapılandırılmış olmalıdır.
AmxLoadveAmxUnload'ın modüllerde çalışması için, ana eklentininSAMP_SDK_WANT_AMX_EVENTSmakrosunu tanımlaması gerekir.ProcessTick'in modüllerde çalışması için, ana eklentininSAMP_SDK_WANT_PROCESS_TICKmakrosunu tanımlaması gerekir.
- Boşaltma: Ana eklentinizin
OnUnload'u sırasında, SDKPlugin_Modulearacılığıyla yüklenen tüm modülleri boşaltır. Bu, yükleme sırasının tersine (en son yüklenen, ilk boşaltılır) yapılır, bu da bağımlılıkları yönetmek ve kaynakların doğru bir şekilde serbest bırakılmasını sağlamak için kritik öneme sahiptir.
- Kod Düzenlemesi: Büyük eklentileri daha küçük, yönetilebilir bileşenlere ayırın, her biri kendi modül dosyasında.
- Yeniden Kullanılabilirlik: Kodun yeniden kullanımını teşvik ederek farklı eklentiler tarafından kullanılabilecek genel modüller (ör: bir veritabanı modülü, gelişmiş bir günlük sistemi modülü) oluşturun.
- Bağımsız Bileşenler: Tamamen olay odaklı ve bağımsız modüller oluşturun. Bir modülün kendi
Plugin_Native'leri,Plugin_Public'leri yakalayabilir ve kendiOnProcessTickmantığına sahip olabilir, bağımsız bir eklenti olarak çalışırken bir ana bilgisayar tarafından yüklenir. - Dinamik Güncellemeler: Kontrollü senaryolarda, ana eklentiyi veya tüm sunucuyu yeniden derlemeye ve yeniden başlatmaya gerek kalmadan sisteminizin parçalarını (bir modül
.dllveya.sodosyasını değiştirerek) güncellemeye olanak tanır (ancak bu, sıkı bir sürüm yönetimi ve uyumluluk gerektirir).
Kendi eklentiniz içinde tanımlanmış bir Plugin_Native'i çağırmak için Plugin_Call kullanın.
Plugin_Call(NativeAdı, Param1, Param2, ...)- Avantaj: AMX native dizisinde native'i arama ek yükünü önler. SDK, kendi native'leri için ad hash'lerinden fonksiyon işaretçilerine doğrudan bir harita tutar, bu da onları dahili olarak çağırmanın en hızlı yolu haline getirir.
- Gerektirir:
SAMP_SDK_WANT_AMX_EVENTS.
// main.cpp
Plugin_Native(InternalCheckPlayerLevel, AMX* amx, cell* params) {
int playerid;
Register_Parameters(playerid);
// Logic to check level
return (playerid % 2 == 0) ? 1 : 0; // Example: even level for even IDs
}
void Check_All_Players_Level() {
for (int i = 0; i < MAX_PLAYERS; ++i) {
if (Pawn_Native(IsPlayerConnected, i)) {
if (Plugin_Call(InternalCheckPlayerLevel, i)) // Calls its own native
Samp_SDK::Log("Player %d is at a high level!", i);
}
}
}- Açıklama: Sunucu konsoluna ve
server_log.txtdosyasına mesajlar yazdırır.logprintfiçin güvenli bir sarıcı. - Kullanım: Hata ayıklama, durum mesajları ve hatalar için.
- Mekanizma: Dahili olarak, SDK
ppData[PLUGIN_DATA_LOGPRINTF]aracılığıylalogprintfişaretçisini alır. Fonksiyon, stringin biçimlendirmesini güvenli bir şekilde halleder.
// Anywhere in your plugin
Samp_SDK::Log("The plugin was initialized with a value %d and a string '%s'.", 123, "test");- Açıklama: Bir string'i güvenli bir şekilde biçimlendirir (
sprintfbenzeri) ve birstd::stringdöndürür. Bu, eklentiniz içinde kullanılmak üzere stringleri biçimlendirmenin önerilen ve en idiomatik yoludur. - Kullanım:
Samp_SDK::Log,Pawn_Native(SendClientMessage, ...), veya C++ kodunuzdaki diğer string ihtiyaçları için biçimlendirilmiş mesajlar oluşturmak için idealdir. - Mekanizma: Dahili olarak,
Plugin_FormatbirSamp_SDK::Formatçağıran bir makrodur. Biçimlendirilmiş stringin tam boyutunu belirlemek içinvsnprintfkullanır ve yeterli kapasiteye sahip birstd::stringayırır, arabellek taşmalarını önler.
int playerid = 0; // Example ID
int health = 50;
Pawn_Native(SendClientMessage, playerid, 0xFFFFFFFF, Plugin_Format("Player %d, your current health is %d.", playerid, health));
// Can also be used for internal logs
Samp_SDK::Log(Plugin_Format("DEBUG: Processing status for ID %d", playerid));- Açıklama:
Samp_SDKad alanı içinde bulunan, string biçimlendirme için temel uygulama fonksiyonu. - Kullanım: Genellikle kullanıcı tarafından doğrudan çağrılmaz.
Plugin_Formatmakrosu, bu fonksiyon için bir kolaylık olarak sağlanır ve diğer SDK makrolarının (Plugin_Public,Plugin_Native) adlandırma kuralıyla uyumludur. Yalnızca belirli bir nedenlePlugin_Formatmakrosundan kaçınmak istiyorsanız doğrudan çağırırsınız.
// Example of how Samp_SDK::Format works, but prefer Plugin_Format
std::string raw_status = Samp_SDK::Format("For internal use only: %d.", 42);- Açıklama: Bir AMX string adresini (
cell amx_addr) bir C++std::string'ine dönüştürür. - Kullanım: Esas olarak
Plugin_NativevePlugin_Native_Hookiçinde,Register_ParametersveyaNative_Paramstarafından otomatik olarak dönüştürülmeyen stringlere erişmeniz gerektiğinde (ör: Pawn parametresi birconststringise ve otomatik Marshalling içinPlugin_NativeveyaPlugin_Public'ınızdastd::stringolarak bildirilmemişse).
Plugin_Native(PrintRawAmxString, AMX* amx, cell* params) {
Native_Params p(amx, params);
cell amx_string_addr = p.Get<cell>(0); // Gets the string address in AMX
std::string cpp_string = Samp_SDK::Get_String(amx, amx_string_addr);
Samp_SDK::Log("String from AMX: %s", cpp_string.c_str());
return 1;
}- Eklentiniz x86 (32-bit) mimarisi için derlenmelidir.
- Desteklenen Platformlar: Windows (.dll) ve Linux (.so).
- Yeni bir "Dynamic-Link Library (DLL)" projesi oluşturun.
- Proje ayarlarında "Çözüm Platformu"nu x86 olarak ayarlayın.
- C++ Dil Standardının en az C++17 olduğundan emin olun.
# For a plugin named 'my_plugin.so' from 'main.cpp'
g++ -m32 -shared -std=c++17 -O2 -fPIC -Wall -Wextra -Wl,--no-undefined main.cpp -o my_plugin.so-m32: 32-bit için derler.-shared: Paylaşılan bir kütüphane (.so) oluşturur.-std=c++17: C++ standardını C++17 olarak ayarlar (C++20 olabilir, ancak minimum gereksinim C++17'dir).-O2: Optimizasyon seviyesi 2.-fPIC: Paylaşılan kütüphaneler için gerekli olan konumdan bağımsız kod üretir.-Wall -Wextra: Hataları yakalamaya yardımcı olmak için ek uyarıları etkinleştirir.-Wl,--no-undefined: Tanımsız semboller varsa kütüphane oluşturmayı engeller.
# For a plugin named 'my_plugin.dll' from 'main.cpp'
g++ -m32 -shared -std=c++17 -O2 -static-libstdc++ -static-libgcc -Wl,--no-undefined main.cpp -o my_plugin.dll-static-libstdc++: C++ standart kütüphanesini statik olarak bağlar. Eklentinizin kullanıcının sisteminde bulunmayabilecek derleyiciye özgü çalışma zamanı DLL'lerine bağımlı olmasını önlemek için önemlidir.-static-libgcc: GCC kütüphanesini statik olarak bağlar.
- Dosya Adı: Eklentiniz
.dll(Windows) veya.so(Linux) uzantısına sahip olmalıdır. Örn:my_plugin.dll. - Konum: Derlenmiş dosyayı SA-MP sunucunuzun
plugins/klasörüne yerleştirin. - server.cfg: Eklentinizin adını (Windows ise uzantısız)
server.cfgdosyasındakipluginssatırına ekleyin.plugins my_plugin (if Linux, my_plugin.so)
Copyright © AlderGrounds
Bu yazılım MIT Lisansı ("Lisans") şartları altında lisanslanmıştır; bu yazılımı Lisans şartlarına uygun olarak kullanabilirsiniz. Lisansın bir kopyasını şu adresten edinebilirsiniz: MIT License
Bu lisans, bu yazılımın ve ilgili dokümantasyon dosyalarının bir kopyasını edinen herhangi bir kişiye ücretsiz olarak aşağıdaki hakları vermektedir:
- Yazılımın kopyalarını kullanma, kopyalama, değiştirme, birleştirme, yayınlama, dağıtma, alt lisans verme ve/veya satma hakkı
- Yazılımın sağlandığı kişilerin de aynısını yapmasına izin verme hakkı (aşağıdaki koşullara tabi olmak kaydıyla)
Yazılımın tüm kopyaları veya önemli parçaları şunları içermelidir:
- Yukarıdaki telif hakkı bildirimi
- Bu izin bildirimi
- Aşağıdaki sorumluluk reddi
Yazılım ve ilgili tüm dokümantasyon telif hakkı yasaları ile korunmaktadır. AlderGrounds yazılımın orijinal telif haklarını elinde tutmaktadır.
YAZILIM "OLDUĞU GİBİ" SAĞLANMAKTADIR, HİÇBİR TÜRDE GARANTİ VERİLMEMEKTEDİR, AÇIK VEYA ZIMNİ, TİCARİ ELVERİŞLİLİK, BELİRLİ BİR AMACA UYGUNLUK VE İHLAL ETMEME GARANTİLERİ DAHİL ANCAK BUNLARLA SINIRLI OLMAMAK ÜZERE.
HİÇBİR KOŞULDA YAZARLAR VEYA TELİF HAKKI SAHİPLERİ HERHANGİ BİR İDDİA, HASAR VEYA DİĞER YÜKÜMLÜLÜKLERDEN SORUMLU TUTULAMAZ, İSTER SÖZLEŞME KAPSAMINDA, HAKSIZ FİİL VEYA BAŞKA BİR ŞEKİLDE OLSUN, YAZILIMDAN VEYA YAZILIMIN KULLANIMINDAN VEYA DİĞER İŞLEMLERDEN KAYNAKLANAN DURUMLAR İÇİN.
MIT Lisansı hakkında detaylı bilgi için: https://opensource.org/licenses/MIT