文章列表

Design Pattern: Observer / Subscribers - Push vs Pull

手機‧電玩
MacauYeah・2023-09-29

相信一般入行IT不久的朋友,都會知道IT系統更新時,有推和拉(push、pull)兩種方式。特別是Programer,對於觀察者模式又或者是訂閱者模式(Observer / Subscriber )會有更多的使用經驗,例如:OS programing要處理event bus,Mobile App要做的推送通知(Push Notification)。 但一般來說,很少人討論推和拉(push、pull)的問題,筆者就著一些踩過的坑來說說差異。 首先,在一個通訊相對穩定的系統中,Push、Pull都很好用。例如同一個OS內,它的socket或pipe可以看作很穩定,可以假設那些要廣播的消息可以正常傳遞出好。但好用歸好用,這個模式對於越來越複雜的交互系統都有一個無法明確處理的問題:怎樣去處理觀察者/訂閱者自己的操作失敗問題。 對於非IT行業的讀者來說,只要你接觸過手機即時聊天程式(IM,如whatsapp, wechat, facebook messenger)應該都會遇到一個問題就是:你收到OS提示通知,但打開聊天程式卻看不到新的對話內容;又者是你連續收到多個同一個內容的提示通知,那怕你已經讀過了。這些都代表了,手機端當初時沒有好好即時回應是否已經操作成功,不需要重複通知的問題。有可能是手機當時掛了,也有可能是網絡不太好。 上述的例子,對一般人來說,可能影響不太。因為重複收到訊息,又或是漏了訊息,也不會怎樣。但對於業務系統,例如定期收費,多收一次又或是少收一次,都會引起某部份關係者的不滿,即使事後有退費機制,但有些匯率問題,始終會有差異。在傳統架構上,有規模的公司系統都可能會使用內部的中央資料庫等做交易(transaction)管理,整個過程,都要嚴謹地記錄廣擴是否成功、觀察者自己的操作是否成功。 在近代,分散式系統又或是微服務的出現,令上述的中央資料庫無法實行。如何好好地重新定義好Transaction管理,就是一大挑戰。筆者最近亦實作了一個要在微服務的上廣播的觀察者模式,但雪上加霜的是,在互聯網的環境下,廣播的消息沒法保證可以正常傳遞出好。觀察者/訂閱者可能已經正常收到消息,也做了相應的操作,只是來不及回應,網路就斷了。這令重複發送信號的可能增加了。 如果說,要以平民的方式去實作這類廣播,Pull會比較有大的容錯。廣播者只是通知觀察者/訂閱者來拉資料,保證廣播當時的資料量可以盡量地少。廣播者開放盡量大的查閱權,觀察者/訂閱者可以自由決定事後更新要取得的資料量。但這樣每個觀察者/訂閱者都要重做一次同步機制,不過好處是,主動權在於他們自己手上。 相對地,Push的容錯就低一點,但要付出的成本也跟Pull差不多。因為網路環境,大家要重現一個基於TCP/IP而有commit/rollback的難度較大。當網路出現斷線,廣播者無法確定是否需要重做。在重複收到訊號時,最後還是需要觀察者/訂閱者來決定怎樣處理重複記錄。但比Pull好的是,Push可以限制單次訊號的傳送量,也可以確保觀察者/訂閱者一定收到特定的記錄。 上述就是筆者在這一年來遇過的坑,如有什麼不足,很歡迎大家一起來作更多討論。

Oracle Database in Docker

科技新知
MacauYeah・2023-09-22

雖然筆者之前有提過,Docker並不是萬能,Docker在管理有狀態應用(Stateful Application)的情況下,只能走單機路線。但因為Docker實在很方便,所以連Oracle Database這類強狀態應用也有出Docker版本。當然,它在預設的情況下,只能在單機下操作。 不過即使在單機操作下,還是有一些跟其他Docker Image有差異的地方,需要特別拿出來聊聊。 假設根據官方的教學,跑起了一個oracle19c的Docker Container。再查看當中的Process,你會發現有一個內部PID為1的runOracle.sh 在Docker中這個PID為1的Process是很重要的,它是判斷整個Container有沒有運行的依據。它就是當初在Docker Image中Entrypoint或CMD指定的那個指令生起的Process。Docker daemon要進行停止指令,要停止container時,也是對著PID為1的那個process來處理。 一般的情況下,如果PID為1的那個process可以無腦地停了、重開,那一切都好辦。但在Oracle Database的情況下,就不適合。因為Database始乎都是有交易概念的(Transaction),它的停止並不是殺了process就了事,它還要考慮HDD操作中,有那些可以被考慮為完成,有那些下次要還原(undo)、重做(redo)。如果殺了process就等於Oracle 的Shutdown Abort,有機會下次開機會,就會有交易異常而且無法決定該如何操作。 大家需要先進入Docker container,經sqlplus進行必要的關閉Database指令。但此時,PID為1的那個process,其實還在進行中,在Docker 層面,它就像是Docker Container還在正常運行中,只是Database離線了。又因為sqlplus關閉Database並不是馬上有結果的,所以在整體關閉時可能需要串連command。就像

時空幻境 - 熱情傳奇 (情熱傳說) 心得分享

手機‧電玩
MacauYeah・2023-09-19

