LV. 19
GP 275

【其他】原始碼拿去

樓主 碳烤鮭魚 eriku850918
GP213 BP-
更: 原始碼看不懂又有一顆好學的心? 6樓查收。

== 原文 ========
呃 我ba
公沙小兔#8880的作者

首先我想要直接幫大家解決迷思,我們直接切入重點。

如果你想要知道"正確的遊戲延遲"
隔壁棚說的沒錯,公沙小兔(以下簡稱沙兔)的遊戲延遲超級不准,千萬不要用。
謝謝各位 收看我的文章



想知道更多可以往下讀

設計理念
伺服器延遲的設計就是我從網頁版偷來的
至於我為什麼要偷呢? 因為我懶得開網頁
然後我很常使用discord 所以我寫成了機器人

好不准喔.gif
至於為什麼他會這麼不准呢?
阿就不是用你的電腦測的啊? 我discord寫個機器人難道還能吃你資源?
這裡我想要稍微帶大家瞭解一下 資源監視器,網頁版JS,以及DC機器人的差異

準確度
資源監視器
絕對是最準的,原因就是 這就是你的電腦與伺服器的延遲

網頁版JS
利用你的網頁瀏覽器跑JS程式碼去測量你以及伺服器的
所以真的要說,也蠻準的

機器人
利用機器人本身的伺服器去測量延遲
根本不是你的電腦去測的,100%不可能跟你的延遲一樣

速度與激情9
資源監視器
首先請你準備一個碼表,接下來用你最快的速度切換所有頻道並記錄下延遲
麻煩在留言區幫我寫下你的最快紀錄以及伺服器資料

網頁版JS
認真說,挺快的 大概幾秒鐘

機器人
比網頁版快一點點

實用性
資源監視器
XD

網頁版JS
非常實用 快速 準確

機器人
快速 不準確

結語
沙兔的作用不是在於提供超正確的延遲
而是可以方便的給想要知道哪個頻道比較不會卡的人做參考
延遲資料如果超過一分鐘才會重新刷新 確保沒有過度請求的問題
資料的出處是從機器人的伺服器對遊戲伺服器
一個discord的機器人不可能用你的電腦效能去測延遲 你是不是誤會了甚麼w

總結來說 沙兔的延遲資料是他自己的延遲資料 不是你的
你如果要去跟你自己的資料做核對當然不一樣
超級不准der 不要用

看完以上還想要邀請沙兔的 這邊

原始碼下收
import json
import multiprocessing
import pathlib
import socket
import time
from typing import List, Literal

import discord
from discord.ext import commands, tasks

class Server(commands.Cog):
    def __init__(self, bot):
        super().__init__()
        self.bot = bot
        self.data_path = fr"{pathlib.Path(__file__).parent.resolve()}/data.json"
        with open(self.data_path) as j:
            _data = json.load(j)
            self.ports = _data["ports"]
            self.update = _data["update"]
        if not self._data_backup.is_running():
            self._data_backup.start()

    @tasks.loop(hours=1)
    async def _data_backup(self):
        await self.bot.wait_until_ready()
        _data = {}
        _data["ports"] = self.ports
        _data["update"] = self.update

        with open(self.data_path, "w") as j:
            json.dump(_data, j)
        print(f"[{self.__cog_name__}] backup saved")

    def cog_unload(self):
        _data = {}
        _data["update"] = self.update
        _data["ports"] = self.ports

        with open(self.data_path, "w") as j:
            json.dump(_data, j)
        return super().cog_unload()

    def worker(self, server, channel, return_dict) -> None:
        """worker"""
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.settimeout(5)
        s_start = time.time()
        host = self.ports[server][channel].split(":")
        port = host[1]
        host = host[0]

        try:
            s.connect((host, int(port)))
            s.shutdown(socket.SHUT_RD)

        except socket.timeout as err:
            s_runtime = "timeout"
        except OSError as err:
            s_runtime = "os error"
        except Exception as err:
            s_runtime = "unknown_error"
            print(f"Unknown error {server} {channel}, {err}")
        else:
            s_runtime = (time.time() - s_start) * 1000
        return_dict[channel] = (
            f"{s_runtime:.2f}ms" if isinstance(s_runtime, float) else s_runtime
        )
        return

    async def refresh_server(self, server: str) -> None:
        """multiprocessing because people are annoying"""
        manager = multiprocessing.Manager()
        return_dict = manager.dict()
        start = time.time()
        jobs = []
        for channel in self.update[server]:
            if channel == "timestamp":
                continue
            p = multiprocessing.Process(
                target=self.worker, args=(server, channel, return_dict)
            )
            jobs.append(p)
            p.start()

        for proc in jobs:
            proc.join()

        for channel in self.update[server]:
            if channel == "timestamp":
                continue
            self.update[server][channel] = return_dict[channel]
        self.update[server]["timestamp"] = time.time()
        print(
            f"[{self.__cog_name__}] {server} refreshed. ({time.time()-start:.4f} seconds)"
        )

    def needs_update(self, server: str) -> bool:
        """check if server was updated within the last 30 seconds"""
        lastsync = self.update[server]["timestamp"]
        return (time.time() - lastsync) > 60

