最近我最喜歡的遊戲之一《Timberborn》發行了 1.0 版本,終於結束了搶先體驗階段。
對於不了解的人來說,《Timberborn》是一款城市建造策略遊戲。在遊戲中,玩家扮演一隻海狸的統治者——在人類(或遊戲中稱作「人族」)從地球上消失後,海狸接管了地球。遊戲內容包括資源收集、滿足海狸的各種需求、建造複雜的水力發電網路、工廠、交通運輸等等。
或者,就我而言,是一個資料庫。
遊戲中包含 3D 水體物理效果、不同的季節(例如乾旱,需要蓄水)以及惡劣的潮汐(新進入地圖的水受到污染,對海狸有害)。
自 2021 年首次發布以來,已經加入了許多功能。
最新更新讓我的遊戲體驗有點問題,因為他們加入了自動化功能。這些自動化功能包括各種感測器,用於檢測惡劣潮汐、水流等等。他們甚至還加入了邏輯閘和HTTP控制桿。
哦,不。我得好好研究一下這些。這是它們在遊戲中的樣子:

如您所見,它們有一個名稱(在本例中為「HTTP Lever 1」)、一個「開啟 URL」和一個「關閉 URL」。
這些功能的概念是讓主播可以將它們與其他服務連接起來,例如 Twitch Webhook。如果有人按讚,就可以播放煙火之類的效果。
但是:誰說你只能使用其中一個呢?

你明白我的意思嗎?
是的。遊戲可以同時執行大約 1000 個這樣的設備一段時間。我在測試的時候,Windows 兩次提示“系統出現問題”,所以從一開始,這都不太實用。不過,也並非一定要如此。
每個控制桿都有一個開啟端和一個關閉端。可惜不支援批量處理,但或許有相關的mod可以實現。另一個端點傳回目前地圖上每個控制桿的狀態。資料大致如下:
[
{
"name": "HTTP Lever 829",
"state": false,
"springReturn": false
},
{
"name": "HTTP Lever 154",
"state": true,
"springReturn": false
},
{
"name": "HTTP Lever 839",
"state": false,
"springReturn": false
},
{
"name": "HTTP Lever 164",
"state": true,
"springReturn": false
}
]
具有兩個狀態的 HTTP 槓桿可以被視為一個位元。
我們只需要一種方法來讀寫它們。
Timberborn 網頁介面:工作原理
我們的想法是,將使用者輸入轉換為 JSON 格式,然後使用 ASCII 編碼將其轉換為二進位格式,並逐位翻轉。讀取時,我們一次讀取所有控制桿狀態,將它們重新排列成比特序列,將其分割成 8 位元資料塊,解碼回字符,並解析生成的 JSON 資料。瞧!一個可讀寫的資料儲存就完成了。
我們先來學一點HTML:
<form method="POST" id="form">
<div>
<input type="text" id="title">
</div>
<div>
<textarea id="text"></textarea>
</div>
<button type="submit">Store in Timberborn</button>
</form>
<button type="button" id="load">
Load data from Timberborn
</button>
現在到了有趣的部分。我們先從一些 JavaScript 框架開始:
const title = document.querySelector('#title')
const text = document.querySelector('#text')
const form = document.querySelector('#form')
const load = document.querySelector('#load')
const chunkSize = 8 // We need this to later split the bits
const numberOfLevers = 1000 // This needs to be the exact number of levers in-game, otherwise it won't work reliably.
接下來,我們監聽表單提交事件,並根據這兩個欄位建立一個 JSON 字串:
form.addEventListener('submit', async (event) => {
event.preventDefault();
const data = {
title: title.value,
text: text.value,
}
const json = JSON.stringify(data)
// ...
})
有了這個之後,我們就可以把它轉換成一系列二進位字串:
form.addEventListener('submit', async (event) => {
// ...
const json = JSON.stringify(data)
const asciiEncoded = json.split('')
.map(c => c.charCodeAt(0))
const binary = asciiEncoded.map(
num => num.toString(2).padStart(chunkSize, '0')
)
// ...
})
這樣我們就得到了一個由 0 和 1 組成的 8 位元長字串陣列:

接下來,我們需要將這些位元連接起來,建立最終的大型位元串。我們將這些位元轉換為布林值,然後轉換為 API URL,之後我們可以使用fetch呼叫這些 URL:
form.addEventListener('submit', async (event) => {
// ...
const bits = binary.join('')
// So there's no leftover data in the registry
// at the end of the current data
.padEnd(numberOfLevers, '0')
.split('')
.map(b => b === '1')
const allUrls = bits.map((bit, key) =>
`http://localhost:8080/api/switch-${bit ? 'on' : 'off'}/HTTP Lever ${key + 1}`
)
await Promise.all(allUrls.map(url => fetch(url)))
console.log('done!')
})
儲存時,這將向遊戲伺服器端發出總共 1000 個 HTTP 請求。難怪遊戲不喜歡這樣。
但是:它真的有效!

(這裡有個GIF動圖,可能要幾秒鐘才能載入…)
接下來,我們需要讀取資料。正如我們在範例中看到的,控制桿狀態可以一次全部獲取,但它們的順序完全打亂了。我們可以透過先載入所有資料,然後再進行排序來解決這個問題。之後,我們將所有資料轉換回位元串,將其分段,並再次解碼為 ASCII 碼:
load.addEventListener('click', async () => {
const response = await fetch('http://localhost:8080/api/levers')
const json = await response.json()
const sorted = json.sort((a, b) => {
const aNumber = Number(a.name.replace('HTTP Lever ', ''))
const bNumber = Number(b.name.replace('HTTP Lever ', ''))
return aNumber - bNumber
})
const bitString = sorted.map(l => l.state ? '1' : '0')
const chunks = []
for (let i = 0; i < bitString.length; i += chunkSize) {
chunks.push(bitString.slice(i, i + chunkSize).join(''))
}
const numbers = chunks.map(c => Number.parseInt(c, 2))
// We filter out everything that's only 0s, because that's likely garbage-data
.filter(n => n > 0)
const letters = numbers.map(n => String.fromCharCode(n))
const data = JSON.parse(letters.join(''))
title.value = data.title
text.value = data.text
})
就這樣!
從技術上講,這現在可以被視為一種雲端儲存。由於 Steam 會將遊戲存檔上傳到雲端,而 Timberborn 將 HTTP 請求視為有狀態的(即在保存遊戲時保存其狀態),因此所有資料都是持久化的。
如果有人能成功地將超過 1 千比特的資料導入 Timberborn,請聯絡我,我非常肯定我們可以想辦法為此建立一個 Drupal 資料庫適配器。
(附註:抱歉,但我並不後悔使用了AI生成的圖像。我最終還是得嘗試一下!)
(附註:本文並非廣告。不過,Timberborn 的開發者們,如果你們看到了這條訊息,我非常期待你們使用自動化功能進行更多有趣的嘗試 :D)
希望您喜歡這篇文章,就像我喜歡寫這篇文章一樣!如果喜歡,請按讚❤️ !我會在空閒時間寫一些科技文章,偶爾也喜歡喝杯咖啡。
如果你想支持我的創作,可以請我喝杯咖啡☕ !你也可以直接透過PayPal支持我!或在Bluesky上關注我🦋 !
原文出處:https://dev.to/thormeier/how-to-use-timberborn-yes-the-beaver-city-building-game-as-a-database-489c