雖然這遊戲出了有點久,但對筆者來說真的一波三折。玩完後,有一股很強的感概,所以還是寫編評價來比達一下感受。 時空幻境 熱情傳奇 Tales of Zestiria ,其實是在PS3未期推出的作品,當時亦有跨代登陸PS4。那時亦因為推廣PS PLUS 會員,也作為特別作品送給當時的會員,筆者也是當時就下載了這遊戲。但筆者總因為各種關係,玩到一半,就被其他事情吸走了。再回來,總是覺得斷了片一樣,總是想從頭玩,好好看一遍劇情。就是這樣,前十小時的部份,起碼玩了三次。 這遊戲有這麼吸引嗎?即使不斷重來,也想玩? 首先,這遊戲的總評價真的不算特別好,能玩下去,有一部份出於對Tales of 系列的情懷,而另一部份,就基於友善的暫停機制,以及剛好的ARPG動作遊戲難度。 我們先聊一聊那些做得不夠好的地方 劇情 整體來說,本作劇情走捨身成仁的路線,有一些命題,在前期刻意說一半,故弄玄虛,到最後才解答的劇情。中途夾雜一些奇怪的小黃色笑話。總之就整體很慢熱。 戰鬥 系列的傳統,慢慢地在戰鬥中加入新機制。這作也不列表,前期單人模式,前、中期加入BG神依合體,中期加入爆發特技,中、後期加入秘奧義。 但最麻煩的是普攻(遊戲中叫作【特技】),它一改傳統,普攻由今集開始,也會隨著使用量有改變。一開始只會有段數差異,隨著使用量增加後,同一個段數配搭不同方向會有新招式。概念是好的,但它對Buffering(預按鍵的時機)做得不太好,導致初期筆者試不出方向鍵的差異,久而久之,忘了有這些特別的技能可以用。 以上,就是筆者覺得最讓人有機會棄坑的原因。我們再看看那些吸引人的地方 戰鬥 扣除方向鍵的問題後,其餘的機制也很有探索的深度。【奧義】剋制【特技】,【天響術】剋制【奧義】,【特技】剋制【天響術】。因為任一角色只有其中兩類技能,要變換只能通過【神依】能力,但需消耗BG(有累積條件的資源)來進行。在BG資源短缺的情況下,如何使用特定兩類技能來應付挑戰、決定何時消BG以換得更多優勢的就變得很有必要探討。 它的裝備系統也是對上述這些策略有所影響,不同裝備有額外技能獎勵,有些對BG資源有累積加成,有些對SC回復速度有影響(體似魂系的耐力槽)。能否通過合成去保留技能優勢,同時保持裝備等級跟得上遊戲進度,也是需要研究研究。 如果大家有看Speedrun,除上述策略需要考究外,還要會不斷測試不同角色招式對控場的差異,玩家可以自由選擇其中一位角色進行人手操控,其他交由AI控制。 整個戰鬥機制,筆者在經過50多小時的一週目主線遊玩後,還覺得有探索的空間。所以對筆者來說,戰鬥機制並不沉悶。 可以暫停的系統 這遊戲,除了在少數的特定CG過場外,所有部份都可以暫停。對於筆者這種,忙起上來三分鐘就會被打擾一次的工作/家庭環境,不能暫停的遊戲真的玩不下去。雖然新主機(PS5/Switch等),對於待機功能已經很成熟。但這遊戲是PS3年代的作品阿,那時制作組已經特意制作暫停工能,而且在非劇情和戰鬥的情況下,還提供任意的快速存檔功能,那可是比同類RPG遊戲,什至是動作遊戲,都要友善。多得這個功能,筆者才能少數地完成在PS平台上的遊戲。 劇情 也多得戰鬥的可探索性,以及可以暫停的系統,讓筆者玩到最後,一些劇情上的疑點也得到了解答。整體劇情並不完美,但也不差,能看完結局,也是一件樂事。其中主角的身世的伏線,處理得不錯。開場故意不提,也沒有讓人刻意深討。但越到後越期,在不經意地變得有越來越有關係,多了一份突如奇來的驚喜。 總結 因為多次重玩,所以筆者對於怎樣可以破關,變得很有執念。或許對比現在的遊戲,老遊戲的聲畫表玩顯得過時,但其內的操作機制,筆者還是很推薦大家去試試。

Git Submodule

科技新知
MacauYeah・2023-09-15

Git Submodule 初次實務上使用submodule來同時管理幾個project的更新。如果有任何理解上的錯誤,請在github中提issue或pull request。 Why Submodule 假設你的團隊中有三個人,A君做A Project,B君做B Project,C君做Main Project。如果可以,A,B各提供已編譯的Binary或Library,給C君直接使用就最好。 但要做到好好管理,A,B都要有自己的發佈系統,即是把Binary上傳到某個分享Repo中,這樣C君就能有條理地通過IDE或Compile工具下載對應的版本。如果是javascript,Repo可能就是npm repo,如果是java,可能就是maven repo。這亦代表A,B君對程式編譯、打包、版本命名等都要很熟悉,不能一輩子都命名為v1.0.0。 如果團隊對這些都不熟悉,C君還有什麼方法呢?其實靠著Submodule的功能,C君也可以硬把A,B的Source code取出,做最後打包。 這跟A、B君自己把source code壓縮然後Email寄給C君是有不同的。因為這樣C君並不清楚A,B的git脈絡:C君需要自己做好A、B的版本記錄。想要只回滾A,B的版本普不容易。但經過git Submodule後,C君可以清楚知道現在正使用的是A、B的那一個commit版本。假如有一天,A、B、C三個都更新了,但發現合起來時就跑不動。C君可以保持A、C的版本不變,單獨提取B的某個版本進行測試。當然,你可以說原本Email也可以這樣管理,但始終你不清楚B的版本記錄,Email的日期並不代表Source Code的進度。(因為有時候,Bug Fix是針對舊版本的做更新,新功能的Email日期反而比Bug Fix要早) 同理,如果大家要連結多個沒有發佈系統的文字資料,也可以利用Submodule。例如筆者正在編輯一本書,當中不同的主題,就是使用Submodule的功能串連起。 Command 馬上看來來Submodule可以怎樣做。 假設你已經知道git 怎樣用,也起了git repo。假設你是C君,進入你的本機repo資料夾內,使用submodule參數。 上面的效果,就是把C君當前repo的狀態,連結到B君submodule當時預設分枝(default branch)的最後一個commit 中。然後C君在自己的repo怎樣更新,它引用到B君的submodule版本都不會變。 直到某一刻,B君說他加了一個穩定的新功能,請C也連帶更新一下。C君也做好自己的準備後,使用submodule參數進行更新。 注意,如果C君有多於一個submodule,上述指令會全部一口氣更新。另外,如果你覺得B君的最新版本不能用,還是可以針對B君取得特定的版本。

排程執行任務 | Linux Schedule Job

科技新知
MacauYeah・2023-09-07

