锘??xml version="1.0" encoding="utf-8" standalone="yes"?> (Jin Qing's Column, Nov., 2022) A The links are used in If the link is a boundary link, which links to other tile, then it has more fields: Links are not saved to navmesh file. They are created on navmesh loading in The main job of 5 steps to create all links: Off-mesh connection is between 2 points which are inside a tile or between 2 adjacent tiles. For each off-mesh connection, there creates a specific polygon consisting of 2 vertices.
See The destinaton polygon of the off-mesh connection is skipped here. It creates a link from off-mesh connection polygon to the target tile.
For bidirectional connection, it also creates a link from the target polygon to the off-mesh connection polygon. So for each off-mesh connection of this tile, 3 or 4 links are created by baseOffMeshLinks() and connectExtOffMeshLinks(),
one on the source polygon, one on the destination polygon and 1/2 on the off-mesh connection polygon. For each layer other than this layer in this tile: Check 9 neighbor tiles' layers, and create links just like previous step: By now, for every off-mesh connection of all the loaded tiles, 3/4 links are created.dtLink
dtLink
defines a link between 2 polygons.
It is an internal data structure.dtLink
is owned by its source polygon.How link is used
findPath()
, to search
all the neighbor polygons, from the current best polygon.fields of
dtLink
dtLink
has 2 required fields:
How are links created
addTile()
.dtNavMesh::addTile()
add a tile to the navmesh. A tile is a square block of the map.dtNavMesh::addTile()
is to create links inside this tile and between this tile and other tiles.
Actually a block indexed by (x, y) of constant size has many layers for multi-floor map.
A dtMeshTile
is actually a layer with an index of (x, y, layer).1. Connect internal links
connectIntLinks()
iterates all the polygons in the tile and create links for them
by the help of neighbors information of the polygons.2. Base off-mesh connections
baseOffMeshLinks()
bases off-mesh connections to their starting polygons and connect connections inside the tile.DT_POLYTYPE_OFFMESH_CONNECTION
.baseOffMeshLinks()
creates 2 links for each off-mesh connection:
3. Connect external off-mesn links within this tile
connectExtOffMeshLinks()
with the source and target tile be this tile.connectExtOffMeshLinks()
searches off-mesh connections that are from this tile to the target tile
by checking the side direction of the connection.4. Connect with layers in current tile
5. Connect with neighbour tiles
Reference
]]>
(閲戝簡鐨勪笓鏍?2021.7)
How to do multiple actions on Event BeginPlay in UE4 Blueprints?
Sams-Teach-Yourself-Unreal-Engine-4-Game-Development-in-24-Hours says:
```
Q. When I try to add a second event node, BeginPlay, the Editor shows me the first one already
placed in the Event Graph. Why does this happen?
A. Some events, such as Event Tick and the BeginPlay event, can have only one instance per
Blueprint.
```
https://forums.unrealengine.com/t/do-multiple-things-on-event-begin-play/411/10
```
The Sequence node allows for a single execution pulse to trigger a series of events in order. The node may have any number of outputs, all of which get called as soon as the Sequence node receives an input. They will always get called in order, but without any delay. To a typical user, the outputs will likely appear to have been triggered simultaneously.
```
Youtube video: [How to do Multiple Actions on Event Begin Play Unreal Engine 4 Blueprints](https://www.youtube.com/watch?v=nqG-ztbs230)
]]>
鍘熸枃錛歔Ninth generation of video game consoles](https://en.wikipedia.org/wiki/Ninth_generation_of_video_game_consoles)
2020.11錛屽井杞?MS) Xbox Series X/S 鍜?Sony PlayStation 5 (PS5) 鍙戝竷錛屾爣蹇楃潃娓告垙涓繪満榪涘叆絎?浠c?br />
鍜屽墠浠g殑 Xbox One 鍜?PS4 鐩告瘮錛屾柊涓浠d富鏈烘湁鍙鐨勬ц兘鎻愬崌錛屾敮鎸佸疄鏃跺厜綰胯窡韙紝4K鍒嗚鯨鐜囷紝鐩爣甯х巼涓?0銆?br />鍐呴儴閮戒嬌鐢ㄤ簡鍥烘佺‖鐩?SSD)銆備綆閰嶇増娌℃湁鍏夐┍錛屼粎鏀寔緗戠粶鍜孶SB銆?br />
瀹氫綅涓婅鑳滆繃浠誨ぉ鍫係witch鍜屼簯娓告垙鏈嶅姟濡?Stadia 鍜?Amazon Luna.
## 鑳屾櫙
絎?浠f椂闂磋緝闀褲傚洜涓烘懇灝斿畾寰嬶紝榪囧幓鍑犱唬涓鑸瘡浠d負5騫存椂闂達紝浣嗘槸 MS 鍜?Sony 鍑轟簡涓棿浠d駭鍝?Xbox One X 鍜?PS4 Pro.
2020.3 寮濮嬬殑 COVID-19 鐤儏褰卞搷涔熶嬌鏂頒竴浠d富鏈虹殑鍙戝竷寤跺悗浜嗐?br />
## 涓昏涓繪満
### PS5
鏈?涓満鍨嬶紝鍩烘湰鍨嬪拰鏁板瓧鍨嬶紝鏁板瓧鍨嬫病鏈夊厜椹辮緝渚垮疁錛屽叾浠栦竴鏍楓?br />PS5鍜孭S4鐨勬父鎴忓吋瀹癸紝鍙湁灝戦噺娓告垙涓嶆敮鎸侊紝浣嗘槸鍙互閫氳繃 PS Now 浜戞父鎴忔湇鍔$帺 PS4 娓告垙銆?br />
### Xbox Series X/S
MS 寤剁戶浜嗗弻涓繪満妯″紡錛氶珮绔殑X緋誨垪鍜屼綆绔殑S緋誨垪銆係緋誨垪娌℃湁鍏夐┍銆?br />涓よ呴兘鏀寔澶栭儴瀛樺偍鍜孹box Live鍦ㄧ嚎鍒嗗彂銆傚悜鍚庡吋瀹逛互鍓嶇殑娓告垙錛屼絾涓嶅寘鎷琄inect娓告垙銆?br />MS榧撳姳寮鍙戝晢浣跨敤 Smart Delivery錛屾妸Xbox One娓告垙鍗囩駭鍒癤box Series X/S銆?br />
## 鍏朵粬涓繪満
* 浠誨ぉ鍫?Switch
* 浜戞父鎴忓鉤鍙幫細Stadia, Amazon Luna, GeForce Now
]]>
(閲戝簡鐨勪笓鏍?2021.3)
鍙傝冿細
https://wenku.baidu.com/view/83991090336c1eb91b375db8.html
Unity Canvas 鏈変釜 Canvas Scaler 緇勪歡錛岀敤鏉ュ喅瀹?Canvas 鐨?Scale(緙╂斁)鍊箋?br />Scale 鏈?X,Y,Z 3涓垎閲忥紝閮芥槸鍚屼竴鍊鹼紝鍗沖湪鍚勪釜鏂瑰悜涓婇兘鏄悓鍊嶇巼緙╂斁鐨勩?br />瀹冩湁3縐峉cale Mode銆?br />
鍥犱負璁捐鏃剁殑瀹介珮姣斾笌鐩爣鏈哄瀷瀹介珮姣斾笉鍚岋紝Canvas 闇瑕佸厛澧炲噺涓虹洰鏍囬珮瀹芥瘮錛岀劧鍚庡啀緙╂斁銆?br />Canvas 緙╂斁騫朵笉褰卞搷UI鍏冪礌鐨勭浉浜掍綅緗紝鍙槸鍚屾瘮緙╂斁銆?br />浣嗘槸楂樺姣旇皟鏁存椂浼氶犳垚UI鍏冪礌鐨勭浉瀵逛綅緗彉鍖栵紝濡傚搴﹀澶у悗錛孶I鍏冪礌浼氬湪瀹藉害鏂瑰悜涓婄浉浜掓暎寮銆?br />
鍙互鍦?Unity Editor Game 欏靛乏涓婅鍒嗚鯨鐜囦笅鎷夎彍鍗曚腑鍒涘緩鍑犱釜浣庡垎杈ㄧ巼灞忥紝鐢ㄦ潵嫻嬭瘯灞忓箷澶у皬鍒囨崲銆?br />嫻嬭瘯鐣岄潰鍙斁緗?涓寜閽紝涓涓敋瀹氬埌宸︿笂錛屼綅浜庡乏涓婏紝涓涓敋瀹氬埌鍙充笅錛屼綅浜庡彸涓嬶紝涓嶈strech銆?br />
3縐嶆ā寮忓涓嬨?br />
## Constance Pixel Size
Constance Pixel Size 妯″紡涓嬶紝Scale 鎬繪槸涓?銆?br />鐩爣鏈轟笂鐨?Canvas 灝辨槸鍏跺垎杈ㄧ巼澶у皬銆?br />鍥犱負璁捐鏃跺垎杈ㄧ巼涓庡疄闄呭垎杈ㄧ巼涓嶅悓錛屾樉紺轟細涓嶅悓銆?br />浣嗘槸鍥劇墖鍜屾寜閽殑澶у皬淇濇寔鍥哄畾鍍忕礌澶у皬銆?br />濡傛灉灞忓箷鍙樺ぇ錛孶I鍏冪礌灝變細鐩鎬簰鏁e紑錛屽彉灝忓垯鑱氭嫝銆?br />濡傛灉闇瑕佺緝鏀撅紝鍙兘閫氳繃紼嬪簭璋冭妭銆?br />
## Scale With Screen Size
闅忓睆騫曞ぇ灝忕緝鏀俱?br />璇ユā寮忎笅鏈変釜 Reference Resolution (鍙傝冨垎杈ㄧ巼)錛屽簲璇ヨ涓轟富嫻佹満鍨嬬殑鍒嗚鯨鐜囥?br />鍦ㄤ富嫻佹満鍨嬩笅錛孲cale 涓?錛屼笌璁捐鏄劇ず鐩稿悓銆?br />
https://blog.csdn.net/u011948420/article/details/112641308
2020涓浗縐誨姩娓告垙璐ㄩ噺鐧界毊涔?WeTest 鎶ュ憡 Android 鎵嬫満 TOP300 鍒嗚鯨鐜囦負 2340*1080 鍗?31%銆?br />
濡傛灉鐩爣鏈哄瀷涓?4680*2160錛屽垯 Scale 姝eソ涓?錛涘鏋滅洰鏍囨満鍨嬩負 1179*540錛屽垯Scale涓?.5.
涓鑸儏鍐典笅瀹介珮姣斾笉鍚岋紝姝ゆ椂Scale綆楁硶鏈?縐嶏紝鍗?縐峉ceen Match Mode錛?br />
### Match Width Or Height
鍖歸厤瀹藉害鎴栭珮搴︺?br />
姝ゆ椂鏈変釜 Match 鍒掑姩鏉★紝鍙互鍦?Width(0)..Height(1)涔嬮棿銆?br />濡傛灉涓?錛屽尮閰嶅搴︼紝鍒?Scale 涓虹洰鏍囧睆瀹戒笌鍙傝冨睆瀹戒箣姣旓紱
濡傛灉涓?錛屽尮閰嶉珮搴︼紝鍒?Scale 涓虹洰鏍囧睆楂樹笌鍙傝冨睆楂樹箣姣旓紱
濡傛灉涓?.5, 鍔犳潈鍖歸厤錛屽垯鏄繖2涓瘮鍊肩殑騫沖潎鍊箋?br />
鍖歸厤瀹藉害鏃訛紝楂樺害鏂瑰悜涓婁細鏈塙I鎵╂暎鎴栬仛鎷€?br />鍖歸厤楂樺害鏃訛紝瀹藉害鏂瑰悜涓婁細鏈塙I鎵╂暎鎴栬仛鎷€?br />鍔犳潈鍖歸厤鏃訛紝UI鍦ㄩ珮涓婃墿鏁e涓婅仛鎷紝鎴栬呭湪楂樹笂鑱氭嫝瀹戒笂鎵╂暎銆?br />
### Expand
澧炲姞銆傚厛澧炲姞瀹芥垨楂樺埌鐩爣瀹介珮姣斻傝澧炲姞鏂瑰悜UI鍏冪礌浼氭暎寮銆?br />
### Shrink
鍑忓皯銆傚厛鍑忓皯瀹芥垨楂樺埌鐩爣瀹介珮姣斻傝鍑忓皯鏂瑰悜UI鍏冪礌浼氳仛鎷€?br />
## Constant Physical Size
鍥哄畾鐗╃悊澶у皬銆?br />闅忕潃4k灞忕殑鍑虹幇錛屽睆騫旸PI浼氬緢澶э紝璁稿璁懼鐨勫儚绱犵偣闈炲父灝忋?br />鍚屾牱鐨勬寜閽紝鍦ㄩ珮DPI涓嬶紝濡傛灉鍥哄畾鍍忕礌澶у皬錛屽垯浼氶潪甯稿皬錛岃繖鏃墮傚悎鐢ㄨ妯″紡銆?br />
]]>
(閲戝簡鐨勪笓鏍?2020.10)
甯у悓姝ユ湇鍔″櫒浠ュ浐瀹氱殑甯х巼鏀墮泦姣忎釜瀹㈡埛绔殑杈撳叆鍛戒護錛屾瘡甯ф墦鍖呬竴涓懡浠ゅ撫錛屾墦涓婃湇鍔″櫒褰撳墠甯у彿錛?br />鐒跺悗騫挎挱璇ュ懡浠ゅ撫鍒版瘡涓鎴風錛岀敱瀹㈡埛绔墽琛屻?br />濡傛灉娌℃湁瀹㈡埛绔緭鍏ュ懡浠わ紝鍒欒鍛戒護甯у彲鑳藉彧鏈変竴涓撫鍙楓?br />
瀹㈡埛绔殑杈撳叆鍛戒護鍒?縐嶆ā寮忥細涓嶆寚瀹氬撫鍙峰拰鎸囧畾甯у彿銆?br />
瀹㈡埛绔笉鎸囧畾甯у彿鐨勬ā寮忎笅錛屽鎴風浠呭憡璇夋湇鍔″櫒鑷繁鐨勫姩浣滐紝鐢辨湇鍔″櫒涓鴻鍔ㄤ綔鎵撲笂褰撳墠鐨勬湇鍔″櫒甯у彿錛岀劧鍚庡啀騫挎挱銆?br />鏈嶅姟鍣ㄥ疄鐜拌緝綆鍗曪紝鍙渶瑕佺紦瀛樺綋鍓嶅撫鐨勬墍鏈夊鎴風杈撳叆錛屼笅涓甯ф椂鍏ㄩ儴鎵撳寘騫挎挱銆?br />
鎸囧畾甯у彿鐨勬ā寮忎笅錛屽鎴風瑕佹眰璇ュ懡浠ゅ湪鎸囧畾甯?鏈嶅姟鍣ㄥ撫)鎵嶇敓鏁堛?br />鏈嶅姟鍣ㄩ渶瑕佺紦瀛樿鍛戒護錛岃繍琛屽埌鎸囧畾甯у彿鏃訛紝鎵嶅皢璇ュ懡浠ゆ墦鍖呭埌鍛戒護甯у茍騫挎挱鎵鏈夊鎴風銆?br />
鎸囧畾甯у彿鍦ㄥ鎴風鏈夐嫻嬪洖婊氭椂杈冧負鏈夊埄錛屽洜涓哄鎴風鐭ラ亾鑷繁鐨勫懡浠ゅ皢鍦ㄧ‘瀹氱殑甯ф墽琛岋紝鍗沖鑷繁鐨勯嫻嬫繪槸鎴愬姛鐨勩?br />鑰屽鏋滀笉鎸囧畾甯у彿錛屽鎴風闇瑕侀嫻嬭嚜宸辯殑鍛戒護浼氬湪鍝釜鏈嶅姟鍣ㄥ撫鍒拌揪鏈嶅姟鍣紝鑰岃繖鍦ㄧ綉緇滄姈鍔ㄨ緝澶ф椂浼氶嫻嬪け璐ャ?br />
鎸囧畾甯у彿浼氶犳垚鍛戒護鐨勫歡鏃舵椂闂磋緝闀褲傝屼笉鎸囧畾甯у彿灝嗕細绔嬪嵆鎵ц銆?br />
濡傛灉緗戠粶鍫靛浜嗕竴浼氬効錛屽鎴風鍙戦佺殑鍛戒護寤舵椂浜嗚緝闀挎椂闂存墠鍒拌揪鏈嶅姟鍣紝
鎸囧畾鐨勫撫鍙峰彲鑳藉皬浜庢湇鍔″櫒褰撳墠甯у彿錛岃繖鏃舵湇鍔″櫒瀵硅鍛戒護鏈?縐嶅鐞嗘柟寮?
涓縐嶆槸鐩存帴蹇界暐璇ュ懡浠わ紝鍥犱負璇ュ懡浠ゅ凡鏃犳硶瀹炵幇銆?br />涓縐嶆槸灝介噺瀹炵幇璇ュ懡浠わ紝鍗沖湪褰撳墠甯ф墽琛屻?br />鑰冭檻鍒板鎴風棰勬祴錛?縐嶉兘鏄嫻嬪け璐ワ紝鍚屾牱闇瑕佸洖婊氾紝浣嗘槸鍦ㄥ綋鍓嶅撫鎵ц鍙兘鍥炴粴閫犳垚鐨勬姈鍔ㄤ細灝忎竴鐐廣?br />濡傝搗璺沖懡浠わ紝涓縐嶆槸宸茬粡璺寵搗鏉ヤ簡琚媺鍥炲湴闈紝鍥犱負璧瘋煩鍛戒護琚彇娑堜簡錛屼竴縐嶆槸璺沖湪絀轟腑鍋滈】浜嗕竴涓嬶紝鍥犱負璧瘋煩鐨勬椂闂寸偣琚歡鍚庝簡銆?br />灝介噺瀹炵幇鍛戒護搴旇姣斾涪寮冨懡浠ゆ洿濂戒竴鐐廣?br />
濡傛灉鏄湪褰撳墠鏈嶅姟鍣ㄥ撫鎵ц榪囨湡甯у彿鐨勫懡浠わ紝閭d箞榪?縐嶆ā寮忓彲浠ュ悎騫舵垚涓縐嶏紝鍗蟲墍鏈夊懡浠ら兘鏄寚瀹氬撫鍙鳳紝
鍙槸鏈夌殑甯у彿鏄?錛岃〃紺鴻鏈嶅姟鍣ㄥ湪褰撳墠甯ф墽琛屻?br />
閫氱敤鐨勫撫鍚屾鏈嶅姟鍣ㄥ簲璇ヨ瀹㈡埛绔寚瀹氬撫鍙楓?br />
鎸囧畾甯у彿鐨勫懡浠ゅ彲浠ュ疄鐜頒弗鏍兼椂闂撮棿闅旂殑鍛戒護搴忓垪錛?br />瀹㈡埛绔彲浠ヤ竴嬈℃у彂閫佹暣涓懡浠ゅ簭鍒楋紝鎸囧畾姣忎釜鍛戒護涓轟笉鍚岀殑甯у彿銆?br />榪樺簲璇ュ厑璁稿鎴風鎸囧畾鍛戒護搴忓垪鐨勫撫闂撮殧錛屼絾鏄鍛戒護鏄珛鍗蟲墽琛岀殑銆?br />鍛戒護搴忓垪鐨勫撫鍙峰簲璇ユ槸鐩稿浜庨鍛戒護鐨勩?br />濡傛灉鍛戒護搴忓垪鐨勯鍛戒護寤跺悗鎵ц錛岄偅涔堟暣涓簭鍒楀叏閮ㄥ皢鍚屾牱寤跺悗銆?br />
瀹㈡埛绔槸鍚﹂渶瑕佺煡閬撹嚜宸辯殑鎸囧畾甯у彿鍛戒護琚歡鍚庢墽琛屼簡錛熻繖鏍峰彲浠ヨ瀹㈡埛绔湁鏇村ソ鐨勮〃鐜幫紵
閭d箞鎴愬姛鎵ц鐨勬寚瀹氬撫鍙峰懡浠ゆ槸鍚︿篃搴旇璁╁鎴風鐭ラ亾錛?br />鏈嶅姟鍣ㄤ粎浠呮槸灝嗗鎴風鍛戒護鍘熸牱騫挎挱錛屽鎴風鍛戒護涓彲浠ュ姞鍏ュ懡浠ゅ簭鍙鳳紝鑷鍒ゆ柇鍛戒護鏄惁寤跺悗浜嗐?br />
鏄惁灝嗕竴涓帺瀹剁殑鎻愬墠鍙戦佺殑鎸囧畾甯у懡浠ゆ彁鍓嶅箍鎾粰鍏朵粬鐜╁錛?br />榪欐牱鍏朵粬鐜╁涓嶄粎瀵硅嚜宸遍嫻嬫垚鍔燂紝瀵硅鐜╁鐨勯嫻嬩篃鎴愬姛銆?br />浣嗘槸娉勯湶浜嗚嚜宸卞皢瑕佹墽琛岀殑鍔ㄤ綔浼氳鍏朵粬鐜╁鍒╃敤銆?br />鎵浠ユ彁鍓嶉噺涓嶈兘澶ぇ錛屾寚瀹氬撫鍙峰簲璇ュ敖閲忔帴榪戞湇鍔″櫒甯у彿銆?br />鏈嶅姟鍣ㄥ氨涓嶇敤緙撳瓨瀹㈡埛绔寚浠や簡錛岀洿鎺ユ敹鍒板悗騫挎挱鍗沖彲銆?br />榪欐牱鏈嶅姟鍣ㄥ箍鎾殑鍛戒護甯т腑鏈夋湇鍔″櫒甯у彿錛屼篃鏈夊鎴風鐨勬寚瀹氬撫鍙楓?br />鏈嶅姟鍣ㄤ篃灝變笉鐢ㄧ瀹㈡埛绔槸鍚︽寚瀹氬撫鍙蜂簡銆?br />鎸囧畾甯у彿鍜岃В鏋愭垚涓虹函瀹㈡埛绔昏緫銆?br />
]]>
(閲戝簡鐨勪笓鏍?2020.9)
鍦ㄥ帇嫻嬩腑鍙戠幇鎬繪湁鍑犱釜璇鋒眰瓚呮椂錛岃秴鏃舵椂闀胯澶т篃浼氭湁錛岃屾垚鍔熺殑璇鋒眰寤舵椂榪滃皬浜庤秴鏃舵椂闂淬?br />鏌ラ敊鐨勭涓鏂瑰悜鏄煡緗戠粶搴撲腑鏈夋秷鎭涪澶便?br />璺熻釜鎵鏈夋秷鎭紝鍙戠幇瓚呮椂鐨勬秷鎭簲璇ユ槸姝e父澶勭悊騫惰繑鍥炰簡銆?br />浜庢槸鏌ユ帴鏀跺簲絳旀秷鎭悗鐨勫鐞嗭紝鏈緇堟壘鍒頒唬鐮侊細
```go
func (c *Client) onRpcRet(cbIndex uint32, ...) {
ii, ok := c.callbacks.Load(cbIndex)
if !ok {
// logger.Errorf("onRpcRet can not find cbIndex %d", cbIndex) // 鍙兘鏄秴鏃跺凡鍒?br /> return
}
```
鎵撳紑鏃ュ織錛屽彂鐜拌秴鏃剁殑璇鋒眰瀵瑰簲鏈夎鏉¢敊璇棩蹇椼?br />姝ゅ鍥炶皟涓嶅瓨鍦ㄧ殑鎯呭喌錛屾甯告槸鍏堣秴鏃跺垹闄ゅ洖璋冿紝鐒跺悗鍐嶆敹鍒板簲絳斻?br />鐜板湪鏄厛鏀跺埌浜嗗簲絳旓紝鍙戠幇鎵句笉鍒板洖璋冿紝鐒跺悗榪囦簡涓孌墊椂闂翠細琚垽涓鴻秴鏃舵棤鍝嶅簲銆?br />
灝嗕笅闈唬鐮佹崲涓搴忓氨濂戒簡錛?br />```go
if err := c.Session.Send(msg); err != nil {
...
return
}
c.callbacks.Store(cbIndex, ...)
```
鏀逛負
```go
// 蹇呴』鍏堣鍥炶皟錛岀劧鍚庡彂閫侊紝鍥犱負搴旂瓟鍙兘浼氬緢蹇?br /> c.callbacks.Store(cbIndex, ...)
if err := c.Session.Send(msg); err...
```
鍘嬫祴鏃跺洜涓哄姞鍘嬫満CPU鏄弧璐熻澆榪愯漿錛屾墍浠?Send() 鍜?Store() 涔嬮棿鍙兘浼氶棿闅旀暟姣錛?br />瓚沖 rpc 璇鋒眰澶勭悊瀹屾垚騫惰繑鍥烇紝鑰屽簲絳旇繑鍥炴椂鍥炶皟榪樻病璁劇疆銆?br />
鍏?Send() 鍚?Store() 鍐欎唬鐮佷細紼嶅井綆鍗曠偣錛屽洜涓?Send() 澶辮觸鍚庡彲浠ョ洿鎺ヨ繑鍥炪?br />鍏?Store() 鍚?Send() 鏃訛紝Send() 澶辮觸鍒欓渶瑕佺浉搴?Delete().
]]>
(閲戝簡鐨勪笓鏍?2020.9)
## Error1
1. 鐐瑰嚮 "Error1" 鎸夐挳
1. c# showStack.PCall()
1. lua ShowStack()
1. c# Test1()
1. c# try { show.PCall() }
1. lua Show() error('this is error')
```
LuaException: TestErrorStack:2: this is error
stack traceback:
[C]: in function 'error'
TestErrorStack:2: in function <TestErrorStack:1>
[C]: in function 'Test1'
TestErrorStack:6: in function <TestErrorStack:5>
LuaInterface.LuaState:PCall(Int32, Int32) (at Assets/ToLua/Core/LuaState.cs:758)
LuaInterface.LuaFunction:PCall() (at Assets/ToLua/Core/LuaFunction.cs:96)
TestLuaStack:Test1(IntPtr) (at Assets/ToLua/Examples/TestErrorStack/TestLuaStack.cs:27)
LuaInterface.LuaDLL:lua_pcall(IntPtr, Int32, Int32, Int32)
LuaInterface.LuaState:PCall(Int32, Int32) (at Assets/ToLua/Core/LuaState.cs:755)
LuaInterface.LuaFunction:PCall() (at Assets/ToLua/Core/LuaFunction.cs:96)
TestLuaStack:OnGUI() (at Assets/ToLua/Examples/TestErrorStack/TestLuaStack.cs:375)
```
lua Show() 涓姏 error, 鍦?C# 涓?try-catch 寰楀埌錛?br />閫氳繃 toluaL_exception() 榪斿洖 Lua 璋冪敤鑰?ShowStack()錛?br />ShowStack() 涓鎵ц錛屼紶閫掑紓甯稿埌 c# 璋冪敤鑰?OnGUI(),
OnGUI()涓柇鎵ц錛屾墦鍗伴敊璇俊鎭?br />
## Instantiate Error
1. "Instantiate Error"
1. c# GetFunction("Instantiate").PCall()
1. lua Instantiate()
1. c# UnityEngine.Object.Instantiate(obj)
1. c# TestInstantiate.Awake()
1. c# try { GetFunction("Show").PCall() }
1. lua Show()
1. c# state.ThrowLuaException(e)
```
LuaException: TestErrorStack:2: this is error
stack traceback:
[C]: in function 'error'
TestErrorStack:2: in function <TestErrorStack:1>
[C]: in function 'Instantiate'
TestErrorStack:12: in function <TestErrorStack:11>
LuaInterface.LuaState:PCall(Int32, Int32) (at Assets/ToLua/Core/LuaState.cs:758)
LuaInterface.LuaFunction:PCall() (at Assets/ToLua/Core/LuaFunction.cs:96)
TestInstantiate:Awake() (at Assets/ToLua/Examples/TestErrorStack/TestInstantiate.cs:15)
UnityEngine.Object:Instantiate(Object)
UnityEngine_ObjectWrap:Instantiate(IntPtr) (at Assets/ToLua/BaseType/UnityEngine_ObjectWrap.cs:203)
LuaInterface.LuaDLL:lua_pcall(IntPtr, Int32, Int32, Int32)
LuaInterface.LuaState:PCall(Int32, Int32) (at Assets/ToLua/Core/LuaState.cs:755)
LuaInterface.LuaFunction:PCall() (at Assets/ToLua/Core/LuaFunction.cs:96)
TestLuaStack:OnGUI() (at Assets/ToLua/Examples/TestErrorStack/TestLuaStack.cs:391)
```
鍦?lua 涓疄渚嬪寲瀵硅薄錛孉wake() 涓悜lua鎶涘紓甯革細state.ThrowLuaException(e)銆?br />涓浜?lua 璋冪敤鍜?OnGUI(), 浣嗘槸鏂板璞$殑 Start() 鎴愬姛璋冪敤浜嗐?
鍥犱負 Awake() 涓?catch 浜嗗紓甯革紝鎸夋墽琛屾垚鍔熷鐞嗐?br />濡傛灉 Awake() 涓笉 catch, Awake() 鎵ц寮傚父錛屼篃涓嶄細鏈?Start() 璋冪敤錛屼絾鏄痩ua Instantiate() 鎵ц浼氭垚鍔燂紝鎵撳嵃鍑哄璞″悕銆?br />
## Check Error
1. "Check Error"
1. c# GetFunction("TestRay").PCall()
1. lua TestRay() return Vector3.zero
1. c# CheckRay(); //榪斿洖鍊煎嚭閿?br />
```
LuaException: bad argument #2 (Ray expected, got Vector3)
LuaInterface.LuaDLL:luaL_argerror(IntPtr, Int32, String) (at Assets/ToLua/Core/LuaDLL.cs:692)
LuaInterface.LuaDLL:luaL_typerror(IntPtr, Int32, String, String) (at Assets/ToLua/Core/LuaDLL.cs:706)
LuaInterface.LuaStatePtr:LuaTypeError(Int32, String, String) (at Assets/ToLua/Core/LuaStatePtr.cs:534)
LuaInterface.LuaState:CheckRay(Int32) (at Assets/ToLua/Core/LuaState.cs:1505)
LuaInterface.LuaFunction:CheckRay() (at Assets/ToLua/Core/LuaFunction.cs:781)
TestLuaStack:OnGUI() (at Assets/ToLua/Examples/TestErrorStack/TestLuaStack.cs:403)
```
## Push Error
1. "Push Error"
1. c# func.Push(Instance);
```
14:04:31.371-157: Type TestLuaStack not wrap to lua, push as UnityEngine.MonoBehaviour, the warning is only raised once
UnityEngine.Debug:LogWarning(Object)
LuaInterface.Debugger:LogWarning(String)
LuaInterface.Debugger:LogWarning(String, Object, Object)
LuaInterface.LuaState:GetMissMetaReference(Type) (at Assets/ToLua/Core/LuaState.cs:1917)
LuaInterface.LuaStatic:GetMissMetaReference(IntPtr, Type) (at Assets/ToLua/Core/LuaStatic.cs:39)
LuaInterface.ToLua:LoadPreType(IntPtr, Type) (at Assets/ToLua/Core/ToLua.cs:2608)
LuaInterface.ToLua:PushUserObject(IntPtr, Object) (at Assets/ToLua/Core/ToLua.cs:2622)
LuaInterface.ToLua:Push(IntPtr, Object) (at Assets/ToLua/Core/ToLua.cs:2636)
LuaInterface.LuaState:Push(Object) (at Assets/ToLua/Core/LuaState.cs:1378)
LuaInterface.LuaFunction:Push(Object) (at Assets/ToLua/Core/LuaFunction.cs:465)
TestLuaStack:OnGUI() (at Assets/ToLua/Examples/TestErrorStack/TestLuaStack.cs:412)
```
## LuaPushError
1. "LuaPushError"
1. c# GetFunction("PushLuaError").PCall()
1. lua PushLuaError()
1. lua TestStack.PushLuaError()
1. c# PushLuaError()
1. c# try { testRay.Push(Instance); }
浠呮槸璀﹀憡錛屾病鏈夊紓甯?br />
## Check Error
1. "Check Error"
1. c# GetFunction("Test5").PCall()
1. lua Test5()
1. lua TestStack.Test5()
1. c# Test5()
1. c# GetFunction("Test4").PCall()
1. lua TestStack.Test4()
1. c# Test4()
1. c# try { show.PCall() }
```
LuaException: TestErrorStack:2: this is error
stack traceback:
[C]: in function 'error'
TestErrorStack:2: in function <TestErrorStack:1>
[C]: in function 'Test4'
TestErrorStack:30: in function <TestErrorStack:29>
[C]: in function 'Test5'
TestErrorStack:34: in function <TestErrorStack:33>
LuaInterface.LuaState:PCall(Int32, Int32) (at Assets/ToLua/Core/LuaState.cs:758)
LuaInterface.LuaFunction:PCall() (at Assets/ToLua/Core/LuaFunction.cs:96)
TestLuaStack:Test4(IntPtr) (at Assets/ToLua/Examples/TestErrorStack/TestLuaStack.cs:85)
LuaInterface.LuaDLL:lua_pcall(IntPtr, Int32, Int32, Int32)
LuaInterface.LuaState:PCall(Int32, Int32) (at Assets/ToLua/Core/LuaState.cs:755)
LuaInterface.LuaFunction:PCall() (at Assets/ToLua/Core/LuaFunction.cs:96)
TestLuaStack:Test5(IntPtr) (at Assets/ToLua/Examples/TestErrorStack/TestLuaStack.cs:102)
LuaInterface.LuaDLL:lua_pcall(IntPtr, Int32, Int32, Int32)
LuaInterface.LuaState:PCall(Int32, Int32) (at Assets/ToLua/Core/LuaState.cs:755)
LuaInterface.LuaFunction:PCall() (at Assets/ToLua/Core/LuaFunction.cs:96)
TestLuaStack:OnGUI() (at Assets/ToLua/Examples/TestErrorStack/TestLuaStack.cs:434)
```
## Test Resume
1. "Test Resume"
1. c# GetFunction("Test6").PCall()
1. lua Test6()
1. lua 鍗忕▼涓皟鐢?TestStack.Test6(go)
1. c# toluaL_exception()
lua coroutine resume() 榪斿洖 false, 涓嶄細鏈夐敊璇?br />
## out of bound
1. "out of bound"
1. c# GetFunction("TestOutOfBound").PCall()
1. c# TestOutOfBound()
1. c# toluaL_exception(L, e)
```
LuaException: Transform child out of bounds
stack traceback:
[C]: at 0x613c2af0
TestLuaStack:TestOutOfBound(IntPtr) (at Assets/ToLua/Examples/TestErrorStack/TestLuaStack.cs:136)
LuaInterface.LuaDLL:lua_pcall(IntPtr, Int32, Int32, Int32)
LuaInterface.LuaState:PCall(Int32, Int32) (at Assets/ToLua/Core/LuaState.cs:755)
LuaInterface.LuaFunction:PCall() (at Assets/ToLua/Core/LuaFunction.cs:96)
TestLuaStack:OnGUI() (at Assets/ToLua/Examples/TestErrorStack/TestLuaStack.cs:454)
```
## TestArgError
1. "TestArgError"
1. c# GetFunction("Test8").PCall()
1. lua Test8()
1. lua TestArgError()
1. c# TestArgError()
1. c# toluaL_exception(L, e)
```
LuaException: TestErrorStack:69: bad argument #1 to 'TestArgError' (number expected, got string)
stack traceback:
[C]: in function 'TestArgError'
TestErrorStack:69: in function <TestErrorStack:68>
LuaInterface.LuaDLL:luaL_argerror(IntPtr, Int32, String) (at Assets/ToLua/Core/LuaDLL.cs:692)
LuaInterface.LuaDLL:luaL_typerror(IntPtr, Int32, String, String) (at Assets/ToLua/Core/LuaDLL.cs:706)
TestLuaStack:TestArgError(IntPtr) (at Assets/ToLua/Examples/TestErrorStack/TestLuaStack.cs:151)
LuaInterface.LuaDLL:lua_pcall(IntPtr, Int32, Int32, Int32)
LuaInterface.LuaState:PCall(Int32, Int32) (at Assets/ToLua/Core/LuaState.cs:755)
LuaInterface.LuaFunction:PCall() (at Assets/ToLua/Core/LuaFunction.cs:96)
TestLuaStack:OnGUI() (at Assets/ToLua/Examples/TestErrorStack/TestLuaStack.cs:463)
```
## TestFuncDispose
1. "TestFuncDispose"
1. c# func.Dispose();
1. c# func.PCall();
```
LuaException: LuaFunction has been disposed
LuaInterface.LuaFunction:BeginPCall() (at Assets/ToLua/Core/LuaFunction.cs:73)
TestLuaStack:OnGUI() (at Assets/ToLua/Examples/TestErrorStack/TestLuaStack.cs:473)
```
## SendMessage
1. "SendMessage"
1. c# gameObject.SendMessage("OnSendMsg");
1. c# OnSendMsg()
1. c# try { GetFunction("TestStack.Test6").PCall() }
1. c# Test6()
1. c# toluaL_exception(L, e);
```
LuaException: this a lua exception
stack traceback:
[C]: at 0x613c2af0
[C]: in function 'TestArgError'
TestErrorStack:69: in function <TestErrorStack:68>
TestLuaStack:Test6(IntPtr) (at Assets/ToLua/Examples/TestErrorStack/TestLuaStack.cs:122)
LuaInterface.LuaDLL:lua_pcall(IntPtr, Int32, Int32, Int32)
LuaInterface.LuaState:PCall(Int32, Int32) (at Assets/ToLua/Core/LuaState.cs:755)
LuaInterface.LuaFunction:PCall() (at Assets/ToLua/Core/LuaFunction.cs:96)
TestLuaStack:OnSendMsg() (at Assets/ToLua/Examples/TestErrorStack/TestLuaStack.cs:277)
UnityEngine.GameObject:SendMessage(String)
TestLuaStack:OnGUI() (at Assets/ToLua/Examples/TestErrorStack/TestLuaStack.cs:481)
```
SendMessage() 絳夋晥浜庣洿鎺ヨ皟鐢紵
## SendMessageInLua
1. "SendMessageInLua"
1. c# GetFunction("SendMsgError").PCall()
1. lua SendMsgError(go)
1. lua go:SendMessage("OnSendMsg");
```
LuaException: this a lua exception
stack traceback:
[C]: at 0x613c2af0
[C]: in function 'SendMessage'
TestErrorStack:38: in function <TestErrorStack:37>
[C]: in function 'TestArgError'
TestErrorStack:69: in function <TestErrorStack:68>
TestLuaStack:Test6(IntPtr) (at Assets/ToLua/Examples/TestErrorStack/TestLuaStack.cs:122)
LuaInterface.LuaDLL:lua_pcall(IntPtr, Int32, Int32, Int32)
LuaInterface.LuaState:PCall(Int32, Int32) (at Assets/ToLua/Core/LuaState.cs:755)
LuaInterface.LuaFunction:PCall() (at Assets/ToLua/Core/LuaFunction.cs:96)
TestLuaStack:OnSendMsg() (at Assets/ToLua/Examples/TestErrorStack/TestLuaStack.cs:277)
UnityEngine.GameObject:SendMessage(String)
UnityEngine_GameObjectWrap:SendMessage(IntPtr) (at Assets/Source/Generate/UnityEngine_GameObjectWrap.cs:657)
LuaInterface.LuaDLL:lua_pcall(IntPtr, Int32, Int32, Int32)
LuaInterface.LuaState:PCall(Int32, Int32) (at Assets/ToLua/Core/LuaState.cs:755)
LuaInterface.LuaFunction:PCall() (at Assets/ToLua/Core/LuaFunction.cs:96)
TestLuaStack:OnGUI() (at Assets/ToLua/Examples/TestErrorStack/TestLuaStack.cs:488)
```
鍜?"SendMessage" 宸笉澶氫竴鏍楓?br />
## AddComponent
1. "AddComponent"
1. c# GetFunction("TestAddComponent").PCall()
1. c# TestAddComponent()
1. c# try { go.AddComponent<TestInstantiate2>(); }
1. c# TestInstantiate2.Awake()
1. c# state.ThrowLuaException(e);
```
Exception: Instantiate exception 2
LuaInterface.LuaStatePtr.ThrowLuaException (System.Exception e) (at Assets/ToLua/Core/LuaStatePtr.cs:607)
TestInstantiate2.Awake () (at Assets/ToLua/Examples/TestErrorStack/TestInstantiate2.cs:16)
UnityEngine.GameObject:AddComponent()
TestLuaStack:TestAddComponent(IntPtr) (at Assets/ToLua/Examples/TestErrorStack/TestLuaStack.cs:237)
LuaInterface.LuaDLL:lua_pcall(IntPtr, Int32, Int32, Int32)
LuaInterface.LuaState:PCall(Int32, Int32) (at Assets/ToLua/Core/LuaState.cs:755)
LuaInterface.LuaFunction:PCall() (at Assets/ToLua/Core/LuaFunction.cs:96)
TestLuaStack:OnGUI() (at Assets/ToLua/Examples/TestErrorStack/TestLuaStack.cs:498)
```
## TableGetSet
1. "TableGetSet"
## TestTableInCo
1. "TestTableInCo"
1. c# GetFunction("TestCoTable").PCall()
1. lua TestCoTable()
1. lua 榪愯鍗忕▼ TestCo(...)
1. lua TestTableInCo(...)
1. c# TestTableInCo()
## Instantiate2 Error
1. "Instantiate2 Error"
1. c# GetFunction("Instantiate").PCall() with go2
1. lua Instantiate()
1. lua UnityEngine.Object.Instantiate(obj)
1. c# TestInstantiate2:Awake()
```
LuaException: Instantiate exception 2
stack traceback:
[C]: in function 'Instantiate'
TestErrorStack:13: in function <TestErrorStack:11>
[C]: in function 'TestArgError'
TestErrorStack:69: in function <TestErrorStack:68>
TestInstantiate2:Awake() (at Assets/ToLua/Examples/TestErrorStack/TestInstantiate2.cs:11)
UnityEngine.Object:Instantiate(Object)
UnityEngine_ObjectWrap:Instantiate(IntPtr) (at Assets/ToLua/BaseType/UnityEngine_ObjectWrap.cs:203)
LuaInterface.LuaDLL:lua_pcall(IntPtr, Int32, Int32, Int32)
LuaInterface.LuaState:PCall(Int32, Int32) (at Assets/ToLua/Core/LuaState.cs:755)
LuaInterface.LuaFunction:PCall() (at Assets/ToLua/Core/LuaFunction.cs:96)
TestLuaStack:OnGUI() (at Assets/ToLua/Examples/TestErrorStack/TestLuaStack.cs:573)
```
## Instantiate3 Error
1. "Instantiate3 Error"
1. c# UnityEngine.Object.Instantiate(go2);
1. c# TestInstantiate2.Awake()
```
Exception: Instantiate exception 2
LuaInterface.LuaStatePtr.ThrowLuaException (System.Exception e) (at Assets/ToLua/Core/LuaStatePtr.cs:607)
TestInstantiate2.Awake () (at Assets/ToLua/Examples/TestErrorStack/TestInstantiate2.cs:16)
UnityEngine.Object:Instantiate(GameObject)
TestLuaStack:OnGUI() (at Assets/ToLua/Examples/TestErrorStack/TestLuaStack.cs:580)
```
## TestCycle
1. "TestCycle"
1. c# GetFunction("TestCycle").PCall()
1. c# TestCycle()
嫻嬭瘯閫掑綊璋冪敤 luaFunction
## TestNull
1. "TestNull"
1. c# StartCoroutine(TestCo(action));
c# 涓垱寤哄崗紼?br />
## TestMulti
1. "TestMulti"
1. c# GetFunction("TestMulStack").PCall()
1. c# TestMulStack()
1. c# try { TestMul0(); }
1. c# TestMul1()
1. throw
]]>
(閲戝簡鐨勪笓鏍?2020.9.1)
榪欏嚑澶╁湪寮鍙?grpc-tolua, 鍙互鍦?unity 欏圭洰涓嬌鐢?lua 鍙戦?grpc 璇鋒眰錛屾棤闇鐢熸垚浠g爜.
鐜板凡瀹炵幇 route_guide 紺轟緥涓殑鍏ㄩ儴4縐峳pc.
瑙侊細https://github.com/jinq0123/grpc-tolua
鏄ㄥぉ鐨勫紑鍙戜腑灝卞彂鐜幫紝榪愯 RecordRoute 鍜?RouteChat 涔嬪悗Unity鏃犳硶鍐嶆榪愯錛屽繀欏繪潃榪涚▼銆?br />鍦?await 璇彞娣誨姞 `ConfigureAwait(false)` 涔嬪悗錛屽ソ鍍?RouteChat 淇浜嗭紝浣?RecoreRoute 渚濇棫銆?br />
ConfigureAwait(false) 淇濊瘉浜?await 涔嬪悗涓嶄細鎶㈠崰涓葷嚎紼嬶紝鏄В鍐蟲閿佺殑涓縐嶆柟娉曘?br />grpc 婧愮爜涓殑 await 鍚屾牱閮借窡鐫榪欏彞銆?br />
浠婂ぉ鍐嶆嫻嬭瘯錛屽彂鐜?RouteChat 騫舵湭鐪熸淇錛屼粛鏈夎緝澶у彲鑳藉崱姝匯?br />
鏈鍒濈殑鐚滄兂鏄?Lua 鍗忕▼錛孋# 寮傛閫犳垚綰跨▼姝婚攣錛屽洜涓哄寮傛涓嶇啛錛屾繪槸鎬鐤戜嬌鐢ㄦ湁璇?br />鍚庢潵杞彉涓烘煡鎵捐 Unity 鍗℃鐨勯樆濉炲紡鎿嶄綔錛屼絾鏄洜涓烘棩蹇楁樉紺轟笉鍏紝鎵鵑亶浠g爜閮芥病緇撴灉銆?br />闄や簡鍦ㄨ嚜宸辯殑浠g爜涓煡鎵鵑敊璇紝榪樺湪 tolua 浠g爜錛実rpc 浠g爜涓煡鎵撅紝鍒板鎬鐤戙?br />浠婂ぉ涓鏁村ぉ閮藉湪娣誨姞鏃ュ織錛岄噸鍚疷nity涓害榪囥傛彁鍑哄悇縐嶇寽鎯籌紝鍙堝弽澶嶉獙璇併?br />
渚濇閲囩敤浜嗕互涓嬫柟娉曪細
* 姣旇緝C# route_guide 浠g爜錛屾煡鎵懼尯鍒?br />* 涓轟粈涔堟槸 client streaming 綾誨瀷鐨?rpc 鏈夐敊
* 鏌ョ湅 tolua 鍗忕▼錛孴imer
* 娣誨姞 Delay, 鏇存敼鍗忕▼鐨勮繍琛屾搴忥紝鎻愰珮鎴栭檷浣庡鐜板嚑鐜?br />* 鍑芥暟鍏ュ彛鍜岃繑鍥炴坊鍔犳棩蹇楋紝璇佹槑鍏舵病鏈夐樆濉?br />
鏌ユ壘閿欒鐨勬柟娉曟槸鍦ㄤ唬鐮佷腑娣誨姞鏃ュ織錛屾壘鍒板紓甯鎬箣澶勩?br />鏈緇堢殑鐜拌薄鏄疷nity娌℃湁Update()璋冪敤浜嗭紝鍏ㄩ儴鍗℃銆?br />
閿欒婧愪唬鐮佹槸榪欐牱鐨勶紝閿欒鐗堟湰涓?awaiter 鍓嶉潰娌℃湁 local.
```lua
local function await(awaitable)
local awaiter = awaitable:GetAwaiter()
coroutine.wait_until(function()
return awaiter.IsCompleted
end)
end
```
鍥犱負鎯沖疄鐜頒竴涓壒孌婄増鏈殑 await() 鐢ㄤ簬嫻嬭瘯, 鎶?awaiter.IsCompleted 鏀逛負鎬繪槸 false銆?br />澶嶅埗浠g爜鏃訛紝鍙戠幇浜嗗彉閲忕己灝?local.
濡傛灉榪欎釜鎴愪負鍏ㄥ眬鍙橀噺錛岀2嬈″嚱鏁拌皟鐢ㄥ氨浼氭洿鏀圭1嬈¤皟鐢ㄧ殑鍙橀噺錛屾垜绔嬪埢鎰忚瘑鍒頒簡榪欏氨鏄閿佺殑鍘熷洜銆?br />娣誨姞 local 涔嬪悗嫻嬭瘯錛屼竴鍒囬兘姝e父浜嗐?br />
鍒嗘瀽緇撴灉鏄洜涓?awaiter 鏇存敼鍚庯紝await() 鍦ㄤ換鍔″畬鎴愬墠灝辮繑鍥炰簡錛?br />浠ヨ嚧浜庡悗闈㈢殑璇誨彇鎴愪負闃誨寮忔搷浣滐紝闃誨浜嗕富綰跨▼銆?br />
鏌ラ敊鏁堢巼浣庣殑涓昏闂鏄?Unity 鏃ュ織鍦ㄥ崱姝誨墠鐨勬棩蹇楁病鏈夋樉紺猴紝榪欎竴鐐圭洿鍒版渶鍚庢閿佸鐩樻椂鎵嶅彂瑙夈?br />鍥犱負鏃ュ織緙哄け錛屾牴鎹棩蹇楀緱鍑虹殑鎵鏈夊垽鏂嚑涔庨兘閿欎簡銆?br />鏈潵鍙互鏍規嵁鏃ュ織蹇熷畾浣嶇殑鍘熷洜錛岀幇鍦ㄥ畬鍏ㄦ壘閿欐柟鍚戙?br />
濡傛灉鏈夊伐鍏瘋鍛婂叏灞鍙橀噺錛屽氨鍙互閬垮厤榪欎釜閿欒銆?br />
Unity Profiler, VS Debugger 鍥犱負 Unity 瀹屽叏鍗℃錛屾墍浠ユ病浠涔堝府鍔┿?br />
]]>
(閲戝簡鐨勪笓鏍?2020.8)
lua涓笉鍖哄垎 string 鍜?byte[], 鑰屽湪 C# 涓?string 鍜?byte[] 涔嬮棿杞崲娑夊強緙栫爜銆?br />
C# 涓竴鑸繖鏍瘋漿錛?br />
string綾誨瀷杞垚byte[]錛?br />```
byte[] byteArray = System.Text.Encoding.Default.GetBytes(str);
```
byte[]杞垚string錛?br />```
string str = System.Text.Encoding.Default.GetString(byteArray);
```
Default 緙栫爜鏄湰鏈哄綋鍓嶆墍鐢ㄧ紪鐮侊紝榪樺彲浠ョ敤 ASCII, UTF8 絳夊叾浠栫紪鐮併?br />
嫻嬩簡鍦?lua 涓鍏ヤ竴鍧?榪涘埗鏁版嵁錛岃皟鐢?tolua 瀵煎嚭鐨勪竴涓柟娉曪紝濡傦細
```
public void Print(string s)
{
byte[] buf = Systen.Text.Encoding.Default.GetBytes(s);
Debug.Log(Bitconvert.ToString(buf));
}
```
嫻嬩簡 Default, ASCII, UTF8, ISO-8859-1(Latin-1), Unicode 鍙戠幇寰楀埌鐨?byte[] 浼氬嚭閿欍?br />
涔熻瘯浜?[C#涓嬌鐢˙uffer.BlockCopy()鏂規硶灝唖tring杞崲涓篵yte array鐨勬柟娉昡(https://www.cnblogs.com/ChineseMoonGod/p/5689526.html)
鍙戠幇 tolua 浼犲埌 C# 鐨?string 宸茬粡鏄紪鐮佽繃鐨勶紝鐩存帴澶嶅埗涔熸槸閿欑殑銆?br />
xlua 涔熸湁鐩稿悓闂錛孾Unity xlua 浠巐ua浼犻抌yte[]鏁版嵁鍒癈#](https://www.jianshu.com/p/63987134c1ba)
浣跨敤 MemoryStream瀵硅薄鏉ヤ紶閫抌yte[]鏁版嵁錛岀‘瀹炴湁鐐圭粫銆?br />
tolua 涓湁涓?LuaByteBuffer錛屽彲浠ョ敤鏉ヤ紶閫?byte[].
[tolua#涓殑LuaByteBuffer綾籡(http://bbs.ulua.org/article/ulua/toluazhongdeluabytebufferlei.html)
浠?lua 浼?byte[] 鍒?C#, 鍙渶瑕佸皢鍙傛暟 string 鏀逛負 LuaByteBuffer:
```
public void Print(LuaByteBuffer luaByteBuffer)
{
byte[] buf = luaByteBuffer.buffer;
Debug.Log(Bitconvert.ToString(buf));
}
```
鏇存紜張綆鍗曠殑鏂規硶鏄敤 LuaByteBufferAttribute:
```
[LuaByteBufferAttribute]
public void Print(byte[] buf)
{
Debug.Log(Bitconvert.ToString(buf));
}
```
鏈緇堝彂鐜頒笉闇瑕?LuaByteBufferAttribute錛岀洿鎺ョ敤 byte[] 灝辮錛?br />```
public void Print(byte[] buf)
{
Debug.Log(Bitconvert.ToString(buf));
}
```
C# 浼?byte[] 鍒?lua, 榛樿涓?"System.Byte[]"(userdata)錛屽彲浠ョ敤 tostring() 杞負 lua string:
```Lua
s = tolua.tolstring(result)
```
濡傛灉鍙互錛屽簲璇ョ粰鏁版嵁鍔犱笂鏍囩[LuaByteBufferAttribute]錛岃繖鏍蜂紶鍒?lua 灝辨槸 string銆?br />鎴栬呭湪C#寤轟竴涓狶uaByteBuffer鎶奲yte[]浼犵粰lua銆?br />
]]>
(閲戝簡鐨勪笓鏍?2020.6)
Unity 淇濊瘉 async 鏂規硶榪愯鍦ㄤ富綰跨▼涓紝鎵浠ョ敤寮傛鏂瑰紡璋冪敤 grpc 鍙互澶уぇ綆鍖栫綉緇滈氫俊鐨勪唬鐮併?br />
浠ヤ笅紺轟緥涓皢 grpc 鐨?RouteGuide 紺轟緥縐誨埌 Unity 涓繍琛屻?br />https://github.com/grpc/grpc/tree/master/examples/csharp/RouteGuide
鍏朵腑 Main() 涓殑浠g爜縐誨埌 Start() 涓繍琛岋紝闃誨璋冪敤鏀規垚寮傛璋冪敤, GetFeature() 鏀規垚 GetFeatureAsync()銆?br />
瀹屾暣浠g爜瑙侊細https://gitee.com/jinq0123/unity-grpc-async
```
using Grpc.Core;
using Routeguide;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using static Routeguide.Program;
public class Test : MonoBehaviour
{
// Start is called before the first frame update
async void Start()
{
var channel = new Channel("127.0.0.1:50052", ChannelCredentials.Insecure);
var client = new RouteGuideClient(new RouteGuide.RouteGuideClient(channel));
// Looking for a valid feature
await client.GetFeatureAsync(409146138, -746188906);
// Feature missing.
await client.GetFeatureAsync(0, 0);
// Looking for features between 40, -75 and 42, -73.
await client.ListFeatures(400000000, -750000000, 420000000, -730000000);
// Record a few randomly selected points from the features file.
await client.RecordRoute(RouteGuideUtil.LoadFeatures(), 10);
// Send and receive some notes.
await client.RouteChat();
await channel.ShutdownAsync();
Debug.Log("End of test.");
}
}
```
]]>
(閲戝簡鐨勪笓鏍?2020.4)
緗戞父鐨勫尮閰嶅彲浠ュ垎涓?縐嶏細鏈夋埧闂村尮閰嶅拰鏃犳埧闂村尮閰嶃?br />
* 鏈夋埧闂村尮閰?br /> + 璇鋒眰鍖歸厤鍗蟲悳绱㈠茍鍔犲叆涓涓埧闂達紝鎴栬呭紑涓涓柊鎴塊棿銆?br /> + 鍖歸厤榪囩▼涓彲浠ョ湅鍒版埧闂翠漢鏁板鍔犮?br /> + 鍙互鍒楀嚭鍏朵粬鎴塊棿錛屽姞鍏ユ寚瀹氭埧闂達紝濡傛鐗岀被澶у巺
+ 鍙互鏃犻渶絳夊緟浜烘弧鍗沖紑濮嬶紝寮濮嬪悗榪樺彲浠ョ戶緇姞浜?br />* 鏃犳埧闂村尮閰?br /> + 璇鋒眰鍖歸厤鍗寵繘鍏ョ瓑寰呯姸鎬侊紝鍖歸厤鎴愬姛鎵嶈兘鐪嬪埌鎵鏈変漢
+ 鍖歸厤鎴愬姛, 濡備漢婊′簡, 鎵嶅彲浠ヨ繘鍏ユ父鎴?br /> + 鏃犳硶鍔犲叆涓涓凡緇忓紑濮嬬殑娓告垙
鏈夋埧闂寸殑鐢ㄦ埛浣撻獙濂姐傛棤鎴塊棿鍖歸厤鍙互鏇寸簿紜尮閰嶃?br />鏈夋埧闂村尮閰嶅彲鑳介渶瑕佸鐞嗛暱鏃墮棿浜轟笉婊℃椂灝濊瘯鍚堝茍鎴塊棿銆?br />
]]># open-match鍖歸厤嫻佺▼
(閲戝簡鐨勪笓鏍?2019.1)
https://github.com/GoogleCloudPlatform/open-match
open-match 鏄竴涓氱敤鐨勬父鎴忓尮閰嶆鏋躲?br />鐢辨父鎴忔彁渚涜嚜瀹氫箟鐨勫尮閰嶇畻娉曪紙浠ocker闀滃儚鐨勬柟寮忔彁渚涳級銆?br />
鍒嗕負澶氫釜榪涚▼錛屽悇榪涚▼涔嬮棿鍏變韓涓涓?redis.
* 鍓嶇, 鎺ユ敹鐜╁鍔犲叆 redis錛屾垚鍔熷悗閫氱煡鐜╁鎴塊棿鏈嶅湴鍧
* 鍚庣錛岃緗竴灞娓告垙鐨勫尮閰嶈鍒欙紝璁劇疆鎴塊棿鏈嶅湴鍧
* MMFOrc錛屽惎鍔ㄥ尮閰嶇畻娉?MMF)
* MMF, 鑷畾涔夊尮閰嶇畻娉曪紝璇誨彇 redis 鑾峰彇鐜╁錛屽尮閰嶆垚鍔熷氨灝嗙粨鏋滃啓鍏?redis. 浠呭尮閰嶄竴灞灝遍鍑恒?br />
娓告垙鏈嶄腑榪炴帴 open-match 鐨勫墠绔笌鍚庣鐨勮繘紼嬶紝鍒嗗埆縐頒負 frontendclient 鍜?Director銆?br />杈撳叆鍒?閮ㄤ喚錛屼竴鏄帺瀹朵俊鎭紝浜屾槸瀵瑰眬淇℃伅銆?br />Director 鍚戝悗绔緭鍏ュ灞淇℃伅錛屽氨浼氭敹鍒頒竴涓帴涓涓殑瀵瑰眬浜哄憳鍒楄〃.
Director 闇瑕佷負姣忎釜瀵瑰眬寮鎴塊棿錛岀劧鍚庨氱煡鍚庣鎴塊棿鍦板潃銆?br />鍚庣灝嗘埧闂村湴鍧鍐欏叆 redis, 鐒跺悗鍓嶇璇誨彇鍒版埧闂村湴鍧錛屽氨閫氱煡 frontendclient錛岃鐜╁榪涘叆鎴塊棿銆?br />## test/cmd/frontendclient
妯℃嫙澶у巺鏈嶆垨緇勯槦鏈嶏紝榪炴帴鍓嶇API, 璇鋒眰鍖歸厤鐜╁/闃熶紞銆傛垚鍔熷悗灝嗘敹鍒版埧闂存湇(DGS)鐨勫湴鍧(Assignment)銆?br />
Player 瀹為檯涓婃槸涓涓槦浼嶏紝鍏朵腑ID瀛楁鏄敤絀烘牸鍒嗛殧鐨勫涓狪D.
铏界劧鍙傛暟綾誨瀷閮芥槸 Player, CreatePlayer() 鍙傛暟涓烘暣涓槦浼嶏紝鑰?GetUpdates() 鍙傛暟鏄崟涓帺瀹躲?br />
main() 涓垱寤哄涓帺瀹訛紝姣忎釜鐜╁璋冪敤 GetUpdates() 浠ヨ幏鍙栫粨鏋滐紝go waitForResults() 涓鐞嗙粨鏋溿?br />waitForResult() 璇誨彇嫻佷腑鐨勫尮閰嶇粨鏋滐紝鍘嬪叆 resultsChan錛堜絾濂藉儚 resultsChan 浠呯敤浜庢墦鍗幫級銆?br />鎵鏈夌帺瀹跺悎騫跺埌 g 瀹炰緥涓紝鐒跺悗璋冪敤 CreatePlayer() 璇鋒眰鍖歸厤銆?br />
cleanup() 璋冪敤 DeletePlayer() 鏉ュ垹闄ゅ尮閰嶈姹傦紝涓嶄粎闇鍒犻櫎鏁翠釜闃熶紞錛屼篃闇瑕佸垹闄ゅ崟涓帺瀹躲?br />
濂藉儚鏈鍚庡彇緇撴灉娌″彇瀵瑰湴鏂癸紝搴旇浠?resultChan 涓幏鍙?Assignment, 騫剁敤璇ュ湴鍧 udpClient().
鐪嬩簡璇ョず渚嬪氨鍙互鐞嗚В frontend.proto## examples/backendclient
MatchObject.Properties 鏄粠 testprofile.json 璇誨彇鐨勶紝搴旇鏀瑰悕涓?Profile 鏄惁鏇村ソ鐐癸紵
pbProfile 鏄?MatchObject錛孭rofile 絳夊悓浜?MatchObject?
Profile 鐨勫畾涔夋槸 MMF 鎵闇鐨勬墍鏈夊弬鏁般?br />`pbProfile.Properties = jsonProfile` 閲嶅浜?閬嶃?br />
ListMatches()鍒楀嚭榪欎釜Profile鐨勬墍鏈夊尮閰嶃?br />鏀跺埌涓涓尮閰嶅悗錛岄』鐢–reateAssignments()灝嗘埧闂存湇鍦板潃, 縐頒負 Assignment, 鍙戦佸埌鎵鏈夋父鎴忓鎴風銆?br />## cmd/frontendapi
CreatePlayer() 灝?Player 瀵硅薄鍐欏叆 redis, 閿間負 Player.Id, 綾誨瀷涓?HSET銆?br />瀵?Player 鐨勬瘡涓?attribute錛屾坊鍔犲埌 ZSET 涓幓銆?br />姝ゅ Player 鏄竴緇勭帺瀹躲?br />
GetUpdates() 姣忛殧2s璇誨彇redis, Player鏁版嵁鏈夊彉鍖栨椂灝卞彂閫併傛澶?Player 鏄崟涓帺瀹躲?br />
濡傛灉CreatePlayer()涓槦浼嶅彧鏈変竴涓帺瀹訛紝
鍒欏啓鍏ョ殑Player涓嶨etUpdates()涓鍙栫殑鐜╁鏄悓涓涓猺edis閿?br />## cmd/backendapi
CreateMatch() 涓?profile 綾誨瀷涓?MatchObject, 鏄竴涓瘮璧涚殑闄愬埗鏉′歡銆?br />profile 鍏堝啓鍏?redis, 閿負 profile.Id.
`requestKey := xid() + "." + profile.Id`,
騫跺皢 requestKey 鍔犲叆 redis 闆嗗悎 "profileq"銆?br />鐒跺悗姣?s鏌ヨ redis, 鐪嬫槸鍚︽湁 requestKey 閿嚭鐜幫紝騫惰繑鍥炶鍊箋?br />
ListMatch() 姣?s璋冪敤涓嬈?CreateMatch().
DeleteMatch() 浠呬粎鍒犻櫎 Id 榪欎釜閿?br />
CreateAssignments() 涓哄涓槦浼嶈緗瓵ssignment, 鍗蟲埧闂村湴鍧銆?br />閬嶅巻鎵鏈塕oster涓殑Player瀵硅薄錛屽湪redis涓緗瓵ssignment.
(Assignment 鏇存敼鍚庯紝浼氳Е鍙戝墠绔洿鏂般?
灝嗘墍鏈?Player.Id 浠?"proposed" 縐誨埌 "deindexed"錛岃繖涓や釜鏄?ZSET, 鍒嗗間負鍔犲叆鏃墮棿銆?br />Roster 搴旇鏄瘮璧涗腑鐨勯樀钀ワ紝濡傜孩鏂癸紝钃濇柟錛屾瘡涓樀钀ヤ腑鍙湁澶氫釜闃熶紞銆?br />
DeleteAssignments() 浠呬粎閬嶅巻鎵鏈?Player 瀵硅薄鏉ュ垹闄?Assignment 瀛楁銆?br />## cmd/mmforc
鍖歸厤嫻佺▼鏄敱 mmforc (matchmaking function orchestrator) 鎺у埗鐨勩?br />
mmforc 姣忕浠?redis 鐨?profileq 涓彇鍑?100 涓垚鍛? 鍏朵腑 profileq 鏄釜set綾誨瀷錛?br />浣跨敤鍛戒護涓篳SPOP profileq 100`.
瀵規瘡涓?profile, 鍒涘緩涓涓?k8s 浠誨姟錛?br />
```
// Kick off the job asynchrnously
go mmfunc(ctx, profile, cfg, defaultMmfImages, clientset, &pool)
```
姣忛殧10s, 榪樻湁鎵鏈夊尮閰嶄換鍔¢兘瀹屾垚鍚庯紝闇瑕?`checkProposals`, 鍗沖垱寤?evaluator 浠誨姟銆?br />
profileq 涓殑鍏冪礌 profile 涓哄瓧絎︿覆錛宮atchObjectID.profileID銆?br />浠?profileID 涓洪敭錛屽彲浠ヤ粠 redis 璇誨彇 profile 鐨勫唴瀹? profile 鏄釜 MatchObject 瀵硅薄銆?br />
profile 鐨勫唴瀹逛負 json 涓詫紝鍏朵腑 "jsonkeys.mmfImages" 涓?mmf (matchmaking function) 闀滃儚銆?br />
濡傛灉profile璇誨彇澶辮觸錛屾垨鑰?mmfImages 涓虹┖錛屽垯浣跨敤榛樿鐨勯暅鍍忋俶mfImages 鏈潵浼氭敮鎸佸涓暅鍍忋?br />
閫氳繃 MMF_* 鐜鍙橀噺浼犲叆鍚勭鍙傛暟.## mmf
紺轟緥錛歟xamples\functions\golang\manual-simple
浠庣幆澧冨彉閲?"MMF_PROFILE_ID" 瑙f瀽鍑?profileID, 騫跺悜 redis 鏌ヨ(HGETALL) profile錛孒SET 綾誨瀷銆?br />
浠?profile 涓彇 pools 瀛楁錛屽嵆鍖歸厤鏉′歡銆?br />pools 鍒嗕負澶氫釜 pool, 姣忎釜 pool 涓湁澶氫釜 filter, 姣忎釜 filter 鍚?redis 鍙栫鍚堢殑 Player.
profile 鐢ㄥ埌浠ヤ笅瀛楁錛?br />
* "properties.playerPool"
json涓詫紝鏄竴浜涜繃婊ゆ潯浠訛紝濡?#8220;mmr: 100-999”
* "properties.roster"
json涓? 鏄涓槦浼嶅ぇ灝忥紝濡?“red: 4”
紺轟緥瑙侊細`examples\backendclient\profiles\testprofile.json`### 綆鍗曞尮閰嶈繃紼?/h3>
simple mmf 鐨勫尮閰嶈繃紼嬪涓嬶細
1. 浠?redis 鏌ヨ profile錛岃幏鍙栬繃婊ゆ潯浠跺拰鍚勯槦浼嶅ぇ灝?br />1. 姣忎釜榪囨護鏉′歡鍚?redis 鏌ヨ錛屾墍鏈夌粨鏋滅殑浜ら泦涓哄彲閫夋垚鍛?br />1. 鍘婚櫎 ignoreList, 鍗蟲渶榪?800s 鍐呭凡鍖歸厤鎴愬姛鐨勬垚鍛橈紝鍗?proposal 鍜?deindexed ZSET 鍒楄〃銆?br />1. 濡傛灉鍙夋垚鍛樹釜鏁板お灝忥紝鍒?insufficient_players 騫墮鍑?br />1. 鍒嗛厤鍚勪釜闃熶紞鎴愬憳
1. 鍚?redis 璁板綍緇撴灉### 緇撴灉
profile 涓坊鍔?roster錛屽嵆鍚勯樀钀ユ垚鍛樺悕鍗曪紝瀛樺叆 prososalKey.
淇濆瓨涓嶅垎闃熶紞鐨勬垚鍛樺悕鍗曘?br />鐒跺悗鍚?"proposalq" 娣誨姞 prososalKey### 緇嗚妭
poolRosters 浠?(pool鍚? filter attribute) 涓洪敭錛屽間負 Player ID 鍒楄〃.
淇濆瓨浠?redis 鏌ヨ鐨勭鍚堟潯浠剁殑 Player ID.
overlaps 浠?pool 鍚嶄負閿紝淇濆瓨絎﹀悎璇ool涓墍鏈塮ilter鐨?Player ID 鍒楄〃錛屽幓闄?ignore list.
rosters 鏄?profile 涓殑 "properties.rosters" 瀛楁銆備笉鐭ヤ綍鐢紵
閬嶅巻 rosters, 涓烘瘡涓樀钀ョ殑姣忎釜player鎵懼埌瀵瑰簲pool鐨凱layerID, 淇濆瓨鍒?mo.Rosters.
鍏朵腑 profileRosters 濂藉儚娌$敤銆?br />
]]>open-match鐨剅edis鏁版嵁
(閲戝簡鐨勪笓鏍?2018.9)
open-match 鏄疓oogle鐨勫紑婧愭父鎴忓尮閰嶆湇妗嗘灦銆?br />
https://github.com/GoogleCloudPlatform/open-match
鍖歸厤涓墍鐢ㄥ埌鐨勭帺瀹舵暟鎹細淇濆瓨鍦?redis 涓傛煡鐪?br />`open-match\internal\statestorage\redis\playerq\playerq.go`
鍙互浜嗚Вredis淇濆瓨鐨勬暟鎹?br />
redis涓湁浠ヤ笅閿箋?br />playerID
鐜╁ID褰㈠錛歚bfd09c94d646493f834a4abe83a5a68c`, 綾誨瀷涓?hash. 鏈変互涓嬪瓧孌碉細playerID.properties
淇濆瓨鐜╁鏁版嵁鐨刯son涓層傚錛?br />
{
"char.paladin": 1538102377,
"map.eastworld": 1538102377,
"mmr.rating": 1740,
"mode.ctf": 1538102377,
"timestamp.enter": 1538102377
}
鐜╁鏁版嵁鐨勬瘡欏瑰奸兘瑕佹眰涓烘暣鏁?indices
set 綾誨瀷錛屼繚瀛樻墍鏈夌帺瀹舵暟鎹敭銆傚錛?br />
127.0.0.1:6379> smembers indices
1) "timestamp.enter"
2) "map.eastworld"
3) "mmr.rating"
4) "mode.ctf"
5) "char.paladin"
濂藉儚娌$敤鍒般?br />鐜╁鏁版嵁閿?/h2>
濡?`timestamp.enter`, 綾誨瀷涓?zset.
姣忎釜鐜╁鏁版嵁閿兘寤虹珛浜嗕竴涓帓搴忛泦錛屾寜璇ョ帺瀹舵暟鎹兼帓搴忥紝鎴愬憳涓?playerID銆?br />
渚嬪錛?br />
127.0.0.1:6379> zrange mmr.rating 1 3 WITHSCORES
1) "ef3736ef2f7941f1a159f279703d5f58"
2) "746"
3) "17ca3bf3a2134c2c90cbe48ebc29f9cb"
4) "891"
5) "b6450b311f3f413595e824897015c462"
6) "891"
]]>
(閲戝簡鐨勪笓鏍?2018.8)
* 瀹夎 Unit2018, 鏀寔 .NET 4.x
* 鍒涘緩涓涓」鐩紝寮鍚?.NET 4.x
Edit->Project Settings->Player->Other Settings
->Configuration->Script Runtime Version->.Net 4.x Equivalent
* 浠?https://packages.grpc.io/ 鐨?Daily Builds 涓嬭澆鏈鏂扮殑
grpc-protoc_windows_x86-VERSION.zip
grpc_unity_package.VERSION.zip
* grpc_unity_package.VERSION.zip
瑙e帇鍒?Assets 鐩綍涓?br />* 浠?github grpc 澶嶅埗 examples/protos/helloworld.proto 涓?Assets/protos/helloworld.proto
* 鍒涘緩 Assets/Scripts/Greeter/, 騫跺湪璇ョ洰褰曚笅榪愯
protoc.exe -I../../../protos --csharp_out=. ../../../protos/helloworld.proto --grpc_out=. --plugin=protoc-gen-grpc=grpc_csharp_plugin.exe
+ 鐢熸垚 Helloworld.cs HelloworldGrpc.cs
+ 鍒涘緩瀹㈡埛绔茍鍙戝嚭璇鋒眰
var client = new Greeter.GreeterClient(channel);
HelloReply reply = client.SayHello(new HelloRequest { Name = "Jin Qing" });
* 瀹屾暣浠g爜瑙侊細https://gitee.com/jinq0123/unity-grpc-sample
* 鏈鍚庢墦鍖呭畨瑁呭埌鎵嬫満嫻嬭瘯閫氳繃
]]>
(閲戝簡鐨勪笓鏍?2018.7)
緗戞父鏈嶅姟鍣ㄤ腑鐨勬埧闂存湇鍔″櫒鏄湁鐘舵佹湇鍔″櫒錛屽彲浠ョ敤 kubernetes statefulset 寮鍚涓疄渚嬨?br />
涓轟簡璁╁鎴風鑳藉鐩磋繛鎴塊棿鏈嶅姟鍣紝闄や簡 statefulset 瑕佹眰鐨?headless 鏈嶅姟錛?br />榪橀』涓烘瘡涓疄渚嬪垱寤?NodePort 綾誨瀷鐨勬湇鍔? 騫朵笖閫夋嫨Pod鍜岀姝㈣漿鍙戙?br />
涓嬮潰 bootcamp.yml 鍏堝垱寤轟簡 bootcamp headless 鏈嶅姟(clusterIP: None),
鍙堝垱寤轟簡 bootcamp StatefulSet, 瀹炰緥涓暟涓?2.
鐒跺悗鍒涘緩 bootcamp-0,1,2 鏈嶅姟錛屽垎鍒搴?bootcamp-0,1,2 pod.
鏈嶅姟涓暟澶т簬瀹炰緥涓暟錛屾槸鎯蟲祴璇曚笅鏈嶅姟娌℃湁瀵瑰簲鐨勫疄渚嬫椂鐨勮〃鐜般?br />
緗戞父涓殑鍖歸厤鏈嶅姟鍣ㄥ皢鍒嗛厤涓涓埧闂寸粰瀹㈡埛绔紝鍒椾婦 bootcamp-0,1,2 pod 鎵鍦ㄨ妭鐐圭殑澶栫綉 IP,
榪炲悓瀵瑰簲鏈嶅姟鐨勭鍙o紝鍙戦佺粰瀹㈡埛绔紝璁╁鎴風鐩磋繛銆?br />
[jinqing@host-10-240-79-10 statefulset]$ cat bootcamp.yml
apiVersion: v1
kind: Service
metadata:
name: bootcamp
namespace: jq
labels:
name: bootcamp
spec:
ports:
- port: 8080
clusterIP: None # StatefulSet瑕佹眰Headless鏈嶅姟
selector:
app: bootcamp # 閫夋嫨 bootcamp 搴旂敤
---
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
name: bootcamp
namespace: jq
spec:
serviceName: bootcamp # 涓婇潰鐨?Headless 鏈嶅姟鍚?/span>
replicas: 2
template:
metadata:
labels:
app: bootcamp # 搴旂敤鍚嶏紝涓庢湇鍔′腑鐨?selector 瀵瑰簲
spec:
containers:
- name: bootcamp
image: docker.io/jocatalin/kubernetes-bootcamp:v1
---
kind: Service
apiVersion: v1
metadata:
name: bootcamp-0
namespace: jq
spec:
type: NodePort # 瀵瑰鏈嶅姟
externalTrafficPolicy: Local # 涓嶈杞彂鍒板叾浠栬妭鐐?/span>
selector:
app: bootcamp
statefulset.kubernetes.io/pod-name: bootcamp-0 # 閫夋嫨 pod
ports:
- protocol: TCP
nodePort: 30880 # 瀵瑰绔彛
port: 8080
---
kind: Service
apiVersion: v1
metadata:
name: bootcamp-1
namespace: jq
spec:
type: NodePort
externalTrafficPolicy: Local
selector:
app: bootcamp
statefulset.kubernetes.io/pod-name: bootcamp-1
ports:
- protocol: TCP
nodePort: 30881
port: 8080
---
kind: Service
apiVersion: v1
metadata:
name: bootcamp-2
namespace: jq
spec:
type: NodePort
externalTrafficPolicy: Local
selector:
app: bootcamp
statefulset.kubernetes.io/pod-name: bootcamp-2
ports:
- protocol: TCP
nodePort: 30882
port: 8080
鍥犱負 statefulset 鐨勬瘡涓疄渚嬫湁涓嶅悓鐨勬爣絳撅紝鎵浠ュ彲浠ヤ負鏈嶅姟閫夋嫨涓涓疄渚嬨?br />
鍒╃敤 externalTrafficPolicy: Local 璁劇疆鏉ョ姝㈣漿鍙戙?br />鍙傝?service.spec.externalTrafficPolicy 鐨勮鏄庯細
https://kubernetes.io/docs/tutorials/services/source-ip/#source-ip-for-services-with-type-nodeport
Setting service.spec.externalTrafficPolicy to the value Local will only proxy requests to local endpoints, never forwarding traffic to other nodes and thereby preserving the original source IP address. If there are no local endpoints, packets sent to the node are dropped, ...
鍥犱負鏈夊彲鑳藉涓狿od寮鍦ㄥ悓涓鑺傜偣涓婏紝鎵浠ュ澶栫鍙h鎴愪簡涓嶅悓鐨?30880-30882銆?br />濡傛灉闄愬埗姣忎釜鑺傜偣鍙紑涓涓疄渚嬶紝鍒欏澶栫鍙e彲浠ヨ鎴愬悓涓涓?br />
鍒涘緩鏈嶅姟錛?br />
[jinqing@host-10-240-79-10 statefulset]$ kubectl apply -f bootcamp.yml
service "bootcamp" created
statefulset.apps "bootcamp" created
service "bootcamp-0" created
service "bootcamp-1" created
service "bootcamp-2" created
鏈嶅姟濡備笅錛?br />
[jinqing@host-10-240-79-10 statefulset]$ kubectl get service -n jq
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
bootcamp ClusterIP None <none> 8080/TCP 3m
bootcamp-0 NodePort 10.96.128.137 <none> 8080:30880/TCP 3m
bootcamp-1 NodePort 10.109.2.56 <none> 8080:30881/TCP 3m
bootcamp-2 NodePort 10.102.181.193 <none> 8080:30882/TCP 3m
2涓疄渚嬶細
[jinqing@host-10-240-79-10 statefulset]$ kubectl get pod -n jq -o wide
NAME READY STATUS RESTARTS AGE IP NODE
bootcamp-0 1/1 Running 0 4m 10.244.0.42 host-10-240-79-10
bootcamp-1 1/1 Running 0 4m 10.244.1.63 host-10-240-79-11
璁塊棶鏈嶅姟蹇呴』鎸囧畾鑺傜偣錛屼笉浼氳嚜鍔ㄨ漿鍙戯細
[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.10:30880
Hello Kubernetes bootcamp! | Running on: bootcamp-0 | v=1
[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.10:30881
curl: (7) Failed connect to 10.240.79.10:30881; Connection timed out
[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.11:30880
curl: (7) Failed connect to 10.240.79.11:30880; Connection timed out
[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.11:30881
Hello Kubernetes bootcamp! | Running on: bootcamp-1 | v=1
娌℃湁璐熻澆鍧囪 錛?0881绔彛鎬繪槸璁塊棶 bootcamp-1錛?br />
[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.11:30881
Hello Kubernetes bootcamp! | Running on: bootcamp-1 | v=1
[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.11:30881
Hello Kubernetes bootcamp! | Running on: bootcamp-1 | v=1
[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.11:30881
Hello Kubernetes bootcamp! | Running on: bootcamp-1 | v=1
[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.11:30881
Hello Kubernetes bootcamp! | Running on: bootcamp-1 | v=1
[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.11:30881
Hello Kubernetes bootcamp! | Running on: bootcamp-1 | v=1
涔熷彲浠ヤ粠澶栫綉璁塊棶.
30882 绔彛鏃犳硶榪炴帴錛?br />
[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.11:30882
curl: (7) Failed connect to 10.240.79.11:30882; Connection refused
[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.10:30882
curl: (7) Failed connect to 10.240.79.10:30882; Connection refused
3涓鍙i兘鏈夌洃鍚細
[root@host-10-240-79-11 tmp]# netstat -ntl | grep 3088
tcp6 0 0 :::30881 :::* LISTEN
tcp6 0 0 :::30882 :::* LISTEN
tcp6 0 0 :::30880 :::* LISTEN
iptables-save 杈撳嚭濡備笅, 鍏朵腑 10.244鏄疨od鐨勭綉孌點?br />
娌℃湁瀹炰緥榪愯鐨勮妭鐐逛笂錛屼細涓㈠純璇鋒眰錛?br />
-A KUBE-NODEPORTS -s 127.0.0.0/8 -p tcp -m comment --comment "jq/bootcamp-1:" -m tcp --dport 30881 -j KUBE-MARK-MASQ
-A KUBE-NODEPORTS -p tcp -m comment --comment "jq/bootcamp-1:" -m tcp --dport 30881 -j KUBE-XLB-LJXDQ4W47M42IZBH
-A KUBE-NODEPORTS -s 127.0.0.0/8 -p tcp -m comment --comment "jq/bootcamp-0:" -m tcp --dport 30880 -j KUBE-MARK-MASQ
-A KUBE-NODEPORTS -p tcp -m comment --comment "jq/bootcamp-0:" -m tcp --dport 30880 -j KUBE-XLB-U5NEOQT6R5WSBVOH
-A KUBE-XLB-LJXDQ4W47M42IZBH -s 10.244.0.0/16 -m comment --comment "Redirect pods trying to reach external loadbalancer VIP to clusterIP" -j KUBE-SVC-LJXDQ4W47M42IZBH
-A KUBE-XLB-LJXDQ4W47M42IZBH -m comment --comment "jq/bootcamp-1: has no local endpoints" -j KUBE-MARK-DROP
-A KUBE-XLB-U5NEOQT6R5WSBVOH -s 10.244.0.0/16 -m comment --comment "Redirect pods trying to reach external loadbalancer VIP to clusterIP" -j KUBE-SVC-U5NEOQT6R5WSBVOH
-A KUBE-XLB-U5NEOQT6R5WSBVOH -m comment --comment "jq/bootcamp-0: has no local endpoints" -j KUBE-MARK-DROP
鏈夊疄渚嬭繍琛岀殑鑺傜偣涓婁細杞彂緇?Pod 8080錛?br />
-A KUBE-NODEPORTS -s 127.0.0.0/8 -p tcp -m comment --comment "jq/bootcamp-0:" -m tcp --dport 30880 -j KUBE-MARK-MASQ
-A KUBE-NODEPORTS -p tcp -m comment --comment "jq/bootcamp-0:" -m tcp --dport 30880 -j KUBE-XLB-U5NEOQT6R5WSBVOH
-A KUBE-NODEPORTS -s 127.0.0.0/8 -p tcp -m comment --comment "jq/bootcamp-1:" -m tcp --dport 30881 -j KUBE-MARK-MASQ
-A KUBE-NODEPORTS -p tcp -m comment --comment "jq/bootcamp-1:" -m tcp --dport 30881 -j KUBE-XLB-LJXDQ4W47M42IZBH
-A KUBE-XLB-LJXDQ4W47M42IZBH -s 10.244.0.0/16 -m comment --comment "Redirect pods trying to reach external loadbalancer VIP to clusterIP" -j KUBE-SVC-LJXDQ4W47M42IZBH
-A KUBE-XLB-LJXDQ4W47M42IZBH -m comment --comment "Balancing rule 0 for jq/bootcamp-1:" -j KUBE-SEP-LJQA4WUIKJUQ5ALU
-A KUBE-XLB-U5NEOQT6R5WSBVOH -s 10.244.0.0/16 -m comment --comment "Redirect pods trying to reach external loadbalancer VIP to clusterIP" -j KUBE-SVC-U5NEOQT6R5WSBVOH
-A KUBE-XLB-U5NEOQT6R5WSBVOH -m comment --comment "jq/bootcamp-0: has no local endpoints" -j KUBE-MARK-DROP
-A KUBE-SEP-LJQA4WUIKJUQ5ALU -s 10.244.1.63/32 -m comment --comment "jq/bootcamp-1:" -j KUBE-MARK-MASQ
-A KUBE-SEP-LJQA4WUIKJUQ5ALU -p tcp -m comment --comment "jq/bootcamp-1:" -m tcp -j DNAT --to-destination 10.244.1.63:8080
30882 绔彛鏃犳硶榪炴帴
-A KUBE-EXTERNAL-SERVICES -p tcp -m comment --comment "jq/bootcamp-2: has no endpoints" -m addrtype --dst-type LOCAL -m tcp --dport 30882 -j REJECT --reject-with icmp-port-unreachable
嫻嬭瘯涓嬫墿瀹癸細
[jinqing@host-10-240-79-10 statefulset]$ kubectl get statefulset -n jq
NAME DESIRED CURRENT AGE
bootcamp 2 2 45m
[jinqing@host-10-240-79-10 statefulset]$ kubectl scale --replicas=3 statefulset/bootcamp -n jq
statefulset.apps "bootcamp" scaled
[jinqing@host-10-240-79-10 statefulset]$ kubectl get statefulset -n jq
NAME DESIRED CURRENT AGE
bootcamp 3 3 47m
[jinqing@host-10-240-79-10 statefulset]$ kubectl get pod -n jq -o wide
NAME READY STATUS RESTARTS AGE IP NODE
bootcamp-0 1/1 Running 0 48m 10.244.0.42 host-10-240-79-10
bootcamp-1 1/1 Running 0 48m 10.244.1.63 host-10-240-79-11
bootcamp-2 1/1 Running 0 45s 10.244.2.60 host-10-240-79-12
[jinqing@host-10-240-79-10 statefulset]$ curl 10.240.79.12:30882
Hello Kubernetes bootcamp! | Running on: bootcamp-2 | v=1
]]>
(閲戝簡鐨勪笓鏍?2018.3)
鏃犵紳涓栫晫緗戞父鏈嶅姟鍣ㄦ灦鏋勭殑璁捐鎬濊礬
http://blog.csdn.net/SmartTony/article/details/6842065
鎻愬嚭浜?縐嶇綉娓告湇鍔″櫒鏋舵瀯錛?br />
* Services-based architecture 鍩轟簬鏈嶅姟鐨勬灦鏋?br />* Cells-based architecture 鍩轟簬cell鐨勬灦鏋?br />
鍩轟簬鏈嶅姟鐨勬灦鏋勬寜鍔熻兘鍒掑垎鎴愪笉鍚屾湇鍔★紝涓嶅悓鏈嶅姟瀹炵幇浜庝笉鍚岀殑榪涚▼銆?br />鑰屽熀浜巆ell鐨勬灦鏋勪嬌鐢ㄧ浉鍚岀殑Cell榪涚▼緇勬垚涓涓泦緹わ紝姣忎釜Cell榪涚▼鍖呭惈鍏ㄩ儴鐨勫姛鑳姐?br />
鍩轟簬鏈嶅姟鐨勬灦鏋勪竴鐩存槸涓繪祦鐨勬灦鏋勶紝鑷粠 microservice 鍜?service mesh 姒傚康鐩哥戶嫻佽錛?br />鍩轟簬寰湇鍔$殑鏋舵瀯搴旇浼氭垚涓烘湭鏉ョ殑鏂瑰悜銆?br />
鍦ㄦ棤緙濆ぇ鍦板浘緗戞父涓紝搴旇鐢ㄥ熀浜巆ell鐨勬灦鏋勬潵瀹炵幇鍦板浘鍙婄浉鍏沖姛鑳斤紝
鍏朵粬涓庝綅緗棤鍏崇殑鍔熻兘鍒欏簲璇ュ敖閲忔寜鏈嶅姟瀹炵幇銆?br />鑰冭檻鍒版湇鍔℃潵鍥炶皟鐢ㄥ歡鏃惰緝澶э紝瀵逛簬瀹炴椂鎬у己鐨勫姛鑳斤紝濡侾K涔熷簲璇ュ湪cell涓婂疄鐜般?br />
鍙互鑰冭檻瀹㈡埛绔氳繃涓撻棬鐨勭綉鍏蟲潵榪炴帴cell, 浣跨敤udp/kcp鏉ュ噺灝忔椂寤躲?br />鑰屽叾浠栭潪瀹炴椂鎬ф湇鍔$敱Tcp緗戝叧杞彂銆?br />鏈嶅姟鍣ㄥ唴閮ㄥ彲鍏ㄩ儴緇熶竴閲囩敤 gRPC.
]]>
(閲戝簡鐨勪笓鏍?2018.1)
鏃墮棿鐭ヨ錛坱emporal perception錛?瀵瑰瑙傜幇璞$殑寤剁畫鎬у拰欏哄簭鎬х殑鍙嶅簲銆傚疄闄呬笂鏄浜嬩歡鍜岃繍鍔ㄧ殑鐭ヨ銆?br />-- http://dict.youdao.com/w/temporal_perception
緗戞父鏃墮棿浠ユ湇鍔″櫒鐨勪負鍑嗐?br />緗戞父瀹㈡埛绔惤鍚庢湇鍔″櫒渚嬪1甯ф椂闂達紝鎵浠ヨ〃鐜扮殑鏄繃鍘葷殑鍦烘櫙銆?br />鍥犱負鐜╁鑷韓鐨勮涓烘槸宸茬煡鐨勶紝鎵浠ユ湰鍦板彲浠ラ嫻嬭嚜韜鑹茬殑鐘舵侊紝瓚呭墠浜庡叾浠栬鑹層?br />澶勪簬瓚呭墠鏃墮棿鐨勪富瑙掍笌澶勪簬榪囧幓鏃墮棿鐨勫叾浠栬鑹插叡澶勩?br />
This raises the problem of interaction between objects displayed in present time space (the player's avatar) and objects displayed in a past time space (remote characters, AI entities). One solution is to make the LCT vary according to the distance from the player's avatar. This idea is called temporal perception, or presentation time or sometimes local perception filters and comes from the analogy with the appearance of the stars in the sky: the farther the distance, the longer the time the light takes to come to us [Singhal-Zyda].
-- http://www.xlgps.com/article/99968.html 甯﹀闄愬埗涓嬬殑瑙嗚瀹炰綋灞炴т紶鎾?br />
涓昏鍙互涓庤繃鍘繪椂闂寸殑鍏朵粬瑙掕壊浜や簰錛岃窛紱昏秺榪滐紝鍙互鍏佽鐨勬粸鍚庢椂闂村氨瓚婇暱銆?br />榪欎釜姒傚康縐頒綔鏃墮棿鎰熺煡榪囨護鍣?temporal perception filter)錛?br />鎴栬呮湰鍦版劅鐭ヨ繃婊ゅ櫒(local perception filter)銆?br />
鍙互鐢ㄦ槦鏄熶綔綾繪瘮錛屾垜浠湅鍒扮殑涓鍏夊勾榪滅殑鏄熸槦鍏跺疄鏄竴騫村墠鐨勬槦鏄熴?br />
Local Perception Filter Demo
http://mikolalysenko.github.io/local-perception-filter-demo/
]]>
(閲戝簡鐨勪笓鏍?2017.8)
浠跨収 http://www.cnblogs.com/archy_yu/p/3185608.html 瀵?Lua 鍜?C++ 璋冪敤榪涜嫻嬭瘯銆?br />
浠g爜瑙侊細https://github.com/jinq0123/TimerLuaIntf
浣跨敤 LuaIntf 緇戝畾 Lua 鍜?C++銆傜敤 boost timer 璁℃椂銆?br />渚濊禆搴?lua-cpp, lua-intf, boost-timer 鐢?conan 瀹夎銆?br />conan 浼氫笅杞芥簮鐮侊紝緙栬瘧錛岀劧鍚庣敓鎴?conanbuildinfo.props 緇?VS 瀵煎叆錛?br />鍏朵腑璁懼ソ浜嗘墍鏈?include, lib 鐩綍錛岄摼鎺ュ簱錛岃繍琛屽簱銆?br />
浠g爜澶ф濡備笅錛?br />
cout << "C++ calls lua add() many times:\n";
{
boost::timer::auto_cpu_timer t;
for (int i = 0; i < COUNT; ++i)
test.dispatchStatic("add", 123, 456);
}
cout << "C++ calls lua add_times() once:\n";
{
boost::timer::auto_cpu_timer t;
test.dispatchStatic("add_times", 123, 456, COUNT);
}
cout << "Lua calls C++ add() many times:\n";
{
boost::timer::auto_cpu_timer t;
test.dispatchStatic("test_c_add", 123, 456, COUNT);
}
cout << "Lua calls C++ add_times() once:\n";
{
boost::timer::auto_cpu_timer t;
test.dispatchStatic("test_c_add_times", 123, 456, COUNT);
}
嫻嬭瘯4縐嶈皟鐢細
* C++ 璋冪敤 1kw 嬈?lua add()
* C++ 璋冪敤 1 嬈?lua add_times(), 鍏朵腑璋冪敤 add() 1kw 嬈?br />* Lua 璋冪敤 C++ add() 1kw 嬈?br />* Lua 璋冪敤 C++ add_times() 1 嬈★紝鍏朵腑璋冪敤 add() 1kw 嬈?br />
杈撳嚭濡傦細
C++ calls lua add() many times:
2.759473s wall, 2.761218s user + 0.000000s system = 2.761218s CPU (100.1%)
C++ calls lua add_times() once:
0.436400s wall, 0.436803s user + 0.000000s system = 0.436803s CPU (100.1%)
Lua calls C++ add() many times:
0.535802s wall, 0.530403s user + 0.000000s system = 0.530403s CPU (99.0%)
Lua calls C++ add_times() once:
0.000005s wall, 0.000000s user + 0.000000s system = 0.000000s CPU (n/a%)
緇撹鏄細
* C++ 璋冪敤 Lua 鍙揪 3鐧句竾嬈?s
* Lua 鍐呴儴璋冪敤鍑芥暟鍙揪 2鍗冧竾嬈″己/s
* Lua 璋冪敤 C++ 鍑芥暟鍙揪 2鍗冧竾嬈″急/s
]]>
(閲戝簡鐨勪笓鏍?2017.8)
鐢╬rotobuf瀹氫箟鍗忚鏃訛紝鍙埄鐢╬rotobuf鐨勭紪鐮佹柟寮忓皢縐誨姩娑堟伅鍘嬬緝鍒板敖閲忓皬銆?br />
service Battle {
// 縐誨姩鍙樺寲閲忋傚皢騫挎挱緇欏叾浠栫帺瀹訛紝鍖呮嫭鑷繁銆?/span>
// 縐誨姩鍙楁闀塊檺鍒躲傝嚜鍔ㄨ漿鍚戠Щ鍔ㄦ柟鍚戙?/span>
rpc Move(Movement) returns (rpc.EmptyMsg);
// 杞悜鏈緇堥潰鍚戙傚皢騫挎挱緇欏叾浠栫帺瀹訛紝鍖呮嫭鑷繁銆?/span>
rpc TurnTo(Rotation) returns (rpc.EmptyMsg);
}
// 浣嶇疆錛岀Щ鍔ㄥ拰瑙掑害閮界敤鏁存暟鍚戦噺琛ㄧず錛屽崟浣嶄負鍒嗙背.
// 浣跨敤鏁存暟鍗犵敤鐨勫甫瀹芥瘮嫻偣鏁板皯銆?/span>
// U3d浣跨敤浠ョ背涓哄崟浣嶇殑嫻偣鏁幫紝闇瑕佽漿鍖栥?/span>
message Position {
optional sint32 x = 1;
optional sint32 y = 2;
}
// 縐誨姩鏃跺彂閫佺Щ鍔ㄩ噺銆備笉鏄彂閫佺粷瀵逛綅緗紝浣跨敤鏇村皬鐨勬暟瀛楋紝鍗犵敤鏇村皯甯﹀銆?/span>
message Movement {
optional sint32 x = 1;
optional sint32 y = 2;
}
// 瑙掑害鍚戦噺鍦ㄦ弧瓚崇簿搴︾殑鍓嶆彁涓嬶紝搴旇灝介噺浣跨敤緇濆鍊煎皬鐨勬暟鎹〃紺猴紝鍗犵敤鏇村皯甯﹀.
message Rotation {
optional sint32 x = 1;
optional sint32 y = 2;
}
// 浣嶇疆鍜岄潰鍚戙傜敤浜庡垵濮嬪寲瀵硅薄銆?/span>
message PosAndRot {
optional Position position = 1;
optional Rotation rotation = 2;
}
璇存槑
* 鍚嶅瓧鐭偣銆傚洜涓篟PC娑堟伅涓渶甯︽湇鍔″叏鍚嶅拰鏂規硶鍚嶏紝鎵浠ackage, service, method鍚嶅瓧瑕佺煭鐐?br />* 鍧愭爣鐢ㄦ暣鏁拌〃紺恒傛誕鐐規暟浼氬浐瀹氬崰鐢?涓瓧鑺傦紝鑰屾帴榪?鍊肩殑鏁存暟鍊煎彧鍗犵敤涓嶅埌涓涓瓧鑺傘?br />* 浣跨敤縐誨姩鍙樺寲閲忋傚湴鍥懼彲鑳藉緢澶э紝緇濆鍧愭爣鍊艱緝澶т細鍗犵敤鍙樺瀛楄妭錛岃岀Щ鍔ㄩ噺鎬繪槸鎺ヨ繎0
* 瑙掑害浣跨敤鍚戦噺鏇村鏄撳鐞嗐備篃鍙嬌鐢ㄦ暣鏁扮殑瑙掑害鍊?0-360)琛ㄧず錛屼絾澶勭悊楹葷儲銆?br />* 縐誨姩闅愬惈浜嗚漿鍚戙傛墍浠ヨ漿鍚戞秷鎭笉澶氾紝涓嶅繀澶湪鎰忓ぇ灝忋?br />* sint緙栫爜鍘嬬緝鏈澶с傝姹傚湴鍥懼潗鏍囧簲璇ラ兘鍦?闄勮繎錛屾璐熷悇鍗娿?br />* 鍗曚綅閫夋嫨涓嶈澶粏錛屽垎綾沖埌鍘樼背閮藉彲浠ャ?/div>
]]>
(閲戝簡鐨勪笓鏍?2017.8)
Lua璇█娌℃湁鎻愪緵public, private鐨勬蹇碉紝鎵鏈夋ā鍧楁垨綾諱腑鐨勬帴鍙i兘鏄叕鏈夌殑銆?br />
鍙互閫氳繃娉ㄩ噴鏉ュ尯鍒嗗叕鏈夌鏈夋帴鍙c?br />
ldoc 鎻愪緵浜嗕竴涓?@section 鏍囩錛屽彲鐢ㄤ綔姝ゅ姛鑳?br />
--- Test module.
-- @module my_mod
local M = {}
--- Public functions
-- @section public
--- foo.
-- @int a a test input
-- @treturn int result
function M.foo(a)
return a + 1
end
--- Private functions
-- @section private
--- goo.
-- @int a a test input
-- @treturn int result
function M.goo(a)
return a + 2
end
return M
ldoc 鐢熸垚鏂囨。鍚庢槸榪欐牱鐨勶細
]]>
(閲戝簡鐨勪笓鏍?2017.8)
gRPC 鏄?Google 鍙戝竷鐨勫璇█ RPC 搴擄紝瑙?https://github.com/grpc/grpc銆?br />
Unity 2017.1 .Net4.6 鏀寔 async, await, 鍘熸潵 grpc 鍦?Unity 涓婄殑闄愬埗宸茬粡娑堥櫎銆?br />
http://www.sohu.com/a/156779221_280780?qq-pf-to=pcqq.group
紺轟緥鍙互榪愯錛歨ttps://github.com/ahakits/unity-grpc-sample
紺轟緥鑷甫Server, 涔熷彲浠ヨ繍琛?grpc 鐨?hello world server 紺轟緥銆?br />杈撳叆 127.0.0.1, 鐐?Ch" 鍒涘緩 Channel.
鐒跺悗杈撳叆涓涓悕瀛楋紝鐐?"Send" 鍗沖彲鏀跺埌搴旂瓟騫舵樉紺恒?br />
]]>
(閲戝簡鐨勪笓鏍?2017.4)
鍚堢悊璁劇疆緗戞父寮鍙戠洰褰曠粨鏋勶紝鍙互鏂逛究鐩綍鏉冮檺璁劇疆銆?br />
浠ュ墠鍒嗕負3澶у潡錛屽垎鍒搴旂編鏈紝紼嬪簭錛岀瓥鍒掔殑鐩綍銆?br />
Art
Code
Design
涔熸湁鍙兘鏄垎鎴?涓猄VN搴撱?br />涓漢鍊懼悜浜庡垎鎴愬涓簱錛孲VN搴旇鍙繚瀛樻枃鏈枃浠躲?br />
瀵逛簬U3d寮鍙戯紝緹庢湳鍜岀瓥鍒掗渶瑕佹洿鏀瑰鎴風寮鍙戠洰褰曘?br />
Art
Design
Client
Server
Common
]]>
(閲戝簡鐨勪笓鏍?2017.4)
鏈嶅姟鍣ㄥ鎴風涔嬮棿鐨刾rotobuf鍗忚瀹氫箟鍦ㄥ鎴風涓庢湇鍔″櫒鍏叡鐩綍涓嬶紝鍖呭悕涓簉pc.
鏈嶅姟鍣ㄥ唴閮ㄥ崗璁畾涔夊湪鏈嶅姟鍣ㄧ洰褰曚笅錛屽寘鍚嶄負svr.
rpc.EmptyMsg 鍜?svr.EmptyMsg 鍒嗗埆瀹氫箟鍦ㄥ悇鑷殑鏍圭洰褰曪紝鏂囦歡鍚嶉兘鏄?empty_msg.proto.
榪愯鏃跺氨浼氭姤閿欙細
[libprotobuf ERROR E:\deps\protobuf-3.2.0\protobuf-3.2.0\src\google\protobuf\
descriptor_database.cc:57] File already exists in database : empty_msg.proto
[libprotobuf FATAL E:\deps\protobuf-3.2.0\protobuf-3.2.0\src\google\protobuf\
descriptor.cc:1275] CHECK failed: generated_database_->Add(encoded_file_descriptor, size):
鍘熷洜涓鴻瘯鍥劇敤鍚屼竴涓枃浠跺悕"empty_msg.proto"寰descriptor_database娣誨姞descriptor銆?br />
濡傛灉鎸夊寘鍚嶅垎瀛愮洰褰曪紝鏂囦歡鍚嶅氨鍙互鍒嗗紑涓?"rpc/empty_msg.proto" 鍜?"svr/empty_msg.proto".
]]>
(閲戝簡鐨勪笓鏍?2017.3.16)
娓告垙鏄潤鎬侀摼鎺ョ殑榪愯搴擄紝娣誨姞behaviac鍔ㄦ佸簱鍚庯紝榪愯鍑洪敊錛?br />
> ucrtbased.dll!free_dbg_nolock(void * const block, const int block_use) 琛?996 C++
ucrtbased.dll!_free_dbg(void * block, int block_use) 琛?1030 C++
libbehaviac_msvc_debug.dll!operator delete(void * block) 琛?17 C++
libbehaviac_msvc_debug.dll!std::_Deallocate(void * _Ptr, unsigned int _Count, unsigned int _Sz) 琛?132 C++
libbehaviac_msvc_debug.dll!std::allocator<std::_Container_proxy>::deallocate(std::_Container_proxy * _Ptr, unsigned int _Count) 琛?720 C++
libbehaviac_msvc_debug.dll!std::_Wrap_alloc<std::allocator<std::_Container_proxy> >::deallocate(std::_Container_proxy * _Ptr, unsigned int _Count) 琛?988 C++
libbehaviac_msvc_debug.dll!std::_String_alloc<std::_String_base_types<char,std::allocator<char> > >::_Free_proxy() 琛?661 C++
libbehaviac_msvc_debug.dll!std::_String_alloc<std::_String_base_types<char,std::allocator<char> > >::~_String_alloc<std::_String_base_types<char,std::allocator<char> > >() 琛?629 C++
libbehaviac_msvc_debug.dll!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::~basic_string<char,std::char_traits<char>,std::allocator<char> >() 琛?1018 C++
libbehaviac_msvc_debug.dll!behaviac::CTagObject::Save(behaviac::IIONode * node, const char * szClassName) 琛?100 C++
libbehaviac_msvc_debug.dll!behaviac::Agent::InitVariableRegistry() 琛?476 C++
libbehaviac_msvc_debug.dll!behaviac::Agent::Init_(int contextId, behaviac::Agent * pAgent, short priority, const char * agentInstanceName) 琛?227 C++
giant_test_client.exe!behaviac::Agent::InitAgent(behaviac::Agent * pAgent, const char * agentInstanceName, const char * agentInstanceNameAny, bool bToBind, int contextId, short priority) 琛?56 C++
giant_test_client.exe!behaviac::Agent::Create<PlaneAgent>(const char * agentInstanceName, int contextId, short priority) 琛?88 C++
giant_test_client.exe!Client::InitPlayer() 琛?36 C++
giant_test_client.exe!Client::Client() 琛?23 C++
giant_test_client.exe!main() 琛?50 C++
giant_test_client.exe!invoke_main() 琛?64 C++
giant_test_client.exe!__scrt_common_main_seh() 琛?253 C++
giant_test_client.exe!__scrt_common_main() 琛?296 C++
giant_test_client.exe!mainCRTStartup() 琛?17 C++
kernel32.dll!@BaseThreadInitThunk@12() 鏈煡
ntdll.dll!___RtlUserThreadStart@8() 鏈煡
ntdll.dll!__RtlUserThreadStart@8() 鏈煡
鐪嬫潵鏄痵tring璺ㄨ秺鍔ㄦ佸簱鏋愭瀯銆?br />濡傛灉string鍦ㄥ姩鎬佸簱涓瀯閫犲張鏋愭瀯錛屽姩鎬佸簱鐨勮繍琛屾椂搴撳彲浠ヤ笌涓葷▼搴忎笉鍚屻?br />浣嗗鏋滅敤涓葷▼搴忕殑榪愯鏃剁敵璇峰唴瀛橈紝鍦ㄥ姩鎬佸簱涓敤鍙︿竴涓繍琛屾椂搴撻噴鏀撅紝灝變細浜х敓涓婇潰鐨勯敊璇?br />
鍙互寤虹珛涓涓渶灝忓寲鐨勭▼搴忔潵澶嶇幇涓婇潰鐨勯敊璇?br />鏂板緩涓涓涓烘爲錛屼負Agent鍒涘緩涓涓睘鎬с?br />鐒跺悗涓葷▼搴忚繍琛屽簱璁句負錛氬綰跨▼璋冭瘯 (/MTd)錛岃屼笉鏄細澶氱嚎紼嬭皟璇?DLL (/MDd)銆?br />璋冭瘯榪愯鍒涘緩Agent鏃跺氨浼氬嚭涓婇潰閿欒銆?
鐤戦棶鏄繖鏄姩鎬佸簱鍐呴儴璋冪敤錛屾庝箞浼氫駭鐢熻法搴撴瀽鏋勫憿錛?br />
鏂偣榪涘叆string鐨勬瀯閫犺繃紼嬪彲浠ュ彂鐜幫紝string涓嶆槸鍔ㄦ佸簱鏋勯犵殑錛岃屾槸涓葷▼搴忔瀯閫犵殑錛?br />
> test_client.exe!behaviac::StringUtils::internal::ToString(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & val) 琛?138 C++
test_client.exe!behaviac::StringUtils::Detail::ToStringPtrHanler<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,0>::ToString(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & v) 琛?192 C++
test_client.exe!behaviac::StringUtils::Detail::ToStringEnumHanler<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,0>::ToString(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & v) 琛?228 C++
test_client.exe!behaviac::StringUtils::Detail::ToStringStructHanler<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,0>::ToString(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & val) 琛?242 C++
test_client.exe!behaviac::StringUtils::ToString<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & val) 琛?256 C++
test_client.exe!behaviac::SetFromString_t<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,0>::Get(std::basic_string<char,std::char_traits<char>,std::allocator<char> > & value) 琛?790 C++
test_client.exe!behaviac::CProperty<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >::GetValueToString(const behaviac::Agent * self) 琛?848 C++
libbehaviac_msvc_debug.dll!behaviac::CTagObject::Save(behaviac::IIONode * node, const char * szClassName) 琛?97 C++
libbehaviac_msvc_debug.dll!behaviac::Agent::InitVariableRegistry() 琛?476 C++
libbehaviac_msvc_debug.dll!behaviac::Agent::Init_(int contextId, behaviac::Agent * pAgent, short priority, const char * agentInstanceName) 琛?227 C++
test_client.exe!behaviac::Agent::InitAgent(behaviac::Agent * pAgent, const char * agentInstanceName, const char * agentInstanceNameAny, bool bToBind, int contextId, short priority) 琛?56 C++
test_client.exe!behaviac::Agent::Create<PlaneAgent>(const char * agentInstanceName, int contextId, short priority) 琛?88 C++
test_client.exe!Client::InitPlayer() 琛?36 C++
test_client.exe!Client::Client() 琛?23 C++
test_client.exe!main() 琛?50 C++
test_client.exe!invoke_main() 琛?64 C++
test_client.exe!__scrt_common_main_seh() 琛?253 C++
test_client.exe!__scrt_common_main() 琛?296 C++
test_client.exe!mainCRTStartup() 琛?17 C++
kernel32.dll!75c3336a() 鏈煡
[涓嬮潰鐨勬鏋跺彲鑳戒笉姝g‘鍜?鎴栫己澶憋紝娌℃湁涓?kernel32.dll 鍔犺澆絎﹀彿]
ntdll.dll!76fa9902() 鏈煡
ntdll.dll!76fa98d5() 鏈煡
鍘熷洜涓?IProperty::GetValueToString()鏄櫄鍑芥暟錛屽疄闄呭疄鐜版槸鐢變富紼嬪簭瀹炵幇妯℃澘綾匯?br /> behaviac::CProperty<>::GetValueToString()
瑙e喅鏂規涓轟嬌鐢╞ehaviac闈欐佸簱騫朵笖闈欐侀摼鎺ヨ繍琛屾椂搴撱?br />
]]>
(閲戝簡鐨勪笓鏍?2017.3)
璺ㄦ湇Lua璋冪敤鏄寚鏈嶅姟鍣ㄩ泦緹ゅ唴閮ˋ鏈嶈皟鐢˙鏈嶄笂鐨勮剼鏈?br />
鏈嶅姟鍣ㄤ箣闂村凡緇忓疄鐜癛PC璋冪敤錛孡ua璋冪敤鏄疪pc璋冪敤鐨勭畝鍖栨柟寮忋?br />
紺轟緥錛?br /> -- Tell remote server svr_id that game_clt_id is disconnected.
local arguments = { "Remote.ClientDisconnected", game_clt_id }
remote_runner.run_mfa(svr_id, "event.dispatcher",
"dispatch", arguments)
浠ヤ笂渚嬪瓙鐩稿綋浜庤皟鐢ㄤ簡鍏朵粬鏈嶅姟鍣ㄤ笂鐨勪唬鐮侊細
require("event.dispatcher").dispatch("Remote.ClientDisconnected", game_clt_id)
闇瑕佸弬鏁頒負錛?br />* 榪滅▼鏈嶅姟鍣↖D
* Lua妯″潡鍚?br />* Lua妯″潡涓殑鍑芥暟鍚?br />* 璋冪敤鍙傛暟鍒楄〃
remote_runner榪欐牱瀹炵幇錛?br />
-- 榪愯鍙︿竴鏈嶅姟鍣ㄤ笂鐨凩ua浠g爜
-- 涔熸敮鎸佹湰鏈嶈繍琛?鏈湇RPC璋冪敤)
local M = {}
local log = require("log"):new("remote_runner")
local pb = require("protobuf")
local serpent = require("serpent")
-- on_result(result) 鐢熸垚 rpc 鍥炶皟鍑芥暟 cb(resp_str)
local function get_mfa_cb(on_result)
if (not on_result) then return nil end
assert("function" == type(on_result))
local cb = function(resp_str)
assert("string" == type(resp_str))
local resp = pb.decode("svr.RunLuaMfaResponse", resp_str)
local ok, copy = serpent.load(resp.returned_dump)
assert(ok, "Run mfa returns invalid value.")
log:debug("RunLuaMfaResponse: %s", serpent.line(copy))
on_result(table.unpack(copy)) -- 鍥炶皟鏃舵墽琛?/span>
end -- cb
return cb
end -- get_mfa_cb()
-- Run module function with arguments on remote server.
-- 紺轟緥 rum_mfa(123, "event.dispatcher", "dispatch", {"EventName", 1,2,3}, nil)
function M.run_mfa(svr_id, module_name, function_name, arguments, on_result)
assert("number" == type(svr_id))
assert("string" == type(module_name))
assert("string" == type(function_name))
assert("table" == type(arguments))
assert(nil == on_result or "function" == type(on_result))
log:debug("Request to call Svr_%s %s.%s()", svr_id, module_name, function_name)
local req = {
module_name = module_name,
function_name = function_name,
arguments_dump = serpent.dump(arguments)
}
local req_str = pb.encode("svr.RunLuaMfaRequest", req)
local cb = get_mfa_cb(on_result)
c_rpc.request_svr(svr_id, "svr.RunLua", "RunMfa", req_str, cb)
end -- run()
return M
閫氳繃Rpc鏈嶅姟RunLua.RunMfa瀹炵幇銆俽un_lua.proto濡備笅瀹氫箟
syntax = "proto3";
package svr;
// 鏈嶅姟鍣ㄥ唴閮ㄨ法鏈嶈皟鐢↙ua
service RunLua {
// 榪愯 module.function(...arguments...)
rpc RunMfa(RunLuaMfaRequest) returns (RunLuaMfaResponse);
}
message RunLuaMfaRequest {
string module_name = 1;
string function_name = 2;
// arguments_dump = serpent.dump({1,2,3})
string arguments_dump = 3;
}
message RunLuaMfaResponse {
// Get returned table copy:
// local ok, copy = serpent.load(returned_dump)
string returned_dump = 1;
}
鏈嶅姟榪欐牱瀹炵幇錛?br />
-- svc_run_lua.lua
-- Run lua by other servers.
local M = {}
local log = require("log"):new("svc_run_lua")
local pb = require("protobuf")
-- Run module.function(...arguments...)
function M.RunMfa(ctx, content)
local req = pb.decode("svr.RunLuaMfaRequest", content)
log:debug("RunMfa %s.%s", req.module_name, req.function_name) -- todo: from where?
local mod = require(req.module_name)
local fun = mod[req.function_name]
local ok, arguments = serpent.load(serpent.dump(req.arguments_dump))
assert(ok, "Illegal arguments.")
local result_table = table.pack(fun(table.unpack(arguments)))
local resp = { returned_dump = serpent.dump(result_table) }
local resp_str = pb.encode("svr.RunLuaMfaResponse", resp)
c_rpc.reply_to(ctx, resp_str)
end -- Run()
return M
]]>
(閲戝簡鐨勪笓鏍?2017.2)
宸ㄤ漢緗戠粶Lua鎵嬫父鏈嶅姟鍣ㄤ腑csv閰嶇疆緋葷粺鐨勮璁?br />
閰嶇疆鏂囦歡涓?csv 鏍煎紡銆?br />csv鏂囦歡鍏ㄩ儴鏀劇疆浜?csv/ 鐩綍銆?br />csv/鍙互鏈夊瓙鐩綍銆?br />csv鐩綍涓嬫墍鏈塩sv鏂囦歡鍙互鐑洿鏂般?br />
絳栧垝鏁版嵁涔熶細瀵煎嚭鍒癱sv.
csv緙栫爜涓簎tf8甯OM銆?br />濡傛灉涓嶅甫BOM錛宔xcel鎵撳紑涓枃鏄劇ず涔辯爜銆?br />
xlsx鎵歸噺杞負utf8鐨刢sv
http://blog.csdn.net/jq0123/article/details/49512877
瑕佹眰csv瑙f瀽鍣ㄥ厑璁稿琛屽瓧孌碉紝鍏佽鍙屽紩鍙鳳紝蹇界暐BOM銆?br />csv瑙f瀽閲囩敤錛歨ttps://github.com/jinq0123/csv_parser_RFC4180
csv鎸変互涓嬭鑼冨緩绔嬶細
絎?琛岋細瀛楁璇存槑錛屽彲浠ュ琛岋紝鍙互涓枃錛屼粎渚涙敞閲婄敤銆?br /> 璇存槑鏀劇1琛岀殑濂藉鏄細澶氳璇存槑涓嶅獎鍝嶄笅闈㈢殑鏁版嵁鏄劇ず錛屽緛閫旂殑csv涔熸槸璇存槑鍦ㄥ厛銆?br />絎?琛岋細瀛楁鍚嶏紝鑻辨枃錛屽尯鍒嗗ぇ灝忓啓錛屽敖閲忎笉鐢ㄧ壒孌婂瓧絎︺?br /> 鍚屼竴琛ㄥ唴鍚勫瓧孌靛悕蹇呴』涓嶅悓銆?br /> 寤鴻鍏ㄩ儴灝忓啓錛岀敤涓嬪垝綰胯繛鎺ュ崟璇嶏紝濡?server_type", "equip_id".
絎?琛岋細綾誨瀷錛屾湁3縐嶏細string, int, float, 緙虹渷涓簊tring, 鏃犳硶璇嗗埆涔熸寜string澶勭悊銆?br /> int, float鏁版嵁緙虹渷鍊?, 瑙f瀽鏈夐敊鏃朵篃鎸?澶勭悊銆?br />
鎵鏈塩sv鍔犺澆鍚庯紝閫氳繃浠ヤ笅鎺ュ彛鏌ヨ
* 鑾峰彇琛ㄦ牸 get_table("test/test.csv") -> csv/test/test.csv
* 鍙栧叏閮ㄨ褰?table.get_all_records()
* 鎸夌儲寮曞彇璁板綍錛堝彲鑳藉涓級
+ 鍙栫1涓?table.get_record("field1", val1, "field2", val2)
+ 鍙栧涓?table.get_records("field1", val1, "field2", val2)
* 鎸夊垪鍚嶅彇瀛楁
+ record.get_string("field3")
+ record.get_int("field3")
+ record.get_float("field3")
* 鑷姩绱㈠紩錛岄嬈℃煡璇㈠緩绔嬬儲寮?br />* 绱㈠紩鍙互鏄鍒楃粍鍚?br />
]]>
(閲戝簡鐨勪笓鏍?2017.1)
hiredis 涓嶆敮鎸?Windows, Windows 涓嬩嬌鐢?wasppdotorg / hiredis-for-windows 銆?br />Linux 涓嬩粛鏄?redis/hiredis銆?br />hiredis-for-windows 鏄互 hiredis 0.13.3 涓哄熀紜縐繪鐨勩?br />
hiredis-for-windows 闇瑕佺◢鍔犱慨姝o細
* 鍘婚櫎 inline 瀹?br /> * TCP_NODELAY 鏀瑰湪榪炴帴涔嬪墠璁劇疆銆?br />璇﹁鍏禝ssue.
Cluster 鏀寔閲囩敤 shinberg/cpp-hiredis-cluster銆傝繖鏄釜CPP搴擄紝鏀寔寮傛錛?br />瑕佹眰 hiredis >= 0.12.0銆?br />jinq0123/cpp-hiredis-cluster 鍦?develop 鍒嗘敮涓婃洿鏀逛簡鎺ュ彛錛岃瀹冩洿濂界敤銆?br />
鍥犱負緗戠粶搴撴槸boost asio, 鎵浠ラ渶瑕乤sio閫傞厤鍣紝閲囩敤 jinq0123/hiredis-boostasio-adapter銆?br />
cpp-hiredis-cluster 鎻愪緵鐨勬槸緇熶竴鐨凜ommand鎺ュ彛錛屾帴鏀跺瓧絎︿覆鍛戒護錛岃繑鍥?redisReply.
瀵逛簬甯哥敤鍛戒護錛岄渶瑕佹洿綆鍗曠殑鎺ュ彛銆?br />鍦↙ua鎵嬫父鏈嶅姟鍣ㄤ唬鐮佷腑鏂板緩CRedis綾伙紝灝佽 cpp-hiredis-cluster錛?br />涓哄父鐢╮edis鍛戒護灝佽鏇村ソ鐢ㄧ殑鎺ュ彛銆?br />CRedis綾誨皝瑁呬簡asio, 鎺ュ彛鏄牴鎹簲鐢ㄩ渶瑕佸畾涔夌殑錛屾墍浠ユ槸涓撶敤鎺ュ彛錛?br />涓嶅湪 cpp-hiredis-cluster 涓疄鐜般?br />
bool CRedis::Init(io_service& rIos, const std::string& sHost, uint16_t uPort)
鍒涘緩 RedisCluster 瀵硅薄銆?br />io_service 鐢ㄤ簬鍒涘緩涓涓?redis 浜嬩歡閫傞厤鍣紝
RedisCluster鍒涘緩闇瑕佷竴涓傞厤鍣ㄣ?br />sHost, uPort 鐢ㄤ簬鍒濆鍖栬繛鎺edis cluster, 鑾峰彇闆嗙兢淇℃伅銆?br />
using Cmd = RedisCluster::AsyncHiredisCommand;
bool CRedis::Init(io_service& rIos, const std::string& sHost, uint16_t uPort)
{
m_pAdapter.reset(new Adapter(rIos));
try
{
m_pCluster.reset(Cmd::createCluster("127.0.0.1", 7000, *m_pAdapter));
}
catch (const RedisCluster::ClusterException &e)
{
LOG_ERROR("Cluster exception: " << e.what());
return false;
}
return true;
}
static Cmd::Action handleException(const RedisCluster::ClusterException &exception,
RedisCluster::HiredisProcess::processState state)
{
// Check the exception type.
// Retry in case of non-critical exceptions.
if (!dynamic_cast<const RedisCluster::CriticalException*>(&exception))
{
LOG_WARN("Exception in processing async redis callback: "
<< exception.what() << " Retry...");
// retry to send a command to redis node
return Cmd::RETRY;
}
LOG_ERROR("Critical exception in processing async redis callback: "
<< exception.what());
return Cmd::FINISH;
}
static void handleSetReply(const redisReply &reply, const CRedis::SetCb& setCb)
{
if (!setCb) return;
if (reply.type == REDIS_REPLY_STATUS)
{
const std::string OK("OK");
if (OK == reply.str)
{
setCb(true);
return;
}
}
LOG_WARN("Set reply: " << reply.str);
setCb(false);
}
void CRedis::Set(const string& sKey, const string& sValue, const SetCb& setCb)
{
assert(m_pCluster);
Cmd::commandf2(*m_pCluster, sKey,
[setCb](const redisReply& reply) {
handleSetReply(reply, setCb);
},
handleException,
"set %s %s", sKey.c_str(), sValue.c_str());
}
static void handleGetReply(const redisReply& reply,
const CRedis::ReplyStringCb& hdlStrReply)
{
if (!hdlStrReply) return;
using Rt = CRedis::ReplyType;
if (reply.type == REDIS_REPLY_NIL)
{
hdlStrReply(Rt::NIL, "");
return;
}
std::string sReply(reply.str, reply.len);
if (reply.type == REDIS_REPLY_STRING)
hdlStrReply(Rt::OK, sReply);
else
hdlStrReply(Rt::ERR, sReply);
}
void CRedis::Get(const std::string& sKey, const ReplyStringCb& hdlStrRepl)
{
assert(m_pCluster);
Cmd::commandf2(*m_pCluster, sKey,
[hdlStrRepl](const redisReply& reply) {
handleGetReply(reply, hdlStrRepl);
},
handleException,
"get %s", sKey.c_str());
}
handleException 鏄疌md::command() 鎺ュ彛涓渶瑕佺殑寮傚父澶勭悊錛岃繖閲屾槸灝介噺閲嶈瘯銆?br />
Cmd::command() 涓殑絎?涓弬鏁版槸 redis 搴旂瓟鐨勫洖璋冿紝璇誨彇 redisReply, 鐒跺悗瑙﹀彂鍛戒護鐨勫洖璋冦?br />
CRedis::Get() 鎵ц redis GET 鍛戒護錛屽浐瀹?涓弬鏁幫紝榪斿洖鏄瓧絎︿覆錛宯il, 鎴栭敊璇?br />
enum class ReplyType
{
OK = 0, // redis replys string/integer/array
NIL = 1, // redis replys nil
ERR = 2, // redis replys error status
};
// 綆鍗曠殑甯哥敤鍛戒護浼氳嚜鍔ㄨВ鏋恟eply, 浣跨敤鏇存槗鐢ㄧ殑鍥炶皟銆?/span>
using ReplyStringCb = function<void (ReplyType, const string& sReply)>;
CRedis::Get() 鐨勫洖璋冨氨鏄?ReplyStringCb銆?br />
void CRedis::Set() 鐨勫洖璋冨彧闇鐭ラ亾鎴愬姛鎴栧け璐ワ紝SetCb 瀹氫箟涓猴細
using SetCb = function<void (bool ok)>;
澶辮觸鏃朵細鏈夐敊璇俊鎭紝宸茬粺涓鎵撳嵃鏃ュ織錛屼笉鍐嶆毚闇插嚭鏉ャ?br />
SET 鍛戒護瀹屾暣鐨勫弬鏁板垪琛ㄨ繕鏈夊叾浠栧弬鏁幫細
set key value [EX seconds] [PX milliseconds] [NX|XX]
鍥犱負甯哥敤鐨勫氨 "set key value", 鍏朵粬鎵╁睍鐨勫懡浠ら渶瑕佷嬌鐢ㄩ氱敤鐨?command() 鎺ュ彛錛?br />騫墮渶瑕佽鍙?redisReply.
浣跨敤 LuaIntf 瀵煎嚭 CRedis 鍒?Lua.
鍥犱負鍙湁涓涓?CRedis, 鎵浠ュ鍑轟負妯″潡 c_redis:
#include <LuaIntf/LuaIntf.h>
namespace {
void Set(const string& sKey, const string& sValue, const LuaRef& luaSetCb)
{
// Default is empty callback.
auto setCb = ToFunction<CRedis::SetCb>(luaSetCb);
GetRedis().Set(sKey, sValue, setCb);
}
void Get(const string& sKey, const LuaRef& luaReplyStringCb)
{
auto replyStringCb = ToFunction<CRedis::ReplyStringCb>(
luaReplyStringCb);
GetRedis().Get(sKey, replyStringCb);
}
} // namespace
void Bind(lua_State* L)
{
LuaBinding(L).beginModule("c_redis")
.addFunction("set", &Set)
.addFunction("get", &Get)
.endModule();
}
闇瑕佸皢 lua 鐨勫洖璋冨嚱鏁拌漿鎴?cpp 鐨勫洖璋冿細
template <class Function>
Function ToFunction(const LuaIntf::LuaRef& luaFunction)
{
// Default is empty.
if (!luaFunction)
return Function(); // skip nil
if (luaFunction.isFunction())
return luaFunction.toValue<Function>(); // Todo: catch
LOG_WARN_TO("ToFunction", "Lua function expected, but got "
<< luaFunction.typeName());
return Function();
}
Lua 榪欐牱璋冪敤錛?br />c_redis.set("FOO", "1234")
c_redis.set("FOO", "1234", function(ok) print(ok) end)
c_redis.get("FOO", function(reply_type, reply)
assert("string" == type(reply))
if 0 == reply_type or 1 == reply_type then
print("FOO="..reply)
else
print("Error: "..reply)
end
end)
]]>
(閲戝簡鐨勪笓鏍?2016.11)
ejabberd鑱婂ぉ鏈嶅姟鍣ㄩ粯璁や細闄愬埗鍚屼竴IP娉ㄥ唽甯愬彿欏婚棿闅?00s銆?
鍦ㄦ父鎴忎腑闇瑕佷負姣忎釜瑙掕壊娉ㄥ唽涓涓亰澶╁笎鍙鳳紝涓嶅簲璇ユ湁姝ら檺鍒躲?
鍙互鏇存敼鏈嶅姟鍣ㄤ唬鐮侊紝涓烘父鎴忔湇鍔″櫒鍏嶉櫎榪欎竴娉ㄥ唽闂撮殧鏃墮棿銆?
鍋囪娓告垙鏈嶇敤涓撶敤鐨勫笎鍙風櫥褰昬jabberd, 鐒跺悗涓鴻繖縐嶅笎鍙峰厤闄ゆ敞鍐岄檺鍒躲?br />
鍦╡jabberd.yml閰嶇疆璁塊棶鎺у埗鍒楄〃(ACL)涓坊鍔?game_master錛?br />
acl:
game_master:
user:
- "game_master_1@localhost"
- "game_master_2@localhost"
game_master 甯愬彿棰勫厛鍒涘緩錛屼緵娓告垙鏈嶅姟鍣ㄧ櫥褰昬jabberd.
mod_register鐨勯厤緗腑錛屽皢 "access_from: deny" 鏀逛負 "access_from: all".
"access_from: deny" 琛ㄧず浠諱綍鐢ㄦ埛閮戒笉鑳芥敞鍐屽笎鍙鳳紝鍙兘鏄櫥褰曞墠娉ㄥ唽銆?
"access_from: all" 琛ㄧず鐧誨綍鐢ㄦ埛涔熻兘娉ㄥ唽甯愬彿銆?
榪欐牱game_master甯愬彿鍏堢櫥褰曪紝鐒跺悗灝卞彲浠ユ敞鍐屾柊甯愬彿浜嗐?
娣誨姞 access_from_without_time_limit錛屽厑璁竒ame_master鏃犳敞鍐岄檺鍒躲?br />
mod_register:
access_from: all
access: register
## Allow some user register accounts without registration_timeout limit.
access_from_without_time_limit:
- allow: game_master
瀹為檯涓婁篃鍙互榪欐牱鐩存帴閰嶇疆錛?
access_from_without_time_limit:
- allow:
- user: game_master_1@localhost
- user: game_master_2@localhost
閰嶇疆鎴?acl 鐨勫ソ澶勬槸錛屽彲浠ョ敤
ejabberdctl reload_config
閲嶆柊鍔犺澆 acl, 鑰屾ā鍧楅厤緗儴鍒嗘棤娉曢噸鏂板姞杞姐?br />
acl 閰嶇疆榪樺彲浠ュ湪 http admin 鐣岄潰鏇存敼銆?br />
浠g爜闇紼嶅姞鏇存敼錛屼慨鏀筸od_register.erl.
try_register/5 娣誨姞 From 鍙傛暟鏀逛負 try_register/6
try_register(User, Server, Password, From, SourceRaw, Lang)
騫跺皢鍏朵腑
case check_timeout(Source) of
鏀規垚
CheckTimeout = case check_from_without_time_limit(From, Server) of
allow -> true;
_ -> check_timeout(Source)
end,
case CheckTimeout of
鍗沖鏋淔rom鏄痝m甯愬彿鏃訛紝CheckTimeout鐩存帴閫氳繃錛屼笉鍐嶅垽鏂?00s鐨勯棿闅斻?br />
check_from_without_time_limit/2 浠跨収check_from/2錛岃繖鏍峰疄鐜幫細
check_from_without_time_limit(JID, Server) ->
Access = gen_mod:get_module_opt(Server, ?MODULE, access_from_without_time_limit,
fun(A) -> A end,
none),
acl:match_rule(Server, Access, JID).
娣誨姞錛?br />
mod_opt_type(access_from_without_time_limit) ->
fun acl:access_rules_validator/1;
...
mod_opt_type(_) ->
[..., access_from_without_time_limit, ...].
]]>
]]>
(閲戝簡鐨勪笓鏍?
Unity3d涓敤鏃犳覆鏌撶殑閫忔槑鐩掑瓙鎽嗗嚭鍦伴潰鍜岄樆妗e尯鍩熴?br /> this.renderer.enabled = false;
鎵鏈夎繖浜涚洅瀛愯涓篘avigation Static.
闃繪。鐩掑瓙Navigation Layer璁句負 Not Walkable.
鐢‥ditorObjExporter.cs 瀵煎嚭榪欎簺鐩掑瓙鍒皁bj鏂囦歡銆?br />http://wiki.unity3d.com/index.php?title=ObjExporter
鐢≧ecast Demo 鎵撳紑obj鏂囦歡錛屽氨鍙互嫻嬭瘯鍦板浘瀵昏礬浜嗐?br />
]]>