प्लेयर अकाउंट

अपने गेम के players को एक ऐसा account दें जो वे हर Aukimi गेम में साथ रखें, ऐसे saves के साथ जो एक डिवाइस से दूसरी तक उनका पीछा करें, चाहे वह Aukimi की सर्विस पर हो या आपके अपने सर्वर पर।

एक लाइन में#

कोई player एक बार play.aukimi.com पर साइन इन करता है और वही account उसे Aukimi से बने हर गेम में मिल जाता है, saves सहित। आपका गेम account माँगता है; यह कभी password को हैंडल नहीं करता।

आपका गेम कभी password क्यों नहीं देखता#

कोई भी गेम पब्लिश कर सकता है। जो गेम किसी Aukimi password की माँग करे, वह बिल्कुल असली लगने वाला phishing page होगा, और आपकी कितनी भी अच्छी नीयत हो, इससे यह नहीं बदलेगा कि कोई दूसरा डेवलपर क्या शिप कर सकता है।

इसलिए password play.aukimi.com पर टाइप होता है, और कहीं और नहीं। आपका गेम PlayerLoginAsync() बुलाता है, एक ब्राउज़र विंडो Aukimi के अपने रंगों में खुलती है, player मंज़ूरी देता है, और विंडो आपके गेम को एक token सौंप देती है।

वह token सिर्फ़ आपके गेम के लिए जारी होता है। गेम A के लिए बना token अगर गेम B को दिखाया जाए तो वह अस्वीकार किया जाता है, नज़रअंदाज़ नहीं, अस्वीकार। यही पूरी बात है: account गेमों के बीच साझा होता है, access नहीं। इसके बिना, कोई एक बदनीयत गेम बाक़ी सारे गेमों में किसी player के saves पढ़ सकता।

किसी player के बारे में आपको क्या मिलता है#

दो चीज़ें, और बस:

आपको यह मिलता हैयह कभी नहीं मिलता
एक display name (PlayerName())email address
एक opaque id, हर गेम में अलग (PlayerID())कोई भी ऐसी चीज़ जो उन्हें कहीं और पहचान दे

id जान-बूझकर एक गेम से दूसरे में बदल जाती है। अपनी player लिस्ट मिलाने वाले दो डेवलपर यह नहीं बता सकते कि वे एक ही इंसान को देख रहे हैं। यह आपको उस डेटा का processor बनाए रखता है, controller नहीं, और यह एक क़ानूनी फ़र्क़ है, दिखावटी नहीं।

कुछ भी game loop को रोकता नहीं#

नेटवर्क से बात करने वाला हर कमांड एक job number लौटाता है, कभी कोई नतीजा नहीं। जब तक request चल रही होती है, आपका loop साठ फ़्रेम प्रति सेकंड पर चलता रहता है, और यही पूरी वजह है कि कोई गेम बस "सर्वर का इंतज़ार" नहीं कर सकता।

job = PlayerLoginAsync()

फिर, हर फ़्रेम में एक बार:

etat$ = PlatformJobState(job)
if etat$ = "done"
    resultat$ = PlatformJobResult(job)
    PlatformJobRelease(job)
endif
if etat$ = "error"
    Print(PlatformJobError(job))
    PlatformJobRelease(job)
endif

Job को पढ़ने के बाद उसे release कर दें। जो job कभी release नहीं होता वह अपना नतीजा बाक़ी पूरे सेशन के लिए मेमोरी में रखे रहता है। कुछ नहीं टूटता, कोई चेतावनी नहीं मिलती, और यह लीक सिर्फ़ किसी लंबे play सेशन में ही दिखता है।

बिना account के खेलना#

हर कोई किसी गेम को आज़माने से पहले साइन अप नहीं करना चाहता। PlayerGuestAsync(name$) बिना email का एक account बनाता है, जो इसी ब्राउज़र में रहता है।

यह एक असली account है: यह save करता है, load करता है, और बाद में इसे claim किया जा सकता है, player एक email और password जोड़ता है, और मौजूदा saves बिना हिले-डुले साथ चले आते हैं।

ईमानदार अड़चन: ब्राउज़र का site data साफ़ करना उस account को खो देता है, और उसे वापस पाने का कोई तरीक़ा नहीं है। यही "no sign-up" की क़ीमत है, और player को ख़ुद पता चलने देने के बजाय आपके गेम को यह बता देना चाहिए। PlayerIsGuest() ठीक इसी वाक्य के लिए है।

Save करना#

job = PlayerSaveAsync(donnees$)
job = PlayerLoadAsync()

save आपकी अपनी बनावट का JSON है, (यह player, यह गेम) की जोड़ी के मुक़ाबले स्टोर किया गया। यह उनके साथ किसी दूसरे ब्राउज़र, दूसरी मशीन, दूसरे प्लैटफ़ॉर्म तक जाता है।

मुट्ठी भर वैल्यू के लिए, SetCloudDataVariable() और CloudDataVariable() आसान हैं, न कोई job, न कोई JSON। पहले CloudDataAllowed() जाँच लें: जब कोई player साइन इन नहीं है तो यह 0 लौटाता है, और फिर भी लिखने की कोशिश चुपचाप कहीं नहीं पहुँचेगी।

स्क्रीन बनाना#

Aukimi कोई sign-in फ़ॉर्म नहीं बनाता। इंजन का बनाया हुआ कोई फ़ॉर्म हमेशा किसी पिक्सेल-आर्ट गेम पर टपकाए गए किसी वेब पेज जैसा दिखेगा, और यह आपके गेम का वह इकलौता हिस्सा होगा जिसे आप दोबारा स्टाइल नहीं कर सकते।

आप इसे बनाते हैं। सिर्फ़ एक हिस्सा है जो ब्राउज़र से आना ज़रूरी है, वह है text entry, इसलिए CreateEditBox() आपको एक असली input field देता है जिसे आप ख़ुद पोज़िशन करते हैं:

CreateEditBox(1)
EditBoxPosition(1, 20, 42)
EditBoxSize(1, 60, 8)
nom$ = EditBoxText(1)

Engine की sample लिस्ट में Player Account डेमो लगभग सौ लाइनों में एक पूरी तरह काम करने वाली स्क्रीन है। इसे खोलें, पढ़ें, फिर हर Print() को अपनी ख़ुद की आर्टवर्क से बदलें।

इनमें से कुछ भी काम करने से पहले#

गेम को आपके Aukimi account से, My games (aukimi.com/app/games) के तहत डिक्लेयर किया जाना ज़रूरी है: एक title, वह पता जहाँ इसे खेला जा सकता है, और वे पते जहाँ आपके गेम को लौटने की इजाज़त है। तब तक PlayerAvailable() 0 लौटाता है, और कोई अच्छा गेम अटका हुआ दिखने के बजाय "accounts are not available" कहता है।

उसी स्क्रीन पर आप देखते हैं कि कौन खेल रहा है। नंबरों को वैसे ही पढ़ें जैसे वे हैं: यह साइन इन किए गए players और शुरू हुए sessions गिनता है, कभी खेले गए गेम नहीं। जो गेम कभी किसी से साइन इन नहीं करवाता वह वहाँ कुछ नहीं दिखाता, और स्क्रीन चुपचाप शून्य दिखाने के बजाय यह बता देती है।

अपना ख़ुद का account सर्वर इस्तेमाल करना#

ऊपर की हर बात Aukimi की account सर्विस से बात करती है। अगर आप अपना गेम अपने ख़ुद के सर्वर पर होस्ट करते हैं, तो वही बारह कमांड इसकी बजाय आपकी सर्विस से बात कर सकते हैं, और आपकी स्क्रिप्ट की एक भी लाइन नहीं बदलती।

Engine में: पैनल Multiplayer → सेक्शन Player accountsMy own server चुनें → एक फ़ील्ड भरें, आपके सर्वर का पता। वह पता सीन की एक सेटिंग है, इसलिए दो गेम दो अलग-अलग सर्विस इस्तेमाल कर सकते हैं।

किसी player को साइन इन करने के दो तरीक़े#

यह चुनाव आपकी स्क्रिप्ट में होता है, किसी सेटिंग में नहीं। आप चाहे किसी भी सर्वर की तरफ़ इशारा करें, दोनों रूप मौजूद रहते हैं।

विंडो (जो आप पहले से जानते हैं)#

job = PlayerLoginAsync()

एक विंडो खुलती है, player वहीं साइन इन करता है, और यह आपके गेम को उनकी तरफ़ से काम करने का अधिकार वापस सौंप देती है। Aukimi की सर्विस के साथ वह विंडो play.aukimi.com है। अपने ख़ुद के सर्वर के साथ, वह पेज आपको ख़ुद बनाना है।

सीधे, एक username और password के साथ#

job = PlayerLoginAsync(username$, password$)

कोई विंडो नहीं। आपका गेम वह पढ़ता है जो player ने आपकी अपनी स्क्रीन पर टाइप किया, और उसे आपके सर्वर पर भेज देता है। लिखने में आसान, और यह आपको शुरू से आख़िर तक अपने गेम का लुक बनाए रखने देता है।

चेतावनी: इस रूप में, password आपके गेम से आपके सर्वर तक वैसे ही जैसा टाइप किया गया जाता है। दो नतीजे, दोनों पक्के: आपके सर्वर का पता https:// से शुरू होना चाहिए (सिर्फ़ अपनी ख़ुद की मशीन पर किया गया टेस्ट इससे छूट पाता है), और यह रूप सिर्फ़ उसी सर्वर के लिए है जिसके आप मालिक हैं

play.aukimi.com जान-बूझकर इसे अस्वीकार करता है। Aukimi कभी ऐसी स्थिति में नहीं आना चाहता जहाँ वह किसी player का password देख सके, और न ही किसी ऐसे गेम को जो आपने नहीं लिखा।

ये दोनों चुनाव सेटिंग से स्वतंत्र हैं: कोई घर का बनाया सर्वर बिल्कुल सिर्फ़ विंडो दे सकता है, और सीधे कभी कोई password स्वीकार न करे।

एक असली उदाहरण#

एक ऐसा गेम जिसकी अपनी "Sign in" स्क्रीन है: गेम द्वारा बनाए गए दो text field, एक button, और button के पीछे यह।

job = PlayerLoginAsync(typedName$, typedPassword$)
DO
    etat$ = PlatformJobState(job)
    if etat$ = "done"
        PlatformJobRelease(job)
        Print("Welcome " + PlayerName())
    endif
    if etat$ = "error"
        PlatformJobRelease(job)
        Print(PlayerLastError())
    endif
    Sync()
LOOP

साइन-इन के बाद सब कुछ इस पेज के बाक़ी हिस्से जैसा ही है: PlayerSaveAsync, PlayerLoadAsync, PlayerName और बाक़ी को न तो पता होता है, न फ़र्क़ पड़ता है, कि किस सर्वर ने जवाब दिया।

आपके सर्वर को क्या जवाब देना है#

आप कोई भी sign-in दें, चार पते ज़रूरी हैं:

यह किसलिए हैगेम क्या उम्मीद करता है
Guest के तौर पर खेलनाबिना email वाला एक account वापस दें
यह player कौन हैdisplay name, id, क्या यह कोई guest है
Save पढ़नाsaved data
Save लिखनाजो गेम भेजे उसे स्टोर करें

फिर, आप जो देना चुनते हैं उसके हिसाब से:

  • Window form को आपके सर्वर पर एक sign-in पेज चाहिए, जो पूरा होते ही गेम को बताए कि किसने साइन इन किया।
  • Direct form को एक और पता चाहिए, जो एक username और password लेकर हाँ या ना में जवाब दे।

सटीक पते, हर जवाब की बनावट और error कोड रिपॉज़िटरी में हैं, docs/engine-player-accounts.md में। वह फ़ाइल कॉन्ट्रैक्ट है; यह पेज नक़्शा है।

नोट: इनमें से कुछ भी किसी native export में काम नहीं करता। Player* कमांड को बात करने के लिए एक सर्वर और बात करने के ज़रिए एक ब्राउज़र चाहिए, और किसी native build के पास इनमें से कोई नहीं होता।

कमांड#

Commandयह क्या करता है
PlayerAvailable()क्या इस गेम के लिए account सर्विस कॉन्फ़िगर है
PlayerLoginAsync()sign-in विंडो खोलता है। एक job लौटाता है
PlayerLoginAsync(user, pass)सीधे साइन इन करता है, सिर्फ़ आपके अपने सर्वर पर। एक job लौटाता है
PlayerGuestAsync()बिना email का एक account बनाता है। एक job लौटाता है
PlayerLoggedIn()क्या इस वक़्त कोई साइन इन है
PlayerName()उनका display name
PlayerID()उनकी opaque id, इस गेम के लिए ख़ास
PlayerIsGuest()क्या यह बिना email वाला account है
PlayerSaveAsync()save लिखता है। एक job लौटाता है
PlayerLoadAsync()उसे वापस पढ़ता है। एक job लौटाता है
PlayerRefreshAsync()token के एक्सपायर होने से पहले उसे रिन्यू करता है
PlayerLogout()इसी डिवाइस पर साइन आउट करता है
PlayerLastError()आख़िरी कॉल क्यों फेल हुआ