บัญชีผู้เล่น
มอบบัญชีให้ผู้เล่นเกมของคุณที่ใช้ได้ในทุกเกมของ Aukimi พร้อมเซฟที่ตามผู้เล่นไปได้ทุกเครื่อง ไม่ว่าจะบนบริการของ Aukimi หรือเซิร์ฟเวอร์ของคุณเอง
สรุปในประโยคเดียว#
ผู้เล่นเข้าสู่ระบบครั้งเดียวที่ play.aukimi.com แล้วพบบัญชีนั้นในทุกเกมที่สร้างด้วย Aukimi รวมถึงเซฟด้วย เกมของคุณขอใช้บัญชีเท่านั้น มันไม่เคยจับต้องรหัสผ่านเลย
ทำไมเกมของคุณไม่มีวันเห็นรหัสผ่าน#
ใครก็ตามสามารถเผยแพร่เกมได้ เกมที่ขอรหัสผ่านของ Aukimi จะเป็นหน้าฟิชชิ่งที่ น่าเชื่อถือมาก และไม่ว่าคุณจะมีเจตนาดีแค่ไหน สิ่งนั้นก็ไม่เปลี่ยนสิ่งที่นักพัฒนา คนอื่น สามารถส่งออกไปได้
ดังนั้นรหัสผ่านจะถูกพิมพ์บน play.aukimi.com เท่านั้น ไม่มีที่อื่นอีก เกมของคุณเรียก
PlayerLoginAsync() หน้าต่างเบราว์เซอร์จะเปิดขึ้นด้วยสีสันของ Aukimi เอง ผู้เล่นกด
ยืนยัน และหน้าต่างนั้นจะส่งโทเคนกลับมาให้เกมของคุณ
โทเคนนั้นออกให้สำหรับ เกมของคุณเท่านั้น โทเคนของเกม A ที่นำไปใช้กับเกม B จะถูก ปฏิเสธ ไม่ใช่แค่เพิกเฉย แต่ปฏิเสธ นั่นคือประเด็นสำคัญ: บัญชี ถูกแชร์ระหว่างเกม แต่ สิทธิ์เข้าถึง ไม่ได้ถูกแชร์ หากไม่มีสิ่งนี้ เกมประสงค์ร้ายเกมเดียวจะอ่านเซฟของ ผู้เล่นในเกมอื่นทั้งหมดได้
สิ่งที่คุณได้รับเกี่ยวกับผู้เล่น#
สองอย่าง ไม่มากไปกว่านั้น:
| คุณได้รับ | คุณไม่มีวันได้รับ |
|---|---|
ชื่อที่แสดง (PlayerName()) | ที่อยู่อีเมล |
id ที่ไม่มีความหมาย ต่างกันในทุกเกม (PlayerID()) | สิ่งใดก็ตามที่ระบุตัวตนพวกเขาในที่อื่น |
id เปลี่ยนไปในแต่ละเกมโดยตั้งใจ นักพัฒนาสองคนที่เทียบรายชื่อผู้เล่นของตนไม่สามารถ บอกได้ว่ากำลังดูคนเดียวกันอยู่ มันยังทำให้คุณเป็นเพียงผู้ประมวลผล ไม่ใช่ผู้ควบคุมข้อมูล นั้น ซึ่งเป็นข้อแตกต่างทางกฎหมาย ไม่ใช่แค่เรื่องตกแต่ง
ไม่มีอะไรบล็อกลูปของเกม#
ทุกคำสั่งที่คุยกับเครือข่ายจะคืนค่าเป็น หมายเลขงาน (job number) ไม่ใช่ผลลัพธ์ ลูปของคุณยังคงทำงานต่อที่หกสิบเฟรมต่อวินาทีในขณะที่คำขอกำลังเดินทาง ซึ่งเป็นเหตุผล ทั้งหมดที่เกมไม่สามารถแค่ "รอเซิร์ฟเวอร์" ได้
job = PlayerLoginAsync()
จากนั้นทุกเฟรม:
etat$ = PlatformJobState(job)
if etat$ = "done"
resultat$ = PlatformJobResult(job)
PlatformJobRelease(job)
endif
if etat$ = "error"
Print(PlatformJobError(job))
PlatformJobRelease(job)
endif
ปล่อยงาน (release) ทันทีที่คุณอ่านมันแล้ว งานที่ไม่เคยถูกปล่อยจะเก็บผลลัพธ์ของ มันไว้ในหน่วยความจำตลอดที่เหลือของเซสชัน ไม่มีอะไรพัง ไม่มีอะไรเตือนคุณ และการรั่วไหล นี้จะปรากฏให้เห็นก็ต่อเมื่อเล่นเซสชันยาว ๆ เท่านั้น
เล่นโดยไม่มีบัญชี#
ไม่ใช่ทุกคนที่อยากสมัครสมาชิกก่อนลองเล่นเกม PlayerGuestAsync(name$) สร้างบัญชี
ที่ไม่มีอีเมล เก็บไว้ในเบราว์เซอร์นี้
มันเป็นบัญชีจริง: มันเซฟได้ โหลดได้ และสามารถ claim ได้ในภายหลัง โดยผู้เล่น เพิ่มอีเมลและรหัสผ่าน แล้วเซฟที่มีอยู่จะติดตามไปโดยไม่ต้องย้ายข้อมูล
ข้อเสียตรงไปตรงมา: การล้างข้อมูลเว็บไซต์ในเบราว์เซอร์จะทำให้เสียบัญชีนั้นไป และไม่มี
ทางกู้คืนได้ นั่นคือราคาของ "ไม่ต้องสมัครสมาชิก" และเกมของคุณควรบอกเรื่องนี้ แทนที่
จะปล่อยให้ผู้เล่นค้นพบเอง PlayerIsGuest() มีไว้เพื่อประโยคนั้นโดยเฉพาะ
การเซฟ#
job = PlayerSaveAsync(donnees$)
job = PlayerLoadAsync()
เซฟคือ JSON ในรูปแบบของคุณเอง เก็บไว้ตามคู่ (ผู้เล่นนี้, เกมนี้) มันตามผู้เล่นไปยัง เบราว์เซอร์อื่น เครื่องอื่น แพลตฟอร์มอื่นได้
สำหรับค่าไม่กี่ค่า SetCloudDataVariable() และ CloudDataVariable() ใช้งานง่ายกว่า
ไม่ต้องมีงาน ไม่ต้องมี JSON ตรวจสอบ CloudDataAllowed() ก่อนเสมอ: มันจะคืนค่า 0
เมื่อไม่มีผู้เล่นล็อกอินอยู่ และการเขียนต่อไปเงียบ ๆ จะไม่ไปไหนเลย
การวาดหน้าจอ#
Aukimi ไม่ วาดฟอร์มล็อกอินให้ ฟอร์มที่เอนจินสร้างขึ้นจะดูเหมือนหน้าเว็บที่ถูก วางทับลงบนเกมพิกเซลอาร์ตเสมอ และมันจะเป็นส่วนเดียวในเกมของคุณที่คุณปรับสไตล์เองไม่ได้
คุณวาดมันเอง ส่วนเดียวที่ต้องมาจากเบราว์เซอร์คือการรับข้อความ ดังนั้น
CreateEditBox() จะให้ช่องอินพุตจริงที่คุณจัดตำแหน่งเอง:
CreateEditBox(1)
EditBoxPosition(1, 20, 42)
EditBoxSize(1, 60, 8)
nom$ = EditBoxText(1)
ตัวอย่าง Player Account ในรายการตัวอย่างของ Engine เป็นหน้าจอที่ทำงานได้ครบ
สมบูรณ์ในโค้ดประมาณร้อยบรรทัด เปิดมันขึ้นมา อ่านมัน แล้วแทนที่ Print() ทุกตัว
ด้วยงานศิลป์ของคุณเอง
ก่อนที่สิ่งนี้ทั้งหมดจะทำงานได้#
เกมต้องถูกประกาศไว้จากบัญชี Aukimi ของคุณ ภายใต้ My games
(aukimi.com/app/games): ชื่อเรื่อง ที่อยู่ที่จะเล่นเกมได้ และที่อยู่ที่เกมของคุณได้รับ
อนุญาตให้กลับไปหา จนกว่าจะทำสิ่งนี้ PlayerAvailable() จะคืนค่า 0 และเกมที่ดีควร
บอกว่า "บัญชีไม่พร้อมใช้งาน" แทนที่จะดูเหมือนค้าง
หน้าจอเดียวกันนั้นคือที่ที่คุณเห็นว่าใครกำลังเล่นอยู่ อ่านตัวเลขตามความหมายจริงของ มัน: มันนับ ผู้เล่นที่ล็อกอินแล้ว และ เซสชันที่เริ่มต้น ไม่เคยนับจำนวนครั้งที่ เกมถูกเล่น เกมที่ไม่เคยขอให้ใครล็อกอินเลยจะไม่แสดงอะไรตรงนั้น และหน้าจอก็บอกเช่นนั้น แทนที่จะแสดงเลขศูนย์แบบเงียบ ๆ
การใช้เซิร์ฟเวอร์บัญชีของคุณเอง#
ทุกอย่างข้างต้นคุยกับบริการบัญชีของ Aukimi หากคุณโฮสต์เกมของคุณเองบนเซิร์ฟเวอร์ ของคุณ คำสั่งสิบสองคำสั่งเดียวกันนี้สามารถคุยกับบริการ ของคุณ แทนได้ และสคริปต์ ของคุณไม่ต้องเปลี่ยนแม้แต่บรรทัดเดียว
ใน Engine: พาเนล Multiplayer → ส่วน Player accounts → เลือก My own server → กรอกช่องเดียว คือที่อยู่ของเซิร์ฟเวอร์คุณ ที่อยู่นั้นเป็นการตั้งค่าของฉาก ดังนั้นเกมสองเกมสามารถใช้บริการที่ต่างกันสองบริการได้
สองวิธีในการล็อกอินผู้เล่น#
ทางเลือกนี้ทำ ในสคริปต์ของคุณ ไม่ใช่ในการตั้งค่า ทั้งสองรูปแบบมีอยู่ไม่ว่าคุณจะ ชี้ไปที่เซิร์ฟเวอร์ใด
หน้าต่าง (สิ่งที่คุณรู้จักอยู่แล้ว)#
job = PlayerLoginAsync()
หน้าต่างจะเปิดขึ้น ผู้เล่นล็อกอินที่นั่น แล้วมันมอบสิทธิ์ให้เกมของคุณกระทำการแทนพวกเขา
กับบริการของ Aukimi หน้าต่างนั้นคือ play.aukimi.com ส่วนกับเซิร์ฟเวอร์ของคุณเอง
หน้านั้นเป็นของคุณที่ต้องสร้างเอง
โดยตรง ด้วยชื่อผู้ใช้และรหัสผ่าน#
job = PlayerLoginAsync(username$, password$)
ไม่มีหน้าต่าง เกมของคุณอ่านสิ่งที่ผู้เล่นพิมพ์บนหน้าจอของคุณเองแล้วส่งไปยังเซิร์ฟเวอร์ ของคุณ เขียนง่ายกว่า และช่วยให้คุณคงรูปลักษณ์ของเกมไว้ได้ตลอดทาง
คำเตือน: ในรูปแบบนี้ รหัสผ่านเดินทางจากเกมของคุณไปยังเซิร์ฟเวอร์ของคุณ ตามที่พิมพ์ สองผลที่ตามมา ทั้งสองข้อเด็ดขาด: ที่อยู่ของเซิร์ฟเวอร์คุณต้องขึ้นต้นด้วย
https://(ยกเว้นการทดสอบบนเครื่องของคุณเองเท่านั้น) และรูปแบบนี้มีไว้สำหรับ เซิร์ฟเวอร์ ที่คุณเป็นเจ้าของ เท่านั้น
play.aukimi.comปฏิเสธรูปแบบนี้โดยตั้งใจ Aukimi ไม่ต้องการอยู่ในตำแหน่งที่เห็น รหัสผ่านของผู้เล่นเลย และเกมที่คุณไม่ได้เขียนเองก็ไม่ควรเห็นเช่นกัน
สองทางเลือกนี้เป็นอิสระจากการตั้งค่า: เซิร์ฟเวอร์ที่สร้างเองอาจเสนอแค่หน้าต่างอย่างเดียว และไม่เคยรับรหัสผ่านโดยตรงเลยก็ได้
ตัวอย่างที่เป็นรูปธรรม#
เกมที่มีหน้าจอ "Sign in" ของตัวเอง: ช่องข้อความสองช่องที่เกมวาดเอง ปุ่มหนึ่งปุ่ม และสิ่งนี้อยู่หลังปุ่มนั้น
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 และคำสั่งอื่น ๆ ไม่รู้และไม่สนใจ
ว่าเซิร์ฟเวอร์ไหนเป็นผู้ตอบ
สิ่งที่เซิร์ฟเวอร์ของคุณต้องตอบให้ได้#
จำเป็นต้องมีสี่ที่อยู่ ไม่ว่าคุณจะเสนอการล็อกอินแบบไหน:
| มีไว้เพื่ออะไร | เกมคาดหวังอะไร |
|---|---|
| เล่นในฐานะแขก | ส่งบัญชีที่ไม่มีอีเมลกลับมา |
| ผู้เล่นคนนี้คือใคร | ชื่อที่แสดง, id, และว่าเป็นแขกหรือไม่ |
| อ่านเซฟ | ข้อมูลที่บันทึกไว้ |
| เขียนเซฟ | เก็บสิ่งที่เกมส่งมา |
จากนั้น ขึ้นอยู่กับสิ่งที่คุณเลือกจะเสนอ:
- รูปแบบหน้าต่าง ต้องการหน้าล็อกอินบนเซิร์ฟเวอร์ของคุณ ซึ่งจะบอกเกมว่าใครล็อกอิน เข้ามาเมื่อเสร็จสิ้น
- รูปแบบโดยตรง ต้องการอีกหนึ่งที่อยู่ ที่รับชื่อผู้ใช้และรหัสผ่านแล้วตอบว่าใช่หรือไม่
ที่อยู่ที่แน่นอน รูปแบบของแต่ละคำตอบ และรหัสข้อผิดพลาด อยู่ในรีโพซิทอรี ที่
docs/engine-player-accounts.md ไฟล์นั้นคือสัญญา ส่วนหน้านี้คือแผนที่
หมายเหตุ: ไม่มีสิ่งใดในนี้ทำงานในการส่งออกแบบเนทีฟ คำสั่ง
Player*ต้องการ เซิร์ฟเวอร์ให้คุยด้วยและเบราว์เซอร์ให้คุยผ่าน และการบิลด์แบบเนทีฟไม่มีทั้งสองอย่าง
คำสั่งทั้งหมด#
| คำสั่ง | ทำอะไร |
|---|---|
PlayerAvailable() | บริการบัญชีถูกตั้งค่าไว้สำหรับเกมนี้หรือไม่ |
PlayerLoginAsync() | เปิดหน้าต่างล็อกอิน คืนค่าเป็นงาน |
PlayerLoginAsync(user, pass) | ล็อกอินโดยตรง บนเซิร์ฟเวอร์ของคุณเองเท่านั้น คืนค่าเป็นงาน |
PlayerGuestAsync() | สร้างบัญชีที่ไม่มีอีเมล คืนค่าเป็นงาน |
PlayerLoggedIn() | มีใครล็อกอินอยู่ตอนนี้หรือไม่ |
PlayerName() | ชื่อที่แสดงของพวกเขา |
PlayerID() | id ที่ไม่มีความหมายของพวกเขา เฉพาะเกมนี้ |
PlayerIsGuest() | นี่คือบัญชีที่ไม่มีอีเมลหรือไม่ |
PlayerSaveAsync() | เขียนเซฟ คืนค่าเป็นงาน |
PlayerLoadAsync() | อ่านเซฟกลับมา |
PlayerRefreshAsync() | ต่ออายุโทเคนก่อนมันจะหมดอายุ |
PlayerLogout() | ล็อกเอาต์บนอุปกรณ์นี้ |
PlayerLastError() | เหตุผลที่การเรียกครั้งล่าสุดล้มเหลว |