在Linux底下,crontab是一個最簡單建立Schedule Job的方法。大家用crontab -e 就可以進入設定。 # crontab -e */1 * * * * /opt/run.sh 其中每個星號,順序代表的是分、時、日、月、星期。上面的例子就是不論何月何日何時,只要每一分鐘就執行一次/opt/run.sh Singleton Job 問題是,實際情況下,你想執行程式的時間都不一定會少於1分鐘。所以你總是有機會上一個job未跑完,下一個job就開始了。為了保障自已,需要一些參考機制,去決定是否讓job開始跑。 有些情況,可能你會想用job server去做監管,但若只為單線執行的工作,起一個job server還是會增加管理上的複雜性。 最簡單的做法,就是根據不同的程式語言,使用file lock(鎖上)的機制,先上鎖,再做事。但要注意考慮有沒有出現異常情況,令你自己反鎖自己。即是你的process死了,但不懂自己解鎖,這樣以後你也不能再執行了。 在Linux Bash Shell下,就有一個很簡單的做法,就是使用flock指令。用它的最大好處,就是從OS層面下,去鎖上。只要process結束了,不論正常還是不正常結束,都會自動解鎖。 以下例子就是在執行/opt/run.sh前,先要取得/tmp/run.lockfile的鎖。如果沒法取鎖,就自動放棄執行後面的指令。 flock -n /tmp/run.lockfile /opt/run.sh # crontab -e */1 * * * * flock -n /tmp/run.lockfile /opt/run.sh Timeout 引入singleton的概念後,其實會引發另一個問題。因為異常的情況,還有機會是不生不死,process hang。所以我們還需要設定一個最大的執行時間,讓你的process在異常的情況下,被強行清走。 例如,ping指令在linux預設是永遠不會自動停止的,可以模擬process hang的情況。如果我們想定時從外部收走ping process,就可以使用timeout指令。以下指令就是2分鐘後殺指ping process。 # in file /opt/run.sh timeout 2m ping localhost # to check process id, you could use # > ps aux | grep ping # you will see two different id for ping and timeout 配合errorcode使用,你可能還會在想在timeout時送出一個email通知自已。 # in file /opt/run.sh timeout 2m ping localhost exitCode=$? if [[ $exitCode -eq 124 ]]; then echo "timeout" # enter email alert with timeout elif [[ $exitCode -gt 0 ]]; then echo "exit with error" # enter email alert with timeout else echo "exit normal" fi 配合docker使用,你可能需要考慮signal怎樣傳遞。 在筆者測試的環境中,似乎SIGTERM會被擋,也有可能是SIGTERM太強,它只把前景的docker container run收走,但其內的ping process還在docker daemon中行走。所以最後改用SIGINT,讓docker container run可以好好地把SIGINT傳入其內。 # It seems that docker captured the SIGTERM. Send SIGINT instead # in file /opt/run.sh timeout --signal=SIGINT 10s docker container run --rm pingtest -c 20 exitCode=$? if [[ $exitCode -eq 124 ]]; then echo "timeout" # enter email alert with timeout elif [[ $exitCode -gt 0 ]]; then echo "exit with error" # enter email alert with timeout else echo "exit normal" fi Full demo, github repo cronjobWithDocker

發佈Docker Swarm App的選擇 - CI/CD系統的參與

科技新知
MacauYeah・2023-08-25

一段時間前,筆者就討論了一些Docker打包的程式的文章,也討論了一些Docker Cluster環境下的選擇。現在也是時候,可以分享一些對於發佈環境的可選空間。 CI/CD系統 CI/CD 全稱是continuous integration (CI) 和 continuous delivery (CD),字面上代表的持續地集成和發佈,實體上就是某台伺服器自動發佈APP。因為使用到Docker Cluster,不論前述什麼選擇 (前文連結 請點這裏),都會有多個node(節點)的出現。要發佈App,總不能一個個node逐個登入設定。所以我們需要一些CI/CD工具,把這個過程都自動化。 在筆者的認知上,CI/CD系統,由兩個部份組成,一個是取得Source Code(程式原始碼)的過程,一個是編譯或發佈Source Code的過程。Gitlab,Github,BitBucket等大型的代碼庫供應商,它們天生為了保存Source Code而提供服務的。不少CI/CD系統都可以跟它們整合,它們提供了存取Source Code的部份,剩下你只要能提供編譯或發佈的伺服器就好。 如果作為小型開發團隊,很少會有意願去自己花錢養一個編譯或發佈的伺服器。(極端地,如果我就是一人團隊,我用自己電腦編譯和發佈就好,伺服器能做的,我自己也能做。)好消息的是,Github提供了一個叫Github Action的CI/CD系統,即使你沒有自己的編譯專用的伺服器,Github Action也可以用Docker Image,提供一個臨時的編譯程序,用完就刪掉。詳細功能還請各位先查看官方教學,筆者也暫時只能零星使用經驗,無法給出有意思的架構。 如果對智慧財產權有高度重視,Source Code不能存放在公開的伺服器,那麼Gitlab Enterprise Edtion則是一個好選擇。運用Gitlab ee,你可以用自己的機器,造一個純本地的庫存伺服器。更強的是,它內建也有CI/CD系統,只要你有間置的伺服器,就可以作為編譯使用。筆者也是從這個方向著手,架設了自己的Gitlab Runner(Gitlab CI/CD系統)。在這裏,就分享一下與Docker Swarm整理的概念。 對於前述兩種選擇,GitLab Runner都可以做得到 底層程式打包成Image並運行在Swarm mode上,每次發佈的是App Binary(執行檔或核心檔案)。 把App直接打包成Image,並運行在Swarm mode上,每次發佈的是App Image。 CI/CD - 打包底層程式成為Image 在這個選擇下,其實就跟傳統自動化發佈的做法類似,只是發佈時,要多個node報行更新指令。如果你使用的底層程式原本就有支援多版本並行,這樣更新時就不用太操心rollback(回滾?)等操作。若系統不支援多版本並行,為求簡化,若遇到要rollback的情況,重跑過去舊的CI/CD操作也是一個做法。當然,我們也可以經過一些備份的操作,來保存被代替的程式,若在發佈過程中出問題,也可以手動重來,不過整件事就越來越複雜。 筆者發佈的基本思路是 使用docker image,編譯和打包App Binary。 使docker image做編譯的好處是,你可以比較放心地假設每次編譯時,你的編譯環境都是乾淨的。 傳送上述的結果至生產環境可以取用的地方。 跳入生產環境執行更新指令 這裏有些隱藏的管理成本,如果你生產環境中有多個node,最後那幾行指令就要多抄幾次。 CI/CD - 打包App成為Image 在這個選擇下,對比傳統自動化發佈的做法,現在要多做一步,就是要包裝自己的Image。不過好處是docker swarm有提供監測工具,在發佈過程每個分身會逐個更新,前一個分身更新成功後才會到下一個分身更新。而且 rollback等的操作,你可以靠docker做到。即是要手動rollback,也可以透過更正docker tags來達到,所以整體上來說沒有比傳統的麻煩。 筆者發佈的基本思路是 編譯App Binary。 打包成docker image。 經docker上傳image。 跳入生產環境執行更新指令。 對比傳統自動化發佈的做法,最後的更新指令,只要執行一次就可以。當然,原本在Docker Swarm中要管理的事還是要好好管理。 CI/CD - 備註事項 雖然CI/CD可以幫忙簡化更新的過程,但實際操作會比上述的例子複雜一些。因為通常對非技術型的外界用戶來說,一個Web App會包含很多不同的功能。上述的例仔,在實際情況下可能需要拆解成很多微服務來進行。所以對管理上還是有相當的挑戰。