213
-
LV. 19
GP 275
3 樓 碳烤鮭魚 eriku850918
GP126 BP-
那我逐條回應好了...

1. 看不懂真的不關我的事情,想學可以問。這點我應該可以無視

2. 阿這也不關我的事情... 我是不是不應該逐條回應,我已經後悔了

3. 我下面提供 最大延遲,最小延遲 單純是為了方便。
    這個的確可以作為 哪一個頻道比較順暢的依據。
    至於玩家想法我無權干涉,我唯一能做到的只有提供我個人倫理道德上認為可靠的數據。

4. 假如玩家的ISP跟橘子不合,那就是玩家的網路問題。
    玩家申請的ISP的問題 aka 玩家的網路問題

然後到底怎麼樣才可以跳到結論說,用機器人查一下 "挖每個都在卡,一定是橘子"
因為他們玩其他遊戲的ping都很低,所以100ms一定很卡?
這個也超過我可以幫助的範圍了

甚麼海外? 哪邊證實?_?

最後
我的延遲不是用拒絕回傳喔 原始碼給你了 自己讀


126
-
LV. 35
GP 782
5 樓 諭諭 maluku1125
GP69 BP-

作者標示-非商業性

本授權條款允許使用者重製、散布、傳輸以及修改著作,但不得為商業目的之使用。使用時必須按照著作人指定的方式表彰其姓名。

BOT很早就在我這邊推廣我出來講幾句廢話OK拔

作者也說了不是100%準確,畢竟測試是從BOT運作的伺服器發送到楓之谷的伺服器,跟每個人一定不一樣,但伺服器上多數用過的人包含我自己用起來就是感覺正相關,用起來沒啥毛病。
lag 看的出來
斷線看得出來
跑的順也看得出來
再說橘子伺服器可能這秒lag下秒順,上秒順下秒斷線

硬要把相關咬著說是不準
如果R^2=1才叫準的話,那科學界大概沒有任何實驗能證明理論了。

ba大花自己時間寫bot無償給大家用,然後有正相關的東西硬要影射別人是用random會不會太過分?
69
-
LV. 19
GP 460
6 樓 碳烤鮭魚 eriku850918
GP119 BP-
這篇回覆主要基於學習用途
有些人的邏輯不是我能高攀的就不多做解釋
我主要想要寫一篇: 國小生也能看懂的教學

前提
雖然我前面說設計理念是我從網頁版偷來的
但是我抄的是概念跟結構,裡面的程式碼會截然不同
兩個出來的結果也會不一樣

雖然我很想要把編碼流程整個呈現出來給大家
但是其實這鬼東西是我半年前寫出來的
我根本不記得了 tehe

何謂伺服器延遲?
其實說真的這個議題我也不一定是正確的
因為會造成伺服器延遲的因素實在是太多了
簡單一點可以看成
依序: 你的電腦 -> 你的網路 -> 你的網路提供者 -> 遊戲伺服器
然後在遊戲伺服器有反應之後 原路走回來
想要看這個流程的人 可以用tracert觀看 有興趣自己google我這邊不多解釋

至於有人問: 為什麼用socket而不是使用ICMP呢?
答案其實很簡單: 我對socket(資工)比較熟悉 ICMP(網路)不是我的專長
所以說真的哪個比較準我也不知道 歡迎懂的人來補充

