FiveM için komut dosyası yazmaya başlamak, çok çeşitli olasılıklar ve seyrek yayılmış dokümantasyon göz önüne alındığında biraz zor olabilir. Bu hızlı ve basit kılavuzda, JavaScript'te hızlı bir kaynakla nasıl başlayacağınızı göstermeye çalışacağız.

Önkoşullar

JavaScript ile ilk komut dosyanızı oluşturmadan önce, ayarlamanız ve anlamanız gereken birkaç şey vardır.

Microsoft'un popüler kod düzenleyicisi olan VSCode Visual Studio Code'u kullanacağız. Ancak, istediğiniz herhangi bir kod düzenleyiciyi kullanabilirsiniz.

Kaynaklar

Bir kaynak, basitçe, tek tek başlatılabilen, durdurulabilen ve yeniden başlatılabilen bir dosya koleksiyonudur. Sunucu-veri klasörünüz (zaten bir sunucu kurduğunuzu varsayarsak), içinde resourceszaten birkaç kaynak bulunan bir klasöre sahip olmalıdır .

Kendi kaynaklarınız üzerinde çalışıyorsanız, muhtemelen bir resources/[local]dizin oluşturmak isteyeceksiniz - bu, sunucu-veri kökünü güncellerken Git tarafından göz ardı edilecektir. Orada, sistemi resources/[local]/mymodekullanarak bir gametype oluşturduğumuz için bir klasör oluşturacağız mapmanager.

Araçlarla Yani bir Windows geliştirme sistemini varsayarak artık böyle bir klasör olması gerekir: C:\your\path\to\cfx-server-data\resources\[local]\mymode. Bu klasörü bundan mymodesonra arayacağız .

Manifest dosyaları

Bir kaynak klasörünün (bunu mymodeyukarıda yaptığınızı biliyorsunuz ) FiveM tarafından tespit edilmesi için bir bildirime ihtiyacı olacaktır. Bu bir oyun türü olduğundan, bunun bir oyun türü mapmanagerolduğu gerçeğini öğretmek için bazı ekstra bilgilere de ihtiyacı olacaktır .