Docker Swarm mode 指令教學 | docker service

科技新知
MacauYeah・2023-08-22

之前一直都討論Image 的打包形式,現在聊聊部署上線時的一些指令。 Docker Service swarm mode 主要通過"docker service" 指令去產生一堆可以在不同節點上運行的container。為了更加形象地講,我把container稱為Image的分身。 docker service create跟docker container run的感覺很像,兩者都可以指定image # swarm mode $ docker swarm init $ docker service create --name nginx_s nginx # container mode $ docker container run -d --name nginx_c nginx 兩者的差別在於docker service 可以指定多少個分身,可以隨時加減數目,而且如果你有多過一台機器,分身就會在不同的機器上遊走。而docker container就是只對本機有操作,也不會散播到其他機器。 # swarm mode $ docker service create --replicas=2 --name nginx_s nginx $ docker service ls ID NAME MODE REPLICAS IMAGE PORTS uro4rwy6nelh nginx_s replicated 2/2 nginx:latest $ docker service update --replicas=5 nginx_s $ docker service ls ID NAME MODE REPLICAS IMAGE PORTS uro4rwy6nelh nginx_s replicated 5/5 nginx:latest # container mode $ docker container run -d --name nginx_c1 nginx $ docker container run -d --name nginx_c2 nginx $ docker container run -d --name nginx_c3 nginx $ docker container run -d --name nginx_c4 nginx $ docker container run -d --name nginx_c5 nginx $ docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c45771f06612 nginx "/docker-entrypoint.…" 7 seconds ago Up 6 seconds 80/tcp nginx_c5 a587a718da3a nginx "/docker-entrypoint.…" 9 seconds ago Up 9 seconds 80/tcp nginx_c4 079f206f8645 nginx "/docker-entrypoint.…" 9 seconds ago Up 9 seconds 80/tcp nginx_c3 e10dc525fd22 nginx "/docker-entrypoint.…" 10 seconds ago Up 9 seconds 80/tcp nginx_c2 dcaa2b4bb3de nginx "/docker-entrypoint.…" 10 seconds ago Up 9 seconds 80/tcp nginx_c1 在建立網段時也差不多,service需要的是overlay network,而container用一般network就可以。 # swarm mode $ docker network create --driver overlay nginx_s_gateway $ docker service update --network-add name=nginx_s_gateway,alias=gateway nginx_s $ docker service ps nginx_s ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS fxqtheyvr914 nginx_s.1 nginx:latest dockertest Running Running 33 seconds ago u0pvj1leoizw \_ nginx_s.1 nginx:latest dockertest Shutdown Shutdown 33 seconds ago q7arumjlxduv nginx_s.2 nginx:latest dockertest Running Running 36 seconds ago kurlwqfmopbg \_ nginx_s.2 nginx:latest dockertest Shutdown Shutdown 37 seconds ago zd0zlkhxafv0 nginx_s.3 nginx:latest dockertest Running Running 40 seconds ago 3kapr00fs6pt \_ nginx_s.3 nginx:latest dockertest Shutdown Shutdown 40 seconds ago 5o4afd3whygo nginx_s.4 nginx:latest dockertest Running Running 35 seconds ago oxocropolbo8 \_ nginx_s.4 nginx:latest dockertest Shutdown Shutdown 35 seconds ago x5y94jf3ok51 nginx_s.5 nginx:latest dockertest Running Running 38 seconds ago cgld3au0w1i9 \_ nginx_s.5 nginx:latest dockertest Shutdown Shutdown 39 seconds ago # container mode $ docker network create nginx_c_gateway $ docker network connect --alias gateway nginx_c_gateway nginx_c1 $ docker network connect --alias gateway nginx_c_gateway nginx_c2 $ docker network connect --alias gateway nginx_c_gateway nginx_c3 $ docker network connect --alias gateway nginx_c_gateway nginx_c4 $ docker network connect --alias gateway nginx_c_gateway nginx_c5 不過比較大的差異是service會停了原有的分身,重開新的分身去加入網段。所以上面的docker service ps nginx_s執行結果,就有一半是停掉的。 類似地,docker service也不能單獨地停掉分身,頂多只能調整--replicas=NUMBER,來控制分身數量。而單機則可以經過docker container stop來暫停分身。

異界鎖鏈心得分享

手機‧電玩
MacauYeah・2023-08-18

