FiveM पार्किंग सिस्टम: रियलिस्टिक वाहन पार्किंग स्क्रिप्ट्स
अपने FiveM शहर में यथार्थवादी पार्किंग जोड़ें। सड़क पार्किंग, भुगतान किए गए लॉट, जब्ती नियम और वाहन अव्यवस्था रोकने के लिए सर्वश्रेष्ठ पार्किंग स्क्रिप्ट।
Agency Scripts
Agency Scripts के संस्थापक और प्रमुख डेवलपर
पार्किंग सिस्टम आर्किटेक्चर को समझना
एक पार्किंग सिस्टम किसी भी FiveM रोलप्ले सर्वर में गहराई और यथार्थवाद जोड़ता है, खिलाड़ियों को उनके वाहनों को छोड़ने के लिए निर्दिष्ट क्षेत्र प्रदान करके और नियमों की अनदेखी करने पर परिणाम लागू करके। इसके मूल में, एक पार्किंग सिस्टम यह ट्रैक करता है कि कौन से पार्किंग स्पॉट भरे हुए हैं, वाहनों को कितनी देर तक पार्क किया गया है, और मीटर या परमिट के माध्यम से भुगतान को संभालता है। सिस्टम में सर्वर-साइड लॉजिक शामिल है जो स्थिति को ट्रैक करता है और भुगतान प्रक्रिया करता है, क्लाइंट-साइड डिटेक्शन जो पार्किंग ज़ोन में प्रवेश और निकास को पहचानता है, और एक वैकल्पिक NUI इंटरफ़ेस जो मीटर की स्थिति और भुगतान विकल्प दिखाता है। एक अच्छी तरह से लागू पार्किंग सिस्टम आपके मौजूदा पुलिस और टोइंग स्क्रिप्ट्स के साथ भी एकीकृत होता है ताकि अवैध रूप से पार्क किए गए वाहनों को अधिकृत खिलाड़ियों द्वारा टिकट किया जा सके या जब्त किया जा सके।
पार्किंग ज़ोन और स्थानों को परिभाषित करना
पार्किंग ज़ोन मानचित्र पर बहुभुज या बॉक्स-आकार के क्षेत्र के रूप में परिभाषित होते हैं, प्रत्येक में विशिष्ट निर्देशांकों और हेडिंग के साथ व्यक्तिगत पार्किंग स्पॉट होते हैं। सर्वर प्रशासकों को कोड संशोधित किए बिना नए पार्किंग क्षेत्र जोड़ने की अनुमति देने के लिए एक कॉन्फ़िगरेशन फ़ाइल का उपयोग करें। प्रत्येक ज़ोन के अलग नियम हो सकते हैं, जैसे मुफ्त पार्किंग, मीटर पार्किंग, या केवल परमिट वाले क्षेत्र। यहाँ एक व्यावहारिक ज़ोन कॉन्फ़िगरेशन संरचना है:
Config.ParkingZones = {
['pillbox_lot'] = {
label = 'Pillbox Medical Parking',
type = 'metered', -- 'free', 'metered', 'permit'
rate = 50, -- $ per hour (metered only)
maxTime = 120, -- minutes max parking
blip = {sprite = 357, color = 3, scale = 0.6},
spots = {
{coords = vector4(310.5, -590.2, 43.3, 70.0), occupied = false},
{coords = vector4(313.8, -591.6, 43.3, 70.0), occupied = false},
{coords = vector4(317.1, -593.0, 43.3, 70.0), occupied = false},
{coords = vector4(320.4, -594.4, 43.3, 70.0), occupied = false},
},
fineAmount = 250, -- fine for overtime or illegal parking
},
['legion_street'] = {
label = 'Legion Square Parking',
type = 'metered',
rate = 75,
maxTime = 60,
blip = {sprite = 357, color = 3, scale = 0.6},
spots = {
{coords = vector4(215.2, -810.5, 30.7, 160.0), occupied = false},
{coords = vector4(212.6, -810.5, 30.7, 160.0), occupied = false},
},
fineAmount = 350,
},
}
यह vector4 फॉर्मेट x, y, z निर्देशांक के साथ हेडिंग कोण भी संग्रहीत करता है, यह सुनिश्चित करता है कि वाहन सही दिशा की ओर पार्क किए गए हैं। occupied फ्लैग रनटाइम पर सर्वर द्वारा प्रबंधित होता है और पुनःप्रारंभ के बीच सहेजा नहीं जाता क्योंकि वाहन गेराज सिस्टम डेटाबेस के माध्यम से अलग से ट्रैक किए जाते हैं। प्रत्येक स्थान के लिए स्पॉट काउंट यथार्थवादी रखें, क्योंकि एक छोटे क्षेत्र में बहुत अधिक स्पॉट होने से वाहन क्लिपिंग समस्याएं होती हैं।
पार्किंग मीटर टाइमर सिस्टम
मीटर सिस्टम ट्रैक करता है कि प्रत्येक वाहन कितनी देर से पार्क किया गया है और तदनुसार शुल्क लेता है। जब कोई खिलाड़ी मीटर वाले क्षेत्र में पार्क करता है, तो वे मीटर के साथ इंटरैक्ट करते हैं ताकि उनका सत्र शुरू हो, अवधि चुनते हैं और अग्रिम भुगतान करते हैं। सर्वर सत्र शुरू होने का समय, भुगतान की गई अवधि, प्लेट नंबर, और क्षेत्र ID संग्रहीत करता है। एक सर्वर-साइड टाइमर थ्रेड समय-समय पर सभी सक्रिय मीटर सत्रों की जांच करता है और समाप्त हो चुके सत्रों को प्रवर्तन के लिए चिह्नित करता है। यहाँ मुख्य मीटर लॉजिक है:
local ActiveMeters = {} -- keyed by plate
RegisterNetEvent('parking:server:startMeter', function(plate, zoneId, duration)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end
local zone = Config.ParkingZones[zoneId]
if not zone or zone.type ~= 'metered' then return end
-- Calculate cost based on duration in minutes
local hours = duration / 60
local cost = math.ceil(hours * zone.rate)
if Player.Functions.RemoveMoney('cash', cost, 'parking-meter') then
ActiveMeters[plate] = {
zone = zoneId,
startTime = os.time(),
paidUntil = os.time() + (duration * 60),
plate = plate,
owner = Player.PlayerData.citizenid,
}
TriggerClientEvent('parking:client:meterStarted', src, duration, cost)
else
TriggerClientEvent('QBCore:Notify', src, 'Not enough cash', 'error')
end
end)
-- Check for expired meters every 60 seconds
CreateThread(function()
while true do
Wait(60000)
local now = os.time()
for plate, meter in pairs(ActiveMeters) do
if now > meter.paidUntil then
-- Meter expired, issue fine
IssueParkingFine(plate, meter.zone, meter.owner)
ActiveMeters[plate] = nil
end
end
end
end)
60 सेकंड का टाइमर रिज़ॉल्यूशन पार्किंग प्रवर्तन के लिए पर्याप्त है बिना अनावश्यक CPU लोड बनाए। मीटर सत्रों को मेमोरी में संग्रहीत करें बजाय डेटाबेस के क्योंकि वे अस्थायी होते हैं और सर्वर पुनः आरंभ के बाद जीवित रहने की आवश्यकता नहीं होती। जब सर्वर पुनः आरंभ होता है, तो सभी मीटर रीसेट हो जाते हैं, जो स्वीकार्य है क्योंकि अधिकांश फ्रेमवर्क में वाहन भी पुनः आरंभ पर गैराज लौटते हैं।
वाहन पहचान और स्थान आवंटन
जब कोई वाहन पार्किंग स्पॉट में प्रवेश करता है या छोड़ता है तो इसका पता लगाने के लिए क्लाइंट साइड पर आवधिक निकटता जांच आवश्यक होती है। पूरे नक्शे के हर स्पॉट की जांच करने के बजाय निकटवर्ती क्षेत्रों के सभी स्पॉट्स के खिलाफ दूरी-आधारित जांच का उपयोग करें। केवल तब पता लगाने वाला लूप चलाएं जब प्लेयर वाहन में हो और कॉन्फ़िगर किए गए पार्किंग ज़ोन के पास हो। यह सामान्य गेमप्ले के दौरान CPU उपयोग को न्यूनतम रखता है:
-- client/detection.lua
local nearestZone = nil
local currentSpot = nil
CreateThread(function()
while true do
local sleep = 1000
local ped = PlayerPedId()
local inVehicle = IsPedInAnyVehicle(ped, false)
if inVehicle then
local veh = GetVehiclePedIsIn(ped, false)
local vehCoords = GetEntityCoords(veh)
for zoneId, zone in pairs(Config.ParkingZones) do
local firstSpot = zone.spots[1]
local zoneDist = #(vehCoords - vector3(firstSpot.coords.x,
firstSpot.coords.y, firstSpot.coords.z))
if zoneDist < 50.0 then
sleep = 200
nearestZone = zoneId
for i, spot in ipairs(zone.spots) do
local spotPos = vector3(spot.coords.x, spot.coords.y, spot.coords.z)
local dist = #(vehCoords - spotPos)
if dist < 3.0 then
local speed = GetEntitySpeed(veh)
if speed < 0.5 then
currentSpot = {zone = zoneId, index = i}
ShowParkingPrompt(zone)
end
end
end
break
end
end
else
nearestZone = nil
currentSpot = nil
end
Wait(sleep)
end
end)
0.5 की गति जांच यह सुनिश्चित करती है कि पार्किंग प्रॉम्प्ट केवल तब दिखाई दे जब वाहन लगभग स्थिर हो, जिससे UI का झिलमिलाना रोका जाता है जब खिलाड़ी एक क्षेत्र से गुजरता है। ज़ोन के पास 200ms की अनुकूली नींद अंतराल और अन्य जगहों पर 1000ms प्रदर्शन के साथ प्रतिक्रिया क्षमता का संतुलन करता है। कई पार्किंग ज़ोन वाले सर्वरों के लिए, प्रत्येक टिक पर हर ज़ोन के माध्यम से पुनरावृत्ति से बचने के लिए स्थानिक हैश या क्वाडट्री का उपयोग करने पर विचार करें।
पार्किंग जुर्माना और प्रवर्तन प्रणाली
जब मीटर समाप्त हो जाता है या वाहन गैरकानूनी रूप से पार्क किया जाता है, तो सिस्टम वाहन मालिक से जुड़ी जुर्माना जारी करता है। जुर्माने को डेटाबेस तालिका में संग्रहित किया जाता है और जब मालिक अगली बार लॉगिन करता है या अपना वाहन पुनः प्राप्त करता है तो दिखाया जाता है। पुलिस खिलाड़ी भी कमांड या टारगेट इंटरैक्शन का उपयोग करके मैन्युअल रूप से पार्किंग टिकट जारी कर सकते हैं। जुर्माना रिकॉर्ड में प्लेट, राशि, जारी करने का कारण, और टाइमस्टैम्प शामिल होता है:
function IssueParkingFine(plate, zoneId, citizenid)
local zone = Config.ParkingZones[zoneId]
local amount = zone and zone.fineAmount or 250
MySQL.insert([[
INSERT INTO parking_fines (plate, citizenid, amount, reason, zone, issued_at)
VALUES (?, ?, ?, ?, ?, NOW())
]], {plate, citizenid, amount, 'Expired parking meter', zoneId})
-- Notify owner if online
local Player = QBCore.Functions.GetPlayerByCitizenId(citizenid)
if Player then
TriggerClientEvent('QBCore:Notify', Player.PlayerData.source,
'Parking fine issued: $' .. amount, 'error')
end
end
-- Police manual ticket command
RegisterNetEvent('parking:server:issueTicket', function(plate, reason)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end
if Player.PlayerData.job.name ~= 'police' then return end
local vehicle = MySQL.query.await(
'SELECT citizenid FROM player_vehicles WHERE plate = ?', {plate}
)
if vehicle and vehicle[1] then
IssueParkingFine(plate, 'manual', vehicle[1].citizenid)
TriggerClientEvent('QBCore:Notify', src, 'Ticket issued for ' .. plate, 'success')
end
end)
फाइन सिस्टम को अपने वाहन पुनःप्राप्ति प्रक्रिया के साथ एकीकृत करें ताकि खिलाड़ियों को गैर-भुगतान किए गए जुर्माने का भुगतान करना पड़े इससे पहले कि वे गैराज से वाहन निकालें। यह एक प्राकृतिक प्रवर्तन लूप बनाता है जहां पार्किंग नियमों की अनदेखी करने के वास्तविक इन-गेम परिणाम होते हैं। मीटर समाप्ति के बाद जुर्माना जारी करने से पहले पांच से दस मिनट की ग्रेस अवधि जोड़ने पर विचार करें, क्योंकि यह वास्तविक दुनिया के पार्किंग प्रवर्तन को दर्शाता है और पूरी तरह से समयबद्ध जुर्मानों से खिलाड़ी की निराशा को कम करता है।
NUI मीटर डिस्प्ले और पेमेंट इंटरफेस
पार्किंग मीटर NUI साफ और सूचनात्मक होना चाहिए, जो वर्तमान ज़ोन का नाम, प्रति घंटे दर, यदि पहले से भुगतान किया गया हो तो शेष समय, और अवधि चयन और भुगतान करने के लिए बटन दिखाए। एक काउंटडाउन टाइमर दिखाएं जो हर सेकंड अपडेट होता है जब मीटर सक्रिय हो ताकि खिलाड़ी को पता चले कि उनके पास कितना समय बचा है। एक कॉम्पैक्ट डिज़ाइन का उपयोग करें जो गेम दृश्य को अवरुद्ध न करे, जैसे कि वास्तविक दुनिया के पार्किंग मीटर स्क्रीन। टाइमर डिस्प्ले को हरे से पीले और फिर लाल रंग में रंग संक्रमण के साथ एनिमेट करें जब समय समाप्त हो रहा हो, जो एक सहज दृश्य संकेत प्रदान करता है बिना खिलाड़ी को सटीक मिनट पढ़ने की आवश्यकता के। NUI को हल्का रखें, वैनिला जावास्क्रिप्ट और न्यूनतम CSS का उपयोग करें, भारी फ्रेमवर्क से बचें जो सरल इंटरफ़ेस के लिए लोडिंग समय बढ़ाते हैं।
टोइंग इंटीग्रेशन और परित्यक्त वाहन
अपने पार्किंग सिस्टम को एक टोइंग मैकेनिक से कनेक्ट करें ताकि एक्सपायर्ड या अवैध रूप से पार्क किए गए वाहन इम्पाउंड लॉट में टो किए जा सकें। जब कोई वाहन निर्धारित सीमा से अधिक समय तक उल्लंघन में हो, तो इसे सर्वर स्टेट में टो करने योग्य के रूप में चिह्नित करें। टो ट्रक जॉब खिलाड़ी तब अपने नक्शे पर इन वाहनों को हाइलाइटेड देख सकते हैं और उन्हें टो करने के लिए भुगतान कमा सकते हैं। टोइंग प्रक्रिया वाहन की स्थिति को डेटाबेस में "out" से "impounded" में अपडेट करनी चाहिए और इम्पाउंड कारण को पार्किंग उल्लंघन के रूप में रिकॉर्ड करना चाहिए। जो वाहन लंबे समय तक बिना किसी खिलाड़ी की इंटरैक्शन के जगहों पर पड़े रहते हैं, उनके लिए एक स्वचालित क्लीनअप रूटीन लागू करें जो एक कॉन्फ़िगर करने योग्य टाइमआउट के बाद उन्हें इम्पाउंड में स्थानांतरित कर देता है, जिससे सक्रिय खिलाड़ियों के लिए जगह खाली हो जाती है। इससे उन खिलाड़ियों के वाहनों से पार्किंग स्थल भरने से रोका जाता है जो कई दिनों या हफ्तों से लॉगिन नहीं हुए हैं।
प्रदर्शन और स्केलेबिलिटी विचार
पार्किंग सिस्टम लगातार डिटेक्शन लूप चलाते हैं जो प्रदर्शन को प्रभावित कर सकते हैं यदि सावधानी से अनुकूलित न किया जाए। क्लाइंट-साइड वाहन डिटेक्शन केवल उन ज़ोन के लिए सक्रिय होना चाहिए जो रेंडर दूरी के भीतर हों, और सर्वर-साइड मीटर चेक थ्रेड को प्रत्येक वाहन के लिए व्यक्तिगत टाइमर बनाने के बजाय सभी सक्रिय सत्रों को बैच-प्रोसेस करना चाहिए। जब खिलाड़ी वाहन प्राप्त करते हैं या एडमिन जुर्माना इतिहास पूछताछ करते हैं, तो तेज़ लुकअप सुनिश्चित करने के लिए प्लेट और सिटिजनआईडी कॉलम दोनों पर पार्किंग जुर्माना डेटाबेस टेबल का इंडेक्स करें। दर्जनों पार्किंग ज़ोन और सैकड़ों एक साथ वाहन वाले सर्वरों के लिए, हर जांच पर कॉन्फ़िग से पढ़ने के बजाय ज़ोन डेटा को Lua टेबल में कैश करने पर विचार करें, और नेटिव फ़ंक्शन का उपयोग करें। GetClosestVehicle संभलकर क्योंकि यह सीमा में सभी वाहनों को स्कैन करता है। पीक लोड के तहत FiveM बिल्ट-इन प्रोफाइलर के साथ अपने पार्किंग रिसोर्स का प्रोफाइल करें ताकि किसी भी हॉटस्पॉट की पहचान हो सके, और याद रखें कि एक पार्किंग सिस्टम को सर्वर टिक समय का 0.1ms से कम उपयोग करना चाहिए ताकि समग्र सर्वर प्रदर्शन प्रभावित न हो।