ข้ามไปยังเนื้อหา
CXGdocs.คู่มือ
Cxg gtfatเชื่อม CXG-GTFAT กับ resource อื่น
CXG DOCUMENTATION

เชื่อม CXG-GTFAT กับ resource อื่น

ไฟล์ bridge/*.lua เป็นจุดที่แก้ไขได้เพื่อเชื่อมสิทธิ์ การบันทึกถาวร การแจ้งเตือน สถานี และรูปแบบข้อมูลรูปลักษณ์ patch สำหรับเมนูเป็นการแก้ไขด้วยตนเองสำหรับบางเวอร์ชัน resource จะไม่แก้ resource อื่นตอนติดตั้ง

เมนูรูปลักษณ์

มี patch ที่เตรียมไว้สำหรับ repository และ revision ต่อไปนี้:

เมนูrevision ต้นทางสิ่งที่ต้องทำเพิ่ม
illenium-appearance1b003ec169b15f145d519438ba7c6454bf746f27ใช้ patch Lua สำหรับบันทึก component
fivem-appearanceb06da32881ed49042909b38a778c10dd9bd9eaedใช้ patch และสร้าง TypeScript bundle ของเกมใหม่ด้วยขั้นตอน build:game
qb-clothing8cca4009dd473ab30c30e443ecad50830b816ed7ใช้ patch ที่จุดบันทึก skin และ outfit
esx_skin / skinchangerfe59ca0bd6da59e2ec6eb4a8d06ece312e96ae7apath ของ patch อ้างอิงจากโฟลเดอร์รากของ repository esx_core

โฟลเดอร์ integrations ในแพ็กเกจมีไฟล์ illenium-appearance.patch, fivem-appearance.patch, qb-clothing.patch และ skinchanger.patch ซึ่งจะไม่ถูกใช้อัตโนมัติ ใน checkout สำหรับพัฒนาเมนู ให้ตรวจ patch ที่ตรงกันก่อนใช้:

โค้ด
git apply --check /ruta/al/parche-correcto.patch
git apply /ruta/al/parche-correcto.patch

หากตรวจไม่ผ่าน ให้หยุดและปรับการเปลี่ยนแปลงให้เข้ากับเวอร์ชันที่ติดตั้ง อย่าฝืนใช้ patch fork และ revision ที่ใหม่กว่าอาจแตกต่างกัน patch ของ fivem-appearance ต้องสร้าง bundle ใหม่ด้วยขั้นตอน build:game ตามคำแนะนำของเมนูนั้น patch เหล่านี้ไม่ได้รับรองทุกเวอร์ชันและใช้แทนการทดสอบในเซิร์ฟเวอร์ไม่ได้

ขณะบันทึก ระบบจะล้าง technical decal เพื่อไม่ให้เมนูบันทึกเป็นตัวเลือกปกติของผู้เล่น เมนูที่มีตารางรูปลักษณ์ของตนเองต้องเรียกการล้างนี้ ณ จุดบันทึก น้ำหนักจะจัดเก็บแยกจากชุด

บันทึกรูปลักษณ์ที่กำหนดเอง

client export SanitizeAppearance คืนค่าสำเนาของรูปลักษณ์ รูปแบบที่รองรับ ได้แก่ components, qb และ esx:

โค้ด
local appearanceCopy = exports['CXG_GTFAT']:SanitizeAppearance(
    ped,
    appearance,
    'components'
)

GuardarApariencia(appearanceCopy)

GuardarApariencia เป็นตัวอย่างการเรียก ให้แทนด้วยฟังก์ชันบันทึกของเมนู components รองรับ array ของ component หรือ object ที่มี property components; แต่ละ component ใช้ component_id, drawable, texture และอาจมี palette รูปแบบ qb ใช้ field decals ที่มี item และ texture; esx ใช้ decals_1 และ decals_2 export คืนค่าสำเนาแบบลึกและเก็บ field อื่นไว้ โดยไม่เปลี่ยน ped ชั่วคราว หาก adapter ของรูปแบบล้มเหลวหรือไม่รู้จักรูปแบบ จะคืนสำเนาเดิมและบันทึกข้อมูลวินิจฉัย

ลงทะเบียน preview ped

หากเมนูใช้ ped สำหรับดูตัวอย่างที่แยกจากตัวละคร ให้ลงทะเบียน preview ของตัวละครที่ใช้อยู่ ยกเลิกการลงทะเบียนก่อนลบ entity:

โค้ด
local previewPed = ObtenerPreviewActual()

if previewPed and DoesEntityExist(previewPed) then
    exports['CXG_GTFAT']:RegisterPreviewPed(previewPed)
end

-- Al cerrar o cancelar el menú, antes de eliminar el ped:
exports['CXG_GTFAT']:UnregisterPreviewPed(previewPed)
EliminarPreview(previewPed)

ObtenerPreviewActual และ EliminarPreview เป็นตัวอย่างการเรียก ให้แทนด้วยฟังก์ชันของเมนู ลงทะเบียนเฉพาะ preview ของตัวละครปัจจุบัน ไม่ใช่ ped ในโลกหรือ preview ของตัวละครอื่น อีกทางเลือกคือกำหนด Config.GetPreviewPed ให้คืนค่า ped ปัจจุบันหรือ nil RefreshAppearance(previewPed) ขอให้ประเมิน ped ที่จัดการอยู่ใหม่ แต่ไม่ได้เปิด Fat เอง

export สำหรับ resource ฝั่งเซิร์ฟเวอร์

server export เป็น API ที่มีสิทธิ์สูงสำหรับ resource ฝั่งเซิร์ฟเวอร์อื่น อย่าส่งต่อโดยตรงจาก event ที่ไคลเอนต์เรียกได้

โค้ด
local playerSource = source -- ID del jugador en el servidor
local kg, err = exports['CXG_GTFAT']:GetWeight(playerSource)
if kg == nil then
    print('No hay un peso confirmado:', err)
end

local appliedKg, setError = exports['CXG_GTFAT']:SetWeight(playerSource, 92.5)
if appliedKg == nil then
    print('No se pudo fijar el peso:', setError)
end

local addedKg, addError = exports['CXG_GTFAT']:AddWeight(playerSource, -2.0)
if addedKg == nil then
    print('No se pudo sumar peso:', addError)
end

local resetKg, resetError = exports['CXG_GTFAT']:ResetWeight(playerSource)
if resetKg == nil then
    print('No se pudo restablecer el peso:', resetError)
end

อาร์กิวเมนต์ source คือ ID ผู้เล่นบนเซิร์ฟเวอร์ ไม่ใช่ค่าที่ไคลเอนต์ส่งมา ทุกค่าเป็น kg GetWeight คืนค่าน้ำหนักหรือ nil, error SetWeight และ AddWeight คืนค่าน้ำหนักที่ใช้แล้วซึ่งปรับให้อยู่ในมาตรฐานเป็น kg หรือ nil, error; SetWeight ปฏิเสธค่านอกช่วงและปัดเป็นขั้นใกล้ที่สุด โดยกรณีกึ่งกลางปัดขึ้น AddWeight รับการเพิ่มค่าติดลบได้ ResetWeight บันทึก defaultKg และคืนค่าน้ำหนักที่ใช้แล้วเป็น kg ด้วย แต่ไม่ลบค่าที่จัดเก็บ

เปิด UI ให้ผู้เล่นจาก resource ฝั่งเซิร์ฟเวอร์อื่นได้ดังนี้:

โค้ด
local playerSource = source -- ID del jugador en el servidor
local opened, err = exports['CXG_GTFAT']:OpenWeightUI(playerSource)
if not opened then
    print('No se pudo abrir la báscula:', err)
end

ส่ง station ID ซึ่งไม่บังคับเป็นอาร์กิวเมนต์ที่สองได้: OpenWeightUI(source, 'gimnasio') หากไม่ระบุสถานี จะใช้ policy การเข้าถึงของคำสั่ง แม้ปิดการลงทะเบียนคำสั่งไว้ ผลลัพธ์ true ยืนยันว่าได้รับอนุญาตและส่งคำขอเปิดแล้ว ไม่ได้ยืนยันว่าไคลเอนต์แสดง UI แล้ว

server export

Exportการใช้งาน
GetWeight(source)คืน kg หรือ nil, error
SetWeight(source, kg)ตั้งน้ำหนักที่ตรวจสอบแล้วและคืน kg ที่ใช้ หรือ nil, error
AddWeight(source, deltaKg)เพิ่มค่าความต่างและคืน kg ที่ใช้ หรือ nil, error
ResetWeight(source)บันทึกและคืนค่าน้ำหนักเริ่มต้นที่ตั้งไว้เป็น kg หรือ nil, error
GetWeightSettings()คืนสำเนาขีดจำกัดที่ใช้อยู่
OpenWeightUI(source, stationId?)ขอเปิดเครื่องชั่งภายใต้ policy ที่ใช้
RefreshCharacter(source)โหลด identity และน้ำหนักใหม่หลัง framework เปลี่ยนเป็นตัวละครที่ต้องการ
ReconcileStorage(source)ปรับข้อมูลจัดเก็บหลังสถานะไม่แน่นอน เมื่อ adapter ยืนยันการเขียนก่อนหน้าได้

RefreshCharacter ไม่บังคับสำหรับระบบหลายตัวละคร ให้เรียกหลัง framework ทำให้ identity ที่ต้องการพร้อมใช้งาน resource ไม่ได้เชื่อม Qbox ให้อัตโนมัติ

ข้อผิดพลาดที่อาจพบ: not_ready, invalid_source, player_unavailable, character_unavailable, invalid_weight, out_of_range, permission_denied, context_denied, busy, storage_failed, storage_timeout, storage_unknown หรือ not_synced อย่าถือว่าข้อผิดพลาดด้านการจัดเก็บคือน้ำหนักที่ยืนยันแล้ว และอย่าลองเขียนซ้ำอัตโนมัติเมื่อได้ storage_timeout หรือ storage_unknown

client export

โค้ด
local kg, err = exports['CXG_GTFAT']:GetWeight()
local settings = exports['CXG_GTFAT']:GetWeightSettings()
local isOpen = exports['CXG_GTFAT']:IsWeightUIOpen()
local closed = exports['CXG_GTFAT']:CloseWeightUI()
local status, statusError = exports['CXG_GTFAT']:GetFatStatus()
local reserved, reservedError = exports['CXG_GTFAT']:GetReservedDecals(PlayerPedId())

GetWeight คืนค่า nil, 'not_synced' จนกว่าจะได้รับค่าที่ยืนยันจากเซิร์ฟเวอร์ GetFatStatus(ped?) และ GetReservedDecals(ped) ให้ข้อมูลแบบอ่านอย่างเดียว ไม่ได้ยืนยันว่า geometry แสดงผลแล้ว GetReservedDecals ใช้ซ่อน decal ที่สงวนไว้จากเมนูได้ RefreshAppearance(previewPed?) อัปเดตเฉพาะรูปลักษณ์ที่จัดการของผู้เล่นหรือ preview ที่ลงทะเบียนไว้

RegisterPreviewPed(ped) และ UnregisterPreviewPed(ped) ให้เมนูส่ง entity preview ให้ selector ได้ มีเพียง resource ที่ลงทะเบียน ped เท่านั้นที่ยกเลิกการลงทะเบียนได้ preview ที่ลงทะเบียนจะถูกล้างเมื่อ resource เจ้าของหยุดทำงาน

SanitizeAppearance(ped, appearance, format) คืนสำเนาของรูปลักษณ์; nil, error ไม่ใช่ตัวบอกความล้มเหลว RegisterPreviewPed และ UnregisterPreviewPed คืน true เมื่อทำงานสำเร็จ และคืน false หากลงทะเบียนหรือลบ ped ไม่ได้

bridge ที่แก้ไขได้

ไฟล์การปรับใช้
bridge/server.luaCanAccess, identity, การโหลด/บันทึกน้ำหนัก และ server hook
bridge/client.luapreview ped, การแจ้งเตือน และ hook การเปลี่ยนน้ำหนัก/หน้าจอ
bridge/interaction.luaลงทะเบียนสถานีกับ target หรือแทนที่ TextUI
bridge/appearance.luaอ่าน/เขียน decal ในรูปแบบรูปลักษณ์เฉพาะ

โดยค่าเริ่มต้น CanAccess รู้จักเฉพาะ ace และ everyone สำหรับ jobs, groups หรือ custom ให้ใช้ API จริงของเซิร์ฟเวอร์เขียนการตรวจสอบ และคืนค่า true เท่านั้นเมื่ออนุญาต กรณี exception และค่าอื่นจะปฏิเสธ ฟิลด์ policy ของ job, group และ custom จะถูกตีความโดย adapter

ผู้ให้บริการจัดเก็บแบบกำหนดเองต้องใช้ signature LoadWeight(characterId, context, done), SaveWeight(characterId, kg, context, done) และหากต้องปรับการเขียนที่ไม่แน่นอน ให้ใช้ ReconcileWeight(characterId, context, done) การโหลดเรียก done(true, kg) (ใช้ kg = nil เมื่อไม่มีข้อมูล) หรือ done(false, 'storage_failed') การบันทึกเรียก done(true) หลังยืนยันแล้วเท่านั้น มิฉะนั้นเรียก done(false, 'storage_failed') การปรับข้อมูลเรียก done(true, true) เฉพาะเมื่อมั่นใจว่าไม่มีการเขียนก่อนหน้าที่จะเสร็จภายหลัง หากรับรองไม่ได้ ให้เรียก done(false, 'storage_unknown') สำหรับการบันทึกแบบ asynchronous จริง ให้ตั้ง AsyncStorage = true; callback ต้องทำงานเสร็จในบริบท FiveM ที่รองรับการรอ API ให้เวลาได้สูงสุด 10 วินาทีก่อนแจ้ง timeout ห้ามลองซ้ำอัตโนมัติหลัง storage_timeout; ให้ปรับข้อมูลผ่านผู้ให้บริการที่รับรองว่าการเขียนก่อนหน้าจะไม่ถูกนำไปใช้ภายหลัง ห้ามกำหนดว่า asynchronous หากผู้ให้บริการคืนค่าก่อนเริ่มหรือจัดคิวการเขียน

hook OnWeightChanged, OnCharacterChanged, OnUIOpened, OnUIClosed และ Log ใช้สังเกตหรือบันทึกการเปลี่ยนแปลง hook ไม่ได้ให้สิทธิ์และไม่ย้อนการดำเนินการที่ยืนยันแล้ว

ตรวจสอบก่อนเปิดใช้งาน

ต้องตรวจ patch และ adapter กับ resource และเวอร์ชันที่ใช้จริงบนเซิร์ฟเวอร์ ก่อนเปิดระบบให้ผู้เล่น:

  1. ทดสอบการเปลี่ยน Normal/Fat ซ้ำด้วยตัวละคร freemode ชายและหญิง
  2. ขณะเปิด Fat ให้บันทึกและโหลดรูปลักษณ์กับชุดอีกครั้ง ยืนยันว่า technical decal ไม่ถูกบันทึกเป็นตัวเลือกปกติ และน้ำหนักยังแยกจากชุด
  3. เมื่อเปิดการบันทึกแยกตามตัวละคร ให้รีสตาร์ต resource และเชื่อมต่อใหม่ ยืนยันว่าตัวละครเดิมได้น้ำหนักคืน และตัวละครอื่นไม่รับค่านั้นไป
  4. เปิดเมนูรูปลักษณ์โดยลงทะเบียน preview แล้วตรวจว่าเป็นตัวละครปัจจุบัน เมื่อยกเลิกหรือปิดเมนู ให้ยกเลิกการลงทะเบียนก่อนลบ entity

ต้องตรวจสอบบนเซิร์ฟเวอร์ของคุณเพื่อยืนยันชุดเมนู framework และเสื้อผ้าที่ใช้จริง การมี patch ไม่ได้ยืนยันผลลัพธ์เหล่านี้ด้วยตัวเอง

CXG · เอกสารรากฐานที่ดี ความเป็นไปได้ไม่มีที่สิ้นสุด
เชื่อม CXG-GTFAT กับ resource อื่น · cxg-gtfat · CXG Docs