直接先講結論:好玩,但節奏就差了一點。而這個節奏差,已經算是還不錯的了,起碼比之後發售的獵天使魔女3要好。 一個成功的大膽新嘗試 本作採取單手制雙角色操作,左搖桿為主角行動,右搖桿為召喚前為視角控制、召喚後為雷基恩行動。 經典動作遊戲操作:主角使用ZR作普攻、按ZL召喚雷基恩自動攻擊。在攻擊、極限躲避時,可以在特定時機按ZL與雷基恩發動(多從)同步攻擊。按R與雷基恩作合體技。 以上操作,大家都可以示為單人操作,雷基恩就像武器Buff一樣使用。(像不像DMC系列?) 大膽就玩法:在召喚出雷基恩後,雙角色在交換走位後有一些策略行動:追擊、跳躍、捆綁等組合攻擊。重按ZL可以拉回雷基恩,同時按ZL+ZR可以跳躍到雷基恩身邊。再跳躍過程中,可順帶對沿途敵人攻擊(一個比DMC4的NERO 魔抓更自主的機制)。這些動作因為要用左右搖桿操作兩角色走位,體驗非常新奇。 筆者動作遊戲的能力一般,沒有研究極限操作,但光是玩它的基本操作,就已經體會到它的樂趣。動作遊戲方面,絕對對得起白金工作室的招牌。筆者亦無法言喻太多,總之玩就對了。 好的說完,就要講講它的毛病。 那個還是不太好的關卡節奏 白金工作室,在很多人眼中會認為是很夠誠意。因為它會加入很多不同的小遊戲小關卡,讓大家可以在高強度的戰鬥中,有時間轉換心情。小關卡或解迷或收集物品,操作也多樣化。 但對筆者來說,這些都很打擾遊玩主線的心情。特別是以最近的獵天使魔女3為例,突然提示你去收集、整個關卡變2D潛行、不適時的動畫過場、特定遲鈍的召喚獸追逐戰,都讓你想好好地玩人型動作遊戲的情緒比打斷。 好在,異界鎖鏈這方面都控制得比較好。小遊戲可以跳過不玩,整關轉變操作模式的情況沒有出現。 雖然如此,但戰鬥過程中總是要加入一些跳躍平台的操作。即便最後打尾王,還是要那樣的調性,一失足又要整段重來。如果你的體驗也於設計跑酷類動作跳躍,我也算了,但一邊格鬥一邊跳,跳完一點都不讓人覺到爽快,那就很礙事。到後來筆者就只能說服自己,這就是白金工作室眼中覺得最有挑戰的東西,如果成功了一定會讓玩家自豪。 綜合評價 總體來講,如果你對各種動作解迷類型都很接受,異界鎖鏈的整體表現一定讓你很滿意。如果你不喜歡在同一個章節中被小遊戲支線打斷、不喜歡突如奇來的平台跳躍,只喜歡專注地挑戰難度格鬥,你就不要對本作有太大的期待。就筆者而言,以5分為滿分,劇情4分,遊戲性3分(如果遊戲性只談格鬥操作及流暢度的話一定有5分,但因為節奏問題,整體感覺只能說中規中矩。)

手機也可以寫攻略

手機‧電玩
MacauYeah・2023-08-11

