Akka邊學邊寫(4) MiniRPG

2021-09-07 11:56:15 字數 3714 閱讀 2061

前面幾篇文章用akka寫了helloworld和echoserver,為了更進一步學習akka,本文將會實現乙個非常小的rpg遊戲server:minirpg。

由於是迷你rpg,所以邏輯非常easy。server能夠處理四種操作:建立玩家、給玩家加經驗、公升級、查詢玩家資訊。以下是player類的**(getters和setters省略):

public class player 

public void levelup() }}

minirpg底層使用tcp協議,訊息使用json格式。完整的訊息格式例如以下圖所看到的:

前八個位元組能夠覺得是訊息頭。當中前四個位元組是訊息id。後四個位元組是json字串長度。其餘位元組是訊息體,也就是utf8格式編碼的json字串。

minirpg設計了三個介面來表示遊戲訊息,這三個介面都是marker介面。裡面未定義不論什麼方法。例如以下圖所看到的:

minirpg使用gson來編碼和解碼json字串,為了把json解析為對應的訊息物件。須要乙個訊息id和class之間的對映關係。msgregistry類便是要建立起這樣乙個對映關係,以下是它的完整**:

public class msgregistry  private static void register(int msgid, class> msgclass)  public static class> getmsgclass(int msgid)  public static int getmsgid(class> msgclass)  public static int getmsgid(object msg)  } 

minirpgserver的actor系統例如以下圖所看到的:

tcpserver負責監聽tcp連線。連線建立之後。交給codec處理。codec將收到的位元組編碼成訊息物件。然後交給msghandler處理。對於每條請求訊息。msghandler都會產生一條響應訊息。響應訊息被codec編碼之後傳送到client。

以下具體介紹整個actor系統是怎樣實現的。

tcpserver是乙個untypedactor,例項化tcpserver時,我們把msghandler引用傳給它:

public class tcpserver extends untypedactor

}

tcpserver僅僅關心四種訊息。以下是onreceive()方法實現:

@override

public void onreceive(object msg) throws exception else if (msg instanceof bound) else if (msg instanceof commandfailed) else if (msg instanceof connected)

}

integer訊息通知tcpserver繫結到某個port,準備接收client連線。假設收到bound訊息,則port繫結成功。server正常啟動。假設是commandfailed訊息。則server啟動失敗:

private void startserver(int port)
假設是connected訊息。說明有client連線已經建立,tcpserver建立乙個子actor(也就是codec)來處理client連線:

private void registercodec(actorref connection)
msgcodec主要負責訊息的編碼和解碼。為此,msgcodec內部使用了乙個bytestring來快取接收到的位元組:

public class msgcodec extends untypedactor 

}

假設msgcodec收到的是received訊息,說明有資料到達。msgcodec嘗試解碼出乙個訊息物件。假設收到的是gamemessage訊息。msgcodec將其編碼為byte然後傳送給client。

假設收到的是connectionclosed,說明連線已經斷開了:

@override

public void onreceive(object msg) throws exception else if (msg instanceof connectionclosed) else if (msg instanceof gamemessage)

}

每當有資料到達時。decodemsg()方法都會被呼叫。decodemsg()先確定能否夠把訊息頭解碼出來,假設不能,就繼續等待很多其它的位元組到達。

假設訊息頭完整到達,decodemsg()就能夠知道訊息體的長度,然後等到訊息體完整到達。之後依據訊息id和json字串解碼訊息物件。然後通知msghandler:

private void decodemsg() }}

private object decodemsg(int msgid, bytestring jsondata)

訊息的編碼就簡單多了,**例如以下所看到的:

private bytestring encodemsg(object msg)

遊戲邏輯由msghandler來處理。

由於僅僅是個demo,所以msghandler內部使用hashmap來模擬資料庫。以下是msghandler的完整**:

public class msghandler extends untypedactor  else if (msg instanceof addexprequest)  else if (msg instanceof leveluprequest)  else if (msg instanceof getplayerinforequest) 

}private int createplayer(createplayerrequest req)

private int addexptoplayer(addexprequest req)

private int levelupplayer(leveluprequest req)

private playerinfo getplayerinfo(getplayerinforequest req)

}

public static void main(string args)

} 為了測試miniserver。我寫了個簡單的客戶端程式。詳細實現就不在這裡介紹了。

POSA邊讀邊寫 1

拿到這本書,就感覺posa是繼gof之後的又一經典之作。序中介紹,posa拓展了模式的範圍,從原來的設計模式,拓展了新的高層次的體系機構模式,和底層的和程式語言相關的慣用法模式。提出了新的模式分類方法 根據規模 抽象層次 提出了模式系統,來幫助我們利用模式來設計 什麼是模式 模式是乙個描述,它描述了...

邊學邊寫資料結構之線性表

學習的時候能將自己學到的東西寫出來也是一種很好的學習方法,它既能加深學習的效果,又能知道自己對學習內容的了解情況。如果你寫不出來也就說明你對所學的內容並不是完全了解,還有值得重新學習的地方。本人大學只學習過乙個學期的c 語言,其他諸如資料結構與演算法壓根就沒有學過,奈何畢業後從事的是與軟體開發有關的...

Python學習筆記 邊學邊寫第乙個爬蟲

python學習筆記 邊學邊寫第乙個爬蟲 請求網頁 import requests response requests.get print response.text 通過chrome開發者工具找到乙個headers 請求網頁 import requests headers response req...