Klasörünüzde adlı bir dosya oluşturun fxmanifest.lua(bu, bir JS komut dosyası yazıyor olsanız bile her zaman Lua'dır) mymode. İçine, favori metin düzenleyicinizi kullanarak aşağıdaki metni yerleştirin:

fx_version 'cerulean'
game 'gta5'

author 'An awesome dude'
description 'An awesome, but short, description'
version '1.0.0'

resource_type 'gametype' { name = 'My awesome game type!' }

client_script 'mymode_client.js'

Yapacağınız herhangi bir yeni kaynak muhtemelen en son oyun özelliklerini isteyecektir. Bunun fx_versioniçin var. Daha fazlasını öğrenmeye ihtiyaç duyarsanız, bu dokümantasyon sitesinde başka bir yerde okuyabilirsiniz. Bu kaynağın gta5, rdr3 veya için commonmi olduğunu belirtmek için gamedeğişkeni kullanmalısınız .

resource_typeÖte yandan, söyler mapmanagerbu, aslında, bir oyun türü olduğunu ve bu deniyor o "Benim harika oyun türü!" . Yalnızca 'bağımsız' bir eklenti kaynağı oluşturuyorsanız, muhtemelen bir resource_typesatır eklemek istemezsiniz .

Son olarak, client_scriptkomut dosyası çalışma zamanına istemcinin adlı bir komut dosyası yüklemesi gerektiğini belirtir mymode_client.js. Bu bir Lua betiği olsaydı, derdi mymode_client.luaya da C # olsaydı, muhtemelen olurdu MyModeClient.net.dll, ama şimdilik JavaScript öğretiyoruz, o yüzden unutun gitsin.

Son olarak, biz adlı bir dosya yapmalıdır mymode_client.jsiçinde mymodekaynak klasör şey.

Kaynak bildirim dosyaları hakkında daha fazla bilgi edinmek için, [kaynak bildirimi başvurusu] [bildirim-başvurusu] 'na bakın.

Kod yazma

Artık JavaScript projenizi ve ortamınızı kurduğunuza göre, biraz kod yazmaya başlayabiliriz.

Senin içinde client.jsdosyaya, en aşağıdaki içeriğe koyalım:

const spawnPos = [686.245, 577.950, 130.461];

on('onClientGameTypeStart', () => {
  exports.spawnmanager.setAutoSpawnCallback(() => {
    exports.spawnmanager.spawnPlayer({
      x: spawnPos[0],
      y: spawnPos[1],
      z: spawnPos[2],
      model: 'a_m_m_skater_01'
    }, () => {
      emit('chat:addMessage', {
        args: [
          'Welcome to the party!~'
        ]
      })
    });
  });

  exports.spawnmanager.setAutoSpawn(true)
  exports.spawnmanager.forceRespawn()
});

Bunu [JavaScript runtime] [javascript-runtime] belgelerinde görmüş olabilirsiniz. Bu zor bir sorudur, özellikle birinci sınıf işlevler kavramına alışkın değilseniz. Global / yerel işlevleri kullanarak farklı bir şekilde de yazabilirsiniz - ama bu biraz tuhaf.

Bunu açıklamalı bir sürümle yavaş yavaş inceleyelim.

// Define a local variable called `spawnPos` with a coordinate somewhere on the map
const spawnPos = [686.245, 577.950, 130.461];

/* 
 * Add an event handler for the (local) event called 'onClientGameTypeStart'. It takes
 * no arguments in this case, since our resource is a game type and you can only run one
 * at once, that means this will basically run when we start ourselves on the client. Nice!
 */
on('onClientGameTypeStart', () => {
  /*
   * Set an automatic spawn callback for the spawn manager. Normally, this works using
   * hardcoded spawn points, but since this is a scripting tutorial we'll do it this way.
   * The spawn manager will call this when the player is dead or when forceRespawn is called.
   */
  exports.spawnmanager.setAutoSpawnCallback(() => {
    // spawnmanager has said we should spawn, let's spawn!
    exports.spawnmanager.spawnPlayer({
      // this argument is basically an object containing the spawn location...
      x: spawnPos[0],
      y: spawnPos[1],
      z: spawnPos[2],
      // ... and the model to spawn as.
      model: 'a_m_m_skater_01'
    }, () => {
      /*
       * A callback to be called once the player is spawned in and the game is visible
       * in this case, we just send a message to the local chat box.
      */
      emit('chat:addMessage', {
        args: [
          'Welcome to the party!~'
        ]
      })
    });
  });

  // Enable auto-spawn.
  exports.spawnmanager.setAutoSpawn(true)

  // And force respawn when the game type starts.
  exports.spawnmanager.forceRespawn()
});

İstemci ve sunucu komut dosyaları arasındaki farka hızlı bir şekilde değinmek: FiveM'de yapacağınız şeylerin çoğu istemci komut dosyaları kullanılarak yapılacaktır, çünkü mevcut sürümlerde OneSync kullanmadığınız sürece sunucu komut dosyalarındaki oyun işlevselliği ile etkileşim yoktur . Sunucu komut eylemler meydana metne sahip kullanılmalıdır karşısında (istemci / sunucu olayları kullanarak) istemcileri ve böyle bir kalıcı veritabanında saklanması / yükleme şeyler gibi çeşitli eylemler için bir 'güven kaynağı' sağlamaktır.

Bir oyuncunun doğması neredeyse tamamen oyun etkileşimi olduğundan, bu müşteri tarafında olur. Katılan her oyuncunun , aralarında paylaşılan değişkenler veya bağlam olmadan bilgisayarlarında çalışan her istemci komut dosyasının yerel bir örneği olacaktır .

Bunu çalıştırıyorum

Muhtemelen bu küçük örneği çalıştırmayı umuyorsunuz - umarım zaten çalışan bir FXServer örneğiniz vardır - yoksa bunun için kılavuzu izleyin.

FXServer'ı başlattıktan sonra refresh, konsoldaki komutu yürütün . Bu fxmanifest.lua, yüklediğiniz her kaynak için her bir dosyayı yeniden okuyacaktır , çünkü muhtemelen sunucuyu yeni başlattınız, bu gerçekten gerekli değildir, ancak sunucu zaten çalışıyorsa, bu sadece yapılacak İyi Bir Fikirdir.

Son olarak, start mymodekonsolda çalıştırın ve localhostgeliştirici modunda FiveM istemcisinin kullanışlı düğmesini kullanarak sunucunuza bağlanın (veya localhostdoğrudan bağlantı sekmesine girin veya varsayılan bağlantı noktasını kullandıysanız, FiveM'nin kurulu olduğu bilgisayardaki bu kullanışlı bağlantıya tıklayın) ).

Oyun yüklendikten sonra, kendinizi bir yerde doğarken görmelisiniz - umarım büyük bir sahnede!

Oyunu çalışır durumda tutun (ve belki oyun seçeneklerinde onu kenarlıksız veya pencereli moda ayarlayın) ve Alt-Tab kod düzenleyicinize geri dönün - yapacak daha çok işimiz var!

Kaynakları yeniden başlatma

Kaynağınızı yinelemek için oyununuzu ve sunucunuzu kapatıp her ikisini de yeniden başlatmak aptalca. Elbette kaynağınızı da yeniden başlatabilirsiniz .

Farklı bir yumurtlama noktası deneyelim.

Yerine spawnPoshat (birincisi) mymode/mymode_client.jsaşağıdaki ile:

const spawnPos = [-275.522, 6635.835, 7.425]

Ardından, sunucu konsolunuzda sihirli komutu yürütün restart mymode. Sohbet kutunuzda belirtilen 'Partiye hoş geldiniz! ~' İfadesini (tekrar) görmeli ve sahne yerine bir iskele üzerinde son bulmalısınız.

Bunun üzerine genişleyen

Muhtemelen daha fazlasını yapmak isteyeceksiniz. Bunun için, yerli halkla hiçbir ilgisi olmayan ve aslında 'oyun tanımlı komut dosyası işlevleri' için bir R * etiketi olan yerlileri nasıl çağıracağınızı öğrenmeniz gerekecek . Yerlileri doğru şekilde aramakla ilgili pek çok karmaşıklık var - tam bir referans için, bunun için özel bölüme bakın - ancak şimdilik basit başlayacağız.

Aptalca bir şekilde 'tekrar bu kinaye', bir araba ortaya çıkaracak bir komut vereceğiz. Yerel olarak. Çünkü sunucu başlarken kimse umursamıyor.

Sayfanızın altına mymode_client.jsşu kodu ekleyin:

RegisterCommand('car', (source, args, raw) => {
  // TODO: make a vehicle! fun!
  emit('chat:addMessage', {
    args: [`I wish I could spawn this ${(args.length > 0 ? `${args[0]} or` : ``)} adder but my owner was too lazy. :(`]
  });
}, false);

Zaten başlayarak, bir işleve çağrı görüyoruz. Bu işlevi tanımlamadık. Evet, biz (FiveM ekibinde olduğu gibi) yaptık, ama bu harika yazılmış bir rehber harikası boyunca size, okuyucuya rehberlik ederken değil. Bu, başka bir yerden gelmesi gerektiği anlamına gelir!

Ve tahmin et ne oldu, aslında REGISTER_COMMAND ! Bu bağlantıya tıkladığınızda bu yerel için belgelere yönlendirileceksiniz. Biraz şuna benziyor:

// 0x5fa79b0f
// RegisterCommand
void REGISTER_COMMAND(char* commandName, func handler, BOOL restricted);

Biz esas olarak ikinci satırdaki isme ( RegisterCommandyukarıdaki JS kodunda kullanıldığı gibi) ve argümanlara dikkat edeceğiz .

Gördüğünüz gibi, ilk argüman komut adıdır . İkinci bağımsız değişken, komut işleyicisi olan bir işlevdir (örneğimizde bir ok işlevi ile temsil edilir) ve üçüncü bağımsız değişken, bunun sınırlı bir komut olup olmayacağını belirten bir mantıksaldır .

İşlevin kendisi source, yalnızca sunucuda çalışıyorsanız gerçekten önemli olan bir bağımsız değişken alır (bu, komutu giren oyuncunun istemci kimliği, sahip olunması gerçekten yararlı bir şey olacaktır) ve bir dizi argsbunlar temelde varoluşu veya varoluşu /car zentornoyapmak gibi komuttan sonra girdiğiniz şeylerdir .args["zentorno"]/car zentorno unused["zentorno", "unused"]

Sohbet kutusuna bir mesajın nasıl yazdırılacağını zaten bildiğimizden, aracın adını sohbet kutusuna yazdırarak bir araç yaratmış gibi yapacağız.

Kaynağı yeniden başlatalım ve ne olacağını görelim. Çalıştırın restart mymode, ardından istemci sohbet kutusuna (varsayılan T) yazın /car zentorno. Sohbet kutusunun bunu uygulayamayacak kadar tembel olduğunuzdan şikayet ettiğini göreceksiniz. Onlara kesinlikle tembel olmadığınızı göstereceğiz ve bunu şimdi uygulayacağız.

Bir araba çıkma yeri uygulama

Bu çok fazla standart kod ve biz bunu doğru şekilde yapmak isteyeceğiz çünkü pek çok insan bu örneği kopyalayacak, bu yüzden biraz bunaltıcı görünebilir.

Temel olarak yapacağımız şey:

  1. Geçilen modelin geçerli olup olmadığını kontrol edin. Bu isimde bir araç yokken bir 'patates' yaratmaya çalışmak hiç eğlenceli değil.
  2. Modeli yükleyin. Kullandığınız her modeli açıkça yönetmeniz gerekir, bunlar orijinal olarak R * tarafından tanımlanan kurallardır.
  3. Modelin yüklenmesini bekleyin. Evet, oyun eşzamansız olarak çalışmaya devam edecek.
  4. Oynatıcının yüklendikten sonra nerede olduğunu bulun.
  5. Aracı yaratın! Harika, sonunda yaratıcı olacaksın.
  6. Oynatıcıyı araca koyun.
  7. Temizleyin, çünkü biz düzenli insanlarız ve.

Haydi gidelim!

Biraz önce yapıştırdığınız biti bununla değiştirin ve endişelenmeyin, siz iki kez 'tembel' demeden önce açıklayacağız:

Delay = (ms) => new Promise(res => setTimeout(res, ms));

RegisterCommand('car', async (source, args, raw) => {
  // account for the argument not being passed
  let model = "adder";
  if (args.length > 0)
  {
    model = args[0].toString();
  }

  // check if the model actually exists
  const hash = GetHashKey(model);
  if (!IsModelInCdimage(hash) || !IsModelAVehicle(hash))
  {
    emit('chat:addMessage', {
      args: [`It might have been a good thing that you tried to spawn a ${model}. Who even wants their spawning to actually ^*succeed?`]
    });
    return;   
  }

  // Request the model and wait until the game has loaded it
  RequestModel(hash);
  while (!HasModelLoaded(hash))
  {
    await Delay(500);
  }

  const ped = PlayerPedId();

  // Get the coordinates of the player's Ped (their character)
  const coords = GetEntityCoords(ped);

  // Create a vehicle at the player's position
  const vehicle = CreateVehicle(hash, coords[0], coords[1], coords[2], GetEntityHeading(ped), true, false);

  // Set the player into the drivers seat of the vehicle
  SetPedIntoVehicle(ped, vehicle, -1);

  // Allow the game engine to clean up the vehicle and model if needed
  SetEntityAsNoLongerNeeded(vehicle);
  SetModelAsNoLongerNeeded(model);

  // Tell the player the car spawned
  emit('chat:addMessage', {
    args: [`Woohoo! Enjoy your new ^*${model}!`]
  });
}, false);

Bu, çok sayıda yerli kullanır. Birkaçını birbirine bağlayıp zor kısımları açıklayacağız.

Adım 1: Doğrulama

Araç adını kontrol etmekle başladık. Verilmezse (bu, komut için bağımsız değişken yok), varsayılan olarak adder. Her iki durumda da bir değişkende saklanır.

Dediğimiz yüzden, oyun motoru ile çalışmak için bu araçtan karma anahtarını istiyorum GET_HASH_KEY ve döndürülen saklamak numberdeğişkeninde hash. Ardından IS_MODEL_IN_CDIMAGE kullanarak aracın CD görüntüsünde olup olmadığını kontrol ederiz . Bu temelde 'bu oyuna kayıtlı mı' anlamına gelir. IS_MODEL_A_VEHICLE kullanan bir araç olup olmadığını da kontrol ediyoruz . Kontrollerden biri başarısız olursa, oyuncuya söyler ve komuttan geri döneriz.

Adım 2: Modeli yükleme

Şimdi, 1. adımdaki hash'i kullanarak gerçek araç modelini yüklemek için REQUEST_MODEL'i çağırıyoruz .

3. Adım: Modelin yüklenmesi bekleniyor

Yüklemenin başarılı olup olmadığını kontrol etmek için HAS_MODEL_LOADED çağrılarını döngüye alıyoruz . Bu bir döngü olduğundan ve işbirliği içinde çoklu görev yaptığımız için, oyuna da çalışması için zaman vermeniz gerekecek - aksi takdirde yükleme asla bitmeyecek ve oyun maalesef donacaktır. Lua ve C # 'dan farklı olarak, yerleşik bir çağrı Waitveya Delayçağrıya sahip değiliz, bu yüzden kendi çağrımızı yaratmalıyız. Fonksiyonu Delaybetiğimizin global kapsamında tanımladık . Belirtilen milisaniye miktarını bekler, ardından betiğe geri bir Söz verir.

Model yüklendikten sonra devam edeceğiz.

4. Adım: Oyuncunun pozisyonunu almak

Oyuncuların fiziksel enkarnasyonları, ped"yaya" nın kısaltması olan kendileriyle tanımlanır . Bu bir GTA terimidir ve genellikle 'yaşayan ve bacakları olan her şey' anlamına gelir. Oyuncunun pedini yerel (temelde bu komutu kim çalıştırıyorsa) almak için PLAYER_PED_ID kullanıyoruz .

Ped'e sahip olduktan ve onu bir değişkene kaydettikten sonra, GET_ENTITY_COORDS kullanarak ped oyuncunun konumunu alırız . Ped bir varlık olduğu için (aynı şey araçlar ve diğer birkaç şey için de geçerlidir), bu kişi konumlarını almak için kullanılır. Bu yerel, bir dizi döndürür number[].

Adım 5: Aracın oluşturulması

Bir araç yaratmak için CREATE_VEHICLE kullanıyoruz . Bu arada, GET_ENTITY_HEADING kullanarak oyuncunun yönünü almak için gizlice bir çağrı yaptık , bu da arabanın oyuncuyla aynı yöne bakmasını sağlıyor.

true, falseVarlık oluşturma yerlileri bir kongre bir ağ nesnesi (ile araç yaratmaktır true), ancak bunu bir misyon nesne yapmaz ( false). Genellikle ilkini istersiniz veya başka hiç kimse aracı görmez - ve tam bir R * görev senaryosu yazmadığınız için ikincisini istemezsiniz.

Adım 6: Oynatıcıyı araca yerleştirme

Şu anda bir pedimiz ve bir aracımız olduğu için, ped'i araca yerleştirmek için SET_PED_INTO_VEHICLE kullanabiliriz . Belgelerin dediği gibi, -1aracın sürücü koltuğu.

7. Adım: Temizleme

Oyun, kendi peşinizi temizlemenizden hoşlanıyor ve bu senaryoda artık araç veya modelle hiçbir şey yapmadığımız için oyunun yönetmesine izin vereceğiz. Bu, SET_ENTITY_AS_NO_LONGER_NEEDED ve SET_MODEL_AS_NO_LONGER_NEEDED için kullandığımız şeydir .

Son olarak, oyuncuya yeni aracının keyfini çıkarmasını söyleriz.

Bunu çalıştırıyorum

Sunucu konsolunuzda refresh; restart mymode(evet, noktaları noktalı virgüllerle bölebilirsiniz) ve /car voltic2oyun istemcisinde deneyin (şimdiye kadar yeniden doğmaktan gerçekten sıkılmış olmalı). Artık kendi Rocket Volticinize sahip olacaksınız!

Sunucu komut dosyaları

Muhtemelen sunucuyla etkileşime giren komut dosyaları da yazmak isteyeceksiniz. Bu bölüm hala yazılacak. :-(


Fivem Oyun Sunucunuzu kurmadan önce bir fivem oyun sunucusuna sahip olmanız gerektiğini unutmayın. Fivem Oyun Sunucusu paketlerimizi incelemek için tıklayın.