上期為大家簡介過筆者使用Github + mdBook制作遊戲攻略。未看過上期介紹的朋友,可以在這個連結(https://lifemag.cyberctm.com/zh_TW/blog/macauyeah/13777) 找到上期內容。今期就繼續為大家介紹一些工具讓手機也能協作。 筆者在開始前,先簡單總結為何會選擇Github + mdBook。 Github是協作工具,追查因為歷史修改記錄會比其他工具更成熟 mdBook以純文字方式操作,適合上傳至Github。 mdBook有自動轉網頁方式,Github有寄存簡單網頁功能。 現在剩下的就是如何做編輯。 電腦端 傳統上,如果要用網誌或Google Doc作為編輯媒介,若你有電腦的話,只要使用現代瀏覽器就可以使用,基本上都會有提供自動儲存草稿的功能。即使你在別台電腦中也可以繼續進度。Google Doc等也有提供離線模式,有時候真的網路不通,可以先修改線下版本再上傳回去雲端。網誌就未必有這些功能。 同樣地,Github也有提供瀏覽器直接修改的模式,不過想要離線操作,就需要使用Github客戶端(或其他Git客戶端)。重要的是,mdBook的原始文件其實只是純文字,可以用最簡單的記事簿程式就可以繼續創作。只是最後要經Github轉化為網頁發佈。 說到尾,有電腦在手,其實什麼方案也不算困難。有網路一切事情都可以解決到。 手機端 但在手機上,因為操作空間的限制,一切都變得很艱難。如果對技術不熟悉的朋友,可能用Google Doc已經是最好的方案。 Google Doc手機版已提供相對友善的排版編輯功能,但它真的不能取代電腦版。很多重要的縮排或插圖功能,還是開電腦使用吧。網誌就更不用考慮了,一般它們的編輯功能都不適合在手機上使用。 而Github的手機版,對於編輯純文字還是相對可以用的。而且mdBook對於一般文章排版也是夠用的。但是這個方案沒有暫存功能,對於長一點的文稿,需要離線慢慢創作就不太可能。 幾經辛苦,筆者終於找到一個Git的手機版,可以輕鬆地離線編輯。那就是PolyGit,它的免費版本雖然一天只能上傳Server 3次,但因為可以離線編輯,即使沒有付費,頂多隔天才一口氣上傳。更重要的是它的文字編輯器,可以看懂部份mdBook markdown格式。你在一邊創作時,就會看到基本的Highligh提示。(不過最可惜的是,PolyGit只有iOS版本,Android版筆者未有找到很好的Github替代品。) 這樣,你就可以隨時隨地,任何地方,都可以繼續創作了。以筆者的角度來講,扣除工作環境外,平時會碰電腦的機會真的少之又少。想好好找個時間、找一台電腦來創作,基本上很少可以實現。但手機就不一樣,午飯在餐廳休息時、晚上睡前坐在床邊,什至乎是大解的時候,拿著手機打打打,也是一個不錯的選擇。 PolyGit 官方連結 https://www.polygitapp.com/

用Github寫攻略其實也不難

手機‧電玩
MacauYeah・2023-08-04

上個月筆者為大家介紹過一位內地的文字攻略制作者Pser_hanser。本月筆者就身體力行,計劃制作一些FF8的協作攻略筆記,亦因此對於協作工具仔細地考量過一翻。 首先協作的基本要素,就是各人可以共同維護。所以國外或內地素人作者,都會以Google Doc或騰訊文檔為主。傳統的網誌就不太適合。而另一方面,就是因為遊戲攻略要考慮附圖的因素,Google Doc或騰訊文檔對於上傳圖片都算很友好。所以對於不熟網頁技術的作者來說就最適合。 不過對於筆者來講,有一個更大的考量點就是歷史記錄和版本差異。因為一份攻略的出現到完善,都會有不同程度的更新。更不用說因為遊戲Bug Fix,導致某些策略上的變更。左思右想,筆者選擇Github + mdBook,一邊可以做多人協作的版本控制,另一方便亦可以自由發佈網頁。 Github的唯一問題可能就是檔案大小問題,若圖檔太多太大,就不適合。不過好在偉大的twitter,現在可以作為第三方存取圖片,筆者的遊戲截圖就可以更方便地上傳及使用。如果大家只是想做輕攻略,就不需要專門為Switch和手機遊戲接上HDMI截取器,可以省下一大筆費用(因為對接Twitter,所以Switch或手機遊戲的截圖的上傳就變得無難度)。 以下是筆者做FF8攻略的初稿,協作連結github (https://github.com/macauyeah/ff8CasualGuide) 截錄一些mdBook的範例 # Disk 01 part 1 - Draft ## Balamb Garden 經過一輪過場動畫後,老師就來接你了。場景轉到課室內,終於可以自由操作。 這時不需要跟傳統方式去開電腦取GF,向外走就好(Quistis會在校園外給你GF),跟老師交談幾句,得知補考的地點後就可以外出。 ![fire caven](https://pbs.twimg.com/media/F1NPIw9agAAQjJp?format=jpg&name=large) 走廊外碰到未來的隊友Selphie,不想煩的話,兩次對話選項都選第二個(speedrun)。 ![donot have time](https://pbs.twimg.com/media/F1NPIw9akAEcKH1?format=jpg&name=large) 從Selphie進來的方向離開,但記得一定打攪一下橋上的路人,他會給你7張卡 ![7 cards](https://pbs.twimg.com/media/F1NPIw_agAAJFWm?format=jpg&name=large) (你現在2樓)進電梯下1樓(暫時沒有選項,所以進電梯就會直達1樓) 在1樓大堂有個導覽板,調查後可以快速移轉。筆者選擇直接去Front Gate。 ![guide box](https://pbs.twimg.com/media/F1NQsHNaAAUriJL?format=jpg&name=large) ![teleport front gate](https://pbs.twimg.com/media/F1NQsHJaAAEaDk1?format=jpg&name=large) 註: 大部份Speedrun玩家都會先去Cafeteria,想早一步取得Quistis卡。筆者因為未弄懂那個必勝法則,所以先跑主線取得Ifrit卡後再回來挑戰。 出校門,Quistis說幾句,它就會給你GF ![Give GF](https://pbs.twimg.com/media/F1NQsHJacAIiI0S?format=jpg&name=large) 後述所有教學都請自行跳過,後期可在Menu > Tutorial慢慢查吧 ### 調整裝備 Junction - Quistis: GF Shiva - Magic, Draw, Item - Squall : GF Quezacotl - Magic, Draw, Item - ![Ability](https://pbs.twimg.com/media/F1NQsHKaYAE7Gj7?format=jpg&name=large) GF - Quezacotl: learn Card - ![card](https://pbs.twimg.com/media/F1NQx2UaEAEiq0g?format=jpg&name=large) - Shiva: learn I Mag RF - ![I mag rf](https://pbs.twimg.com/media/F1NQx5faUAA2EN1?format=jpg&name=large) Config - Cursor: Memory - Camera movement: 0% - Battle Message: max - Battle Speed: max - ![config](https://pbs.twimg.com/media/F1NQx2VaYAAmsUd?format=jpg&name=large) ## Fire Cavern 默認Boss以外隨機戰鬥都以逃跑為主,逃跑方式為長按L2 + R2。有需要完全戰鬥的會再特別說明。 出校園後,向東走,走向一個山洞。進行後Quistis會再有一輪教學。 走到門前,選10 mins進行考試。 ![twitter](https://pbs.twimg.com/media/F1SmNqVaEAAMa-E?format=jpg&name=large) 入洞後,右 > 上 > 上 > 上 > 上 > Boss戰。 在途中,遇敵Red Bats時,Draw指令抽取Thunder(第一項)。Squall, Quistis每人各抽7個以上Thunder魔法。 ![twitter](https://pbs.twimg.com/media/F1SmNqUagAENuOh?format=jpg&name=large) ### Boss Battle: Ifrit - Boss參考LV 6, 1068HP - Squall、Quistis: 對Squall放Thunder魔法,讓Squall先進入黃血狀態。 - ![twitter](https://pbs.twimg.com/media/F1SmNqUagAAj5wt?format=jpg&name=large) - 保守策略,Thunder每次大概扣100HP,Squall的血量大概為200時,就不再使用。被Boss慢慢攻擊就夠。Boss Fire魔法大概扣 60-65,所以即使很不幸,也有兩次援衝的機會。 - Squall 使用 Renzokuken: 筆者有Trigger增傷的情況下普攻平均傷害55,不用Renzokuken的話大概18-20個回合可以送走Boss。道理上使用Renzokuken後也是差不多,數次數就大概知道幾時結束。但因為有時Trigger失誤,筆者會同時使用Quistis攻擊(雖然這樣效率不是最高),所以實戰上比較難去數。 - Quistis: 有條件的話就自己攻擊自己,為後述的Fish Fin戰做準備。 頁面顯示效果 https://macauyeah.github.io/ff8CasualGuide/Disk01-01.html#balamb-garden 有興趣的朋友可以隨時checkout或commit 我的攻略 https://github.com/macauyeah/ff8CasualGuide

Docker打包 App還是打包底層程式作為Image ?

科技新知
MacauYeah・2023-07-28

雖然筆者對於Docker Swarm Mode的資歷尚淺,但由於後期更動的難點越來越多,筆者很想早一點討論其中不同操作的差異 Docker Swarm Docker Swarm Mode其實是Docker提供的一個Cluster(群集)環境。在其中運行的Image,都可以比較方便地隨時分身到不同的node(節點)上,對於提高負載或可用性,都是一個不錯的解決。 只要該Image跑起的Container是Stateless(前後兩次執行的結果互不相干涉),或者是把Stateful的部份(有干涉的部份)外包到第三方(例如儲存空間使用NFS,或記憶體暫存改為Key-Value Database),就可以方便地運作在Docker Swarm mode上。 部署Docker Swarm的選項 Docker Swarm可以把Image變成分身Container,但並不沒有硬性改變傳統App操作方式。大部份App在執行時,都需要另一個底層程式的支緩。例如 Php Web App,需要底層php fpm + nginx或apache Java Web App,就需要java + Tomcat 所以在發佈App時,可以選擇把 App直接打包成Image 只把底層程式打包在Image中(例如Tomcat),再在跑起Container時再動態接起App。 兩者有何差別? 就信心層面上,一定是把App直接打包成Image實際一點。因為這樣可以極大地減少測試環境和正式環境的差異而出現的問題。筆者一開始也不完全讚成,但也越來越傾向這種做法。 在解釋筆者為何有這個結論前,先條列式地對比一下兩種差別。 事項打包App成為Image打包底層程式成為Image 打包複雜度 需要把App用到的一些環境變數引入設定Image的entrypoint中,方便配合不同的環境可以改變App的行為。打包次數根據App數量有關。比較靈活,但比較需要學習和試錯。 底層程式統一設定環境變數,其中所有App都會使用類似或相同的設定,設定方式跟傳統方式無異。打包次數根據底層程式數量有關。比較死版,但要試錯的成本較低 發佈流程 打包App成Image。再靠Docker Swarm設定Image有多少分身,每個分身不需要特別再設定。 原來的底層程式已存在於Docker Swarm中,只需把新建或更新了的App放入不同分身的儲存空間,讓底層程式動態跑起App。 管理複雜度 每個App都是獨立的,代表有任何更新也是獨立更新。在微服務的協作環境中,需要管理員從Image層面為每個App設定網絡(network)或開放端口(Port)。但每個App可以設定不同的分身數量,靈活性一定比只打包底層程式要高。 使用同一個底層程式Image的App都會使用同一個網路和端口設定。在微服務的協作環境中,管理員要應付的設定數量一定比打包App要少。但由於是Conatiner分身是針對底層程式,所以若然某個App有不同需求,就要重新設定另一套底層程式。 上述幾個點,最後其實都是複雜度和靈活度的取捨。雖然打包App的工序更多,但提供的靈活性也更多。如果考慮要從傳統模式中過渡,方便與完成不懂Docker的同事協作,就首選打包底層程式。如果考慮可重複性和信心保證,還是打抱App比較直接,要複制一個環境到另一個環境,也比較易測試。

自己架設Docker的共享儲存空間

科技新知
MacauYeah・2023-07-21

Docker很好用,在單機環境下真的很好用。Docker原本的設計,是為了快速迭代而設計成Image的。在一般設定下,每次新建或重建container,都會根據Image重設一下各方面的環境,包括儲存空間。重設CPU,Memory,大家都很易理解,但重設儲存空間,真的不是每一個使用情況都可以這樣。 又或者說,未必所有使用情況都會有一個第三方的儲存空間可以用。所以良心的Docker在單機環境下也有提供bind mount或是docker named volume,作為可以長期保存,不受container生死的影響,以達到長期存在Data的存在。 單機-儲存空間 單機情況下很簡單,就用一個docker compose做例子 其中html就是一個bind mount,而nginxlogs就是一個docker named volume,兩者都可以長期保存data,除非各位自己手動刪除,否則不會因為container的興亡而不見了。 但有兩個很重要的分別 bind mount,直接跟host os連接,實際上是每次folder有更新,docker都要同步host和container之間的資料。 bind mount在linux下很暢順,因為大部份docker image/container原本就是linux engine,所以folder mount真的可以互通。 bind mount在windows / mac下,就會不斷抄資料。面對大量檔案,例如node_module,就會有速度上的問題 docker named volume,就是docker 分離一些獨立空間,然後再綁到container上 相對bind mount,即使在windows / mac下,都沒有那個速度上的問題。筆者猜測,即使是獨立空間,其實本身都已經限定在linux enginx下,所以沒有需要抄資料。 但在windows / mac下,因應docker 底層建立Linux VM的技術不同,你可能沒法在windows / mac預設環境下直接讀取docker named volume。 若要讀取docker named volume,最好的做法,還是連上docker container,然後用docker cp 來抄回資料。一但抄資料,其實都會有速度上問題,不過docker cp是手動決定何時做的,不做docker cp,其實container也是可以用。 Cluster-儲存空間 雖然良心的bind mount和named volume解決了單機上的儲存問題,但到了cluster環境,就沒有可以跨機同步儲存空間的做法,要做就自己建立。 筆者也稍為研究了一下同步的問題,不過對技術真的很有要求。所以退而求其次,筆者還是選擇簡單的第三方儲存空間。就是做一個可以分享存取的NAS。 建立nfs linux下要安裝nfs其實很簡單,不過要注意資料夾和防火牆權限,以下安裝教學以ubunut 22.04為例,記得把下面的YOUR_DOCKER_NODE_ADDRESS_RANGE轉為你的真實IP段落 修改docker compose 最後,你在原來的docker-compose的docker volume上加driver_opts就大功告成。 記得把下面的YOUR_NFS_IP轉為你的真實IP

Pser_hanser 用愛發電的文字遊戲攻略制作者

手機‧電玩
MacauYeah・2023-07-18

雖然筆者玩已少有再制作攻略,大部份都以分享心得為主。但筆者對攻略制作者都很支持,不論是公司媒體還是素人制作,在質量足夠的情況下,筆者購買紙本或是推廣他們的作品。 最近因為華文攻略的抄襲事件,反而讓多認識一位內地的攻略作者,Pser_hanser。他跟一般的Up主不一樣,他做的大部份攻略都是文字攻略。很明顯,文字攻略被抄走的難度一定低很多,但他也頂著壓力的情況下繼續用愛發電。 Pser_hanser的作品集 https://docs.qq.com/sheet/DR1NnTkRrc0NhUmxV 他的攻略,雖不能搶首發,但勝在持續更新,有些錯誤的地方,都會因為協作效應得到更正。 他也有一份堅持,就是做數據整理。一般網紅作者都會為了量產,只挑主線或特定迷題去影片攻略,省時,不需要全面驗正。但Pser_hanser就偏走最傳統路線,文字、流程、內容數據整理,目的就是方便他人查看,重複使閱讀。 拜搜尋引擎所托,現在很多影片都可以被特定的方式搜尋。不過對於可重複檢閱,還是文字更有意義。筆者過去因為Speedrun的原故,也查找了不少外國網站,只有同人才能編制得出一些「真·爽」的攻略。 瀏覽完Pser_hanser幾篇的作品,筆者亦都很受到鼓舞,雖不能靠寫攻略來養家活口,能對自己鍾愛的遊戲的支持,才是重要。筆者一直也認為,作為素人,也可以隨時創作,因為攻略的核心以協作為主,當有人起草了主脈落,其他人就可以一同持續修正。文字攻略所需要器材真的不多,只要能書寫,就可以描述很多抽象事情。現在各大主機平台,截圖也是很方便的,上傳圖像遠比錄影要容易。所以筆者開立了個Discord Server,有興趣參與華文攻略制作的朋友可以一起來聊聊。 https://discord.gg/5szV86tN 華文同人攻略連結

FF16 - 心得分享

手機‧電玩
MacauYeah・2023-07-14

絕對一讚的唯美 雖然FF16這代大大改變以往的遊戲方法,但作為老牌遊戲,它的角色建模、CG過程始終都保持領先地位。這些元素,大家可以在試玩版中體驗到。試玩版的序章一開始進入遊戲,就馬上可以看到第一場召喚獸大戰,畫面精彩、夠震撼、令人興奮。序章部份還有教學及實戰,控制主角打哥布林及BOSS。其中回避、攻擊模式做得不錯,雖然只是哥布林,但BOSS表現也很有壓場感,讚、很好。 探索部份有點失落 餘下的,就要聊聊機制的部份。雖然劇情很好,也有看大片的感覺,但畢竟是遊戲,要長期遊玩還是要好好考慮難度和探索設計的問題。 在一開始遊玩時,筆者還會不停探索地圖,檢道具,清野怪以及小BOSS。但越玩就越發現,這些都並不必要,什麼覺得有點多餘。 因為隨著遊戲進程,需要買裝備或升級裝備的時候,對材料的消耗量並不多,主線中原本就會得到足夠的材料以及金錢,解支線的剛性需求不大。而且初期很快就會得到兩件紫色防具,而這兩件防具足夠用到中後期。另一方面,武器跟隨主線就可以到武器店建造,不能強化。而後期,單單做武器商的支線以及打某幾隻危險怪就可以制造最高級防具以及武器,跟本用不著到處探索找材料。 支線部分,大部分支線都十分無聊,對劇情沒什麼關係,而且獎勵雞肋,所以並沒有特別的吸引力。除了增加道具使用數量以及裝備圖紙等,其他支線做與不做真是無分別。 所以即使地圖再大再多,筆者也無任何探索欲望。 而技能方面,遊戲合共可以選擇3個召喚獸技能以及6個分支技能。每個召喚獸分支技能升到最高級可以放在不同召喚獸上使用,而且可以隨時重置。這部分就可以自行選擇自已喜愛的技能,設計尚算宜人。 總結 總括來講,今集劇情畫面一流,對得起3A大作的稱號,但其他部分遊戲吸引力就很普通,難以讓玩家流年忘返。 劇情4分、遊戲性2分、畫面5分 對比FF7重制系列的可玩性,此作不推薦。但若然為傳統劇情老玩家,或完全未玩過系列作,想以入門試水溫但怕痛苦的,反而就值得一試。

死亡島2- 心得分享

手機‧電玩
MacauYeah・2023-07-07

系統篇 死亡之島2 玩法與第一代類似,遊戲多出技能卡牌選擇,相關選擇會影響角色主要攻擊及防禦手段,包括使用格檔還是使用閃避作防禦手段。而攻擊技能都有三種選擇,所有技能都有相應卡片強化效果。 角色相互的差異到中後期已經無太大差別,故無需煩惱使用哪個角色,因為對劇情結局都無影響。如有朋友一起遊玩,還可以分工合作,使得遊玩多樣化。 而喪屍種類就有十數種,包括屬性不同的喪屍,角色可以利用不同環境屬性攻擊,例如:可以先用水炸彈弄濕,再用電攻擊可加速中電擊屬性累積,所以活用屬性關係攻擊可以事半攻倍。 裝備系統強化則看稀有度以及級數,除橙色裝備無法掉落得到外,其他稀有度都可以從喪屍以及裝備箱得到。屬性強化則可以選擇火、雷、出血、切割、腐蝕等強化,而稀有度就影響強化數量,即越稀有,可強化數量越高。 而升級裝備所需要的金錢並不是小數,需要做取捨。但以筆者經驗來看,升級裝備並不是必要的,因為隨角色升級更換裝備效果會更佳,而且3級以內裝備差別不大,再上才有一定差別。 劇情篇 遊戲劇情可以說是今集敗筆之作,劇性相當荷里活,而角色毫無特點,直接可以用三無來形容:無感動、無高潮、令人無記憶點,總括來講不及第一代劇情好。 而遊戲性就可以說是中規中矩,如有朋友一起遊玩,則可以更好。 總結- 還是等等等吧 劇情評分2分滿分五分,遊戲性3分,建議打折再進行購買。