Lycohinya 是怎麼搭起來的(四):把商團經濟搬出伺服器
商團(薇莉雅)是一套會自己運轉的經濟:生產、消耗、價格、掛單、NPC 商人、倉庫、物流、合約、聲望。這些跟 Minecraft 的世界沒有關係,卻要大量運算,帳也必須對得起來。2.0 我把整套模擬搬到另一台機器上的獨立服務,用 Rust 寫,帶著自己的 MariaDB。
哪些留在遊戲裡
生存伺服器上的商團插件只留跟世界有關的部分:NPC 實體、玩家背包和物品本身、選單、領地,以及透過 Vault 扣錢加錢。價格怎麼算、倉庫剩多少、帳本怎麼記,全部由遠端服務決定。
這樣切,模擬再重也是另一台機器在扛,不會跟世界搶同一台伺服器的資源。
兩邊怎麼溝通
一律由遊戲這邊發起,用 HTTPS。商團插件會定期送心跳、定期去拉通知,玩家操作時再送對應的請求。遠端服務不會反過來呼叫遊戲。
遠端靠心跳判斷遊戲還在不在。一段時間沒收到心跳,它就凍結模擬、拒絕所有請求,等心跳回來再繼續。這樣遊戲伺服器關機或斷線時,商團不會在沒人看著的情況下自己跑下去。
玩家買一筆東西時
sequenceDiagram autonumber actor P as 玩家 participant G as 商團插件(生存伺服器) participant V as Vault 經濟 participant B as 商團運算服務 P->>G: 在倉庫選單按購買 G->>B: 查報價(不改任何東西) G->>P: 顯示確認畫面 P->>G: 確認 Note over G: 先把這筆請求寫進本機日誌 G->>B: 送出交易(附請求編號) Note over B: 先演練一遍再回滾,記下待扣款 G->>V: 扣款,只扣一次 Note over G: 收據寫進本機日誌 G->>B: 交回扣款收據 Note over B: 庫存、帳本、結果一起寫進資料庫 G->>P: 回覆結果、重開選單 G-->>P: 扣款後 Vault 出錯時,改顯示「處理中」 Note over G,B: 不知道扣了沒:不自動重試、不自動退款,等人工對帳
虛線是扣款出錯時才會走的路。
送出去的請求都先寫進生存伺服器本機的日誌,而且每筆都有編號。回應要是在網路上掉了,插件可以拿同一個編號重送,遠端認得這個編號,會直接回之前存好的結果,不會成交兩次。
扣錢只發生在一個地方:商團插件在遊戲裡呼叫 Vault,扣一次。遠端第一次收到交易時只是演練、記下一筆待扣款,等收到扣款收據,才把庫存、帳本和結果一起寫進去。
最麻煩的是 Vault 被呼叫之後出錯,插件不知道錢到底扣了沒。這種情況我選擇停下來:這筆標成「未知」,不自動重試,也不自動退款,玩家看到「處理中」,等人工對帳。對完之前,遠端會擋下後續的寫入。猜錯的代價是多扣或少扣玩家的錢,停一下比較安全。
同一個玩家同時只能有一筆交易在跑,第二筆會直接被擋掉。連線請求也交給背景去跑,排隊滿了就拒絕,不會讓遊戲卡住等網路。
連不上的時候
商團插件連不上遠端時,不會偷偷切回本機的舊邏輯自己算。兩邊同時寫帳本,比暫停一下麻煩得多。所以遠端或它的資料庫出狀況時,商團功能會暫停,但世界的其他部分照常運作。
這就是搬出去的代價:商團綁在一條跨網路的連線上,多養一台機器,也多一個會斷的地方。
什麼時候值得這樣做
只有在那塊邏輯跟世界無關、又重到會影響遊戲時才值得。一般的商店、拍賣場用現成插件就好,沒必要另外開服務。商團是因為要模擬整個市場,帳又必須正確,我才把它搬出去。