← กรณีการใช้งาน

โรงประมูลและตลาดผู้เล่นในเกม

รายการ การประมูล และเวลานับถอยหลังแบบสดในทุกไคลเอนต์ ขยายเวลาอัตโนมัติเมื่อประมูลในวินาทีสุดท้ายเพื่อกันการตัดหน้า มีซื้อทันทีและราคาขาย โดยเซิร์ฟเวอร์ของคุณตัดสินทุกการประมูล และเกมของคุณเก็บเหรียญกับไอเท็มไว้เอง

โรงประมูล ตลาดซื้อขาย หรือตลาดของผู้เล่นช่วยให้เศรษฐกิจในเกมหมุนไปได้ แต่จะรู้สึกยุติธรรมก็ต่อเมื่อทุกคนเห็นสิ่งเดียวกันในเวลาเดียวกัน คือเห็นราคาใหม่ทันทีที่มีคนประมูล เห็นเวลานับถอยหลังเท่ากันทุกหน้าจอ และไม่มีใครแย่งไปได้ในวินาทีสุดท้าย แพ็กเกจโอเพนซอร์ส @hibira-io/auction ให้สิ่งนี้บน Hibira โดยเซิร์ฟเวอร์ของคุณเองเป็นผู้ตัดสินทุกการประมูล

สิ่งที่ผู้เล่นได้รับ

  • รายการที่ลงขาย เปลี่ยนราคา และปิดลง จะแสดงในทุกไคลเอนต์ที่เปิดอยู่โดยไม่ต้องรีเฟรช
  • เวลานับถอยหลังตรงกับนาฬิกาของเซิร์ฟเวอร์ และการประมูลในวินาทีสุดท้ายจะเพิ่มเวลาแทนที่จะถูกตัดหน้า
  • แจ้งทันทีเมื่อมีคนประมูลสูงกว่า ซื้อทันทีได้ และดูราคาขายล่าสุดของแต่ละไอเท็มได้
ตัวอย่างโรงประมูล: ผู้เล่นประมูลธนูนักล่า อีกหน้าต่างประมูลสูงกว่าในไม่กี่วินาที และผู้เล่นคนแรกเห็นราคาใหม่พร้อมการแจ้งเตือน
ตัวอย่างโรงประมูล: ผู้เล่นประมูลธนูนักล่า อีกหน้าต่างประมูลสูงกว่าในไม่กี่วินาที และผู้เล่นคนแรกเห็นราคาใหม่พร้อมการแจ้งเตือน

สร้างด้วย

  • หนึ่งแชนแนลสาธารณะหรือส่วนตัวต่อหนึ่งโรงประมูล (auction-main) มีอีเวนต์เดียวคือ auction-update ที่ส่งข้อมูลรายการทั้งหมดพร้อมหมายเลขเวอร์ชัน
  • HTTP API (trigger) จากเซิร์ฟเวอร์ของคุณ แต่ละการเปลี่ยนแปลงถูกส่งครั้งเดียว ไม่ว่าจะมีผู้เล่นดูอยู่กี่คน
  • @hibira-io/auction: ฝั่งเซิร์ฟเวอร์ตรวจการประมูล ขยายเวลาการประมูลที่ใกล้ปิด และปิดการขาย ฝั่งไคลเอนต์เก็บเวอร์ชันล่าสุดของแต่ละรายการและตามทันหลังเชื่อมต่อใหม่
ผู้เล่น Aเซิร์ฟเวอร์ของคุณHibiraผู้เล่น BPOST /auction/:id/bid120 ทองhouse.bid() ตรวจการประมูลและกันทองไว้auction-updateราคา 120, A นำauction-updateauction-update"ประมูล 126"
การประมูลไปที่เซิร์ฟเวอร์ของคุณ แล้ว Hibira แจ้งผู้เล่นทุกคน

ขั้นที่ 1: สร้างโรงประมูลบนเซิร์ฟเวอร์

ไอเท็มและเหรียญยังอยู่ในระบบของเกมคุณ โรงประมูลจะขอให้คุณกันเหรียญของผู้ประมูลไว้ คืนให้เมื่อมีคนประมูลสูงกว่า และโอนไอเท็มกับเหรียญเมื่อการประมูลปิด

import Pusher from 'pusher';
import { createAuctionHouse } from '@hibira-io/auction/server';

const hibira = new Pusher({ appId, key, secret, host: 'ws.hibira.io', useTLS: true });

const house = createAuctionHouse({
  pusher: hibira,
  name: 'main',
  extendWithin: 30000, // a bid in the last 30 s adds time
  reserve: async ({ userId, amount }) => {
    if (!(await wallet.hold(userId, amount))) throw new Error('not enough gold');
  },
  release: async ({ userId, amount }) => wallet.unhold(userId, amount),
  settle: async ({ listing }) => game.deliver(listing), // idempotent by listing.id
});
house.start(); // closes and settles ended auctions

ขั้นที่ 2: เอนด์พอยต์สี่ตัว

ดึงผู้เล่นจากเซสชันของคุณเองเสมอ อย่าอ่านจากเนื้อหาคำขอ

app.get('/auction', async (req, res) => res.json(await house.snapshot()));

app.post('/auction/:id/bid', requireLogin, async (req, res) => {
  try {
    res.json(await house.bid({ listingId: req.params.id, bidderId: req.user.id, bidder: { name: req.user.name }, amount: req.body.amount }));
  } catch (err) {
    res.status(err.status ?? 500).json({ error: err.code });
  }
});
// The same for house.buyout() and house.list()

ขั้นที่ 3: แสดงโรงประมูลในเกม

import { AuctionHouse } from '@hibira-io/auction';

const house = AuctionHouse.open(pusher, 'main', {
  load: () => fetch('/auction').then((r) => r.json()),
});

house.on('change', ({ listings }) => render(listings));
setInterval(() => listings.forEach((l) => showTimeLeft(l, house.timeLeft(l))), 250);

bidButton.onclick = () => fetch(`/auction/${l.id}/bid`, { method: 'POST', body: JSON.stringify({ amount: l.minBid }) });

house.prices(type) คืนราคาขายล่าสุดของไอเท็มแต่ละประเภทสำหรับกราฟราคา หลังเชื่อมต่อใหม่ โรงประมูลจะโหลดสแนปช็อตอีกครั้ง จึงไม่พลาดอะไร

ลองใช้

ตัวอย่างโรงประมูล เป็นตลาดในเกมที่สมบูรณ์ด้วย Next.js มีพ่อค้า NPC กระเป๋า ซื้อทันที การแจ้งเตือนเมื่อถูกประมูลสูงกว่า และราคาขาย รองรับเจ็ดภาษา เปิดสองหน้าต่างแล้วลองประมูลในหน้าต่างหนึ่ง

เคล็ดลับ

  • ทุกการเปลี่ยนแปลงนับเป็นหนึ่งข้อความ ไม่ว่าจะมีผู้เล่นดูกี่คน แบ่งโรงประมูลขนาดใหญ่ตามหมวดหมู่หรือภูมิภาค (name: 'weapons') เพื่อให้แต่ละไคลเอนต์โหลดเฉพาะส่วนที่แสดง
  • ถ้ามีเกมเซิร์ฟเวอร์หลายเครื่อง ให้ส่ง store ที่อยู่บนฐานข้อมูลของคุณ การบันทึกเป็นแบบเปรียบเทียบก่อนเขียน สองเซิร์ฟเวอร์จึงรับการประมูลเดียวกันพร้อมกันไม่ได้
  • มันโอนเหรียญและไอเท็มของเกมคุณเอง ไม่ใช่เงินจริง
  • ไคลเอนต์ Unity, Godot หรือ Pusher SDK ใดก็ได้ สามารถติดตามแชนแนล auction-main เดียวกันและเรียกเอนด์พอยต์เดียวกันได้ สำหรับห้องและการจับคู่ ดูห้องเกมและล็อบบี้แบบผู้เล่นหลายคน