程式碼解析
接下來我會解釋一下 沙兔的核心程式
我會拿簡易版本來做解釋 很多其他的元件其實跟延遲沒有關係
主要是在解決discord以及使用者的使用體驗或是優化

def worker(host, port):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 創造一個 socket "端"
    s.settimeout(5)                                       
# 這個端的超時設定為5秒
    s_start = time.time()                                 
# 這裡是我們紀錄當前時間
    try:
        s.connect((host, int(port)))                      
# 連線至伺服器
        s.shutdown(socket.SHUT_RD)
    except Exception as err:
return "error"
# 任何的錯誤會落在這裡
    else:                                                 
        return (time.time() - s_start) * 1000
# 成功了
    
相信很多人看完上面的程式碼還是會覺得 幹,誰看的懂啊?
還記得一開始提到的 你的電腦 -> 你的網路 -> 你的網路提供者 -> 遊戲伺服器

我們創造一個"端"就是在假裝這是你的電腦
然後透過這個"端"去連線到遊戲伺服器
等到連線成功之後就會記錄時間
那個時間就會是這個伺服器的回應延遲了

那麼相信大家小學化學課都有學過
實驗最重要的就是對照
因為日常生活中的變數太多了
所以在同樣的環境下取得的實驗結果才是最有參考性的
試想:
如果你做一個用到日晷的實驗
然後一個在早上做 一個在晚上做
實驗結果會不一樣也是可想而知

遊戲延遲這種東西也是
不要拿A遊戲比B遊戲
不要拿A數據比B數據
更不要拿兩個用完全不同流程做出來的實驗結果去做比對

之所以會附上最大最小也是因為這樣
在同一筆資料的範圍內去做比較
而不是楓之谷的ping vs 踩地雷的ping
這種比較根本沒有意義

然後如果有人想要自己試試看的
普力特 5頻 host: 202.80.104.79port: 8585
這兩個數值記得要用string去帶入喔

後言
json 我就先不附上 因為有點大
如果真的有人想要可以來我DC群問我
想要問我關於我的機器人的事情也可以來DC或是留言問我
想要討論python, discord-bot也可以來問我
想要知道楓之谷如何運作不要來問我
想要知道金字塔如何運作不要來問我
想要知道任何不再我掌控之中的東西也請不要找我負責
我還以為我簽了甚麼鬼維護合約 到底關我屁事

以上內容僅代表本人立場
希望大家都能夠更加了解我的機器人
共勉之
119
-
LV. 14
GP 145
10 樓 講實話打臉你的人 ms0560463
GP1 BP-
同是軟體工程師 已經習慣了 因為太多鍵盤工程師
1
-
LV. 31
GP 499
11 樓 Kuso12 kuso27153216
GP0 BP-
我自己用樓主提供的code測試,艾麗亞全頻道的延遲幾乎都在10~20ms附近,晚上熱門時段也只有到20~30ms(話說為什麼跟機器人的結果差這麼多

(太長了只擷取部分)

然而事實上晚上大部分頻道都可以感受到0.1~0.2秒的延遲,更別說小遊戲甚至可以延遲數秒了(1秒=1000ms)

看到這結果我想了想,楓谷會讓人感覺延遲的問題應該根本不是出在網路連線上,而是伺服器執行運算或指令的效率太差,也就是常說的伺服器太爛。

會這麼想還有一個原因。
其實艾麗亞有固定幾個頻道長期以來無論冷熱門時段都是比較不會延遲的(我自己發現以後請朋友換到這幾頻,也有明顯感受到變順暢,而且頻道人數並沒有比較少),
然而無論是資源監視器、網頁、機器人或我自己跑樓主code,測出來的延遲數值都和其他頻道差不多,沒有拉開差距
因此我推測這幾個頻道背後的伺服器硬體,在執行運算的效率上應該是明顯優於其他頻道,所以才比較不會延遲

如果說延遲的原因是出在伺服器硬體計算速度(伺服器爛)的話,是不是根本就沒有辦法透過非官方的方式測試出延遲?甚至連比較頻道之間的延遲差距都沒辦法做到,只能參考頻道有沒有斷線而已
0
-
未登入的勇者,要加入 14 樓的討論嗎?
板務人員: