Điều khiến một MMORPG khác với game một người chơi là máy chủ đứng sau mọi thứ bạn nhìn thấy. Trong phần đầu tiên của nhật ký phát triển (devlog) Ancient Online: Remastered này, chúng tôi giải thích cách mình đang xây dựng một MMORPG với Unreal Engine 5.8: công việc được chia giữa client và máy chủ ra sao, thế giới được mô phỏng thế nào, và làm sao chúng tôi có thể chỉnh sửa trực tiếp một thế giới duy nhất, liền mạch.
Hai phần: client và máy chủ
Ancient Online gồm hai phần mềm riêng biệt:
- Client được viết bằng C++ trên Unreal Engine 5.8. Kết xuất hình ảnh, âm thanh, giao diện và nhập liệu là việc của nó.
- Máy chủ độc lập với Unreal: chúng tôi viết nó từ đầu bằng C++23. Toàn bộ luật chơi của game chạy ở đây.
Vì sao chúng tôi viết máy chủ riêng thay vì viết bên trong engine? Vì những gì một máy chủ MMORPG cần khác với những gì một game engine cần: không có đồ họa, nhưng có hàng nghìn thực thể, dữ liệu lưu trữ lâu dài, thời gian hoạt động liên tục kéo dài và nhu cầu về hiệu năng có thể dự đoán. Một máy chủ riêng cho phép chúng tôi chỉ làm phần việc cần thiết và kiểm soát từng byte.
Máy chủ toàn quyền: không tin client
Nguyên tắc nền tảng của chúng tôi là: client đưa ra yêu cầu, máy chủ đưa ra quyết định.
- Di chuyển: Thao tác của người chơi được gửi tới máy chủ, và máy chủ tính toán vị trí. Client hiển thị vị trí mà máy chủ báo về bằng phép nội suy mượt mà. Vì thế, một client “tự dịch chuyển tức thời” hay đi xuyên tường thì chẳng đi đến đâu cả đối với máy chủ.
- Chiến đấu: Những kết quả như sát thương, đòn trúng và đẩy lùi được tính trên máy chủ. Chẳng hạn, máy chủ quyết định một đòn combo có quật ngã đối thủ hay không rồi phát kết quả cho mọi người cùng một lúc.
- Kinh tế: Vật phẩm, tiền tệ và giao dịch cửa hàng chỉ thay đổi trên máy chủ và trong cơ sở dữ liệu.
Cái giá của cách tiếp cận này là phải xử lý tốt độ trễ mạng; phần thưởng là một thế giới nơi gian lận khó hơn nhiều và cùng một luật áp dụng cho tất cả.
Vòng lặp thế giới 25 Hz
Máy chủ cập nhật thế giới 25 lần mỗi giây. Ở mỗi bước, AI của quái vật, di chuyển, chiến đấu, hiệu ứng kỹ năng và thời tiết đều tiến thêm một nhịp. Bước cố định giữ cho việc mô phỏng có thể dự đoán và bảo đảm cùng một đầu vào luôn cho ra cùng một kết quả.
Không phải người chơi nào cũng cần biết về mọi thứ. Máy chủ chia thế giới thành một lưới và chỉ gửi cho mỗi người chơi các cập nhật về những thực thể nằm trong vùng quan tâm của họ (những thực thể ở gần). Điều này giữ lưu lượng mạng ở mức hợp lý ngay cả trong một thành phố đông đúc.
Một giao thức nhị phân gọn nhẹ
Giữa client và máy chủ không có JSON hay REST; mỗi thông điệp là một gói tin nhị phân có bố cục cố định. Điều đó tiết kiệm cả băng thông lẫn thời gian CPU. Khi thêm một hệ thống mới (như thời tiết, di chuyển hay dịch vụ tài khoản trong game), chúng tôi viết cho nó một hợp đồng gói tin riêng, có đánh số phiên bản, và dùng các tệp header dùng chung để bảo đảm client và máy chủ làm việc theo cùng một hợp đồng.
Lưu trữ: lưu mà không bắt game phải chờ
Dữ liệu người chơi nằm trong cơ sở dữ liệu PostgreSQL. Nhưng để vòng lặp thế giới phải chờ cơ sở dữ liệu ở mỗi bước là điều không thể chấp nhận. Vì vậy việc lưu được thực hiện ở chế độ nền, theo kiểu ghi sau (write-behind): máy chủ thế giới đẩy các thay đổi vào một hàng đợi (Redis), và một tiến trình ghi chạy nền ghi chúng vào cơ sở dữ liệu theo lô. Nhịp độ của game không phụ thuộc vào tốc độ của cơ sở dữ liệu.
Các kênh và máy chủ đăng nhập
Người chơi trước hết kết nối tới một máy chủ đăng nhập, nơi xử lý việc xác minh tài khoản, chọn nhân vật và phiên đăng nhập. Sau đó họ chuyển sang một trong bốn kênh game (CH1–CH4). Trạng thái trực tiếp của các kênh được hiển thị trên trang trạng thái máy chủ của trang web game.
Một thế giới liền mạch, chỉnh sửa trực tiếp
Thế giới của Ancient Online được thiết kế như một thế giới duy nhất, liền mạch thay vì những bản đồ riêng lẻ ngăn cách bởi màn hình tải; nó được chia thành các ô và được tải theo kiểu streaming.
Nội dung của thế giới (địa hình, vật thể, vị trí đặt quái vật) không nằm trong mã nguồn mà nằm trong cơ sở dữ liệu, có quản lý phiên bản. Chúng tôi có thể chỉnh sửa thế giới này bằng một trình biên tập thế giới ngay trong game: các thay đổi trước hết được thực hiện trong bản nháp, được kiểm tra, rồi mới được xuất bản. Mỗi lần xuất bản tạo ra một phiên bản mới, và client xác minh rằng dữ liệu thế giới nó đang giữ khớp với của máy chủ bằng cách so sánh một mã tóm lược (digest). Nếu không khớp, nó chờ dữ liệu được cập nhật rồi mới tiếp tục vào game.
Nhiệm vụ: Lua làm ngôn ngữ kịch bản
Nhiệm vụ và lời thoại NPC được viết bằng Lua 5.4 trên máy chủ. Nhờ đó chúng tôi phát triển và kiểm thử nhiệm vụ mà không phải biên dịch lại máy chủ.
Tin nhắn của người chơi không bao giờ rời khỏi máy chủ của chúng tôi
Chúng tôi không dùng dịch vụ dịch thuật bên ngoài cho việc dịch trò chuyện trong game. Chúng tôi chạy một mô hình dịch cục bộ, chỉ dùng CPU, trên chính máy chủ của mình; tin nhắn của người chơi không được gửi tới bất kỳ API bên ngoài nào. Nhờ vậy, những người chơi nói các ngôn ngữ khác nhau có thể hiểu nhau mà tin nhắn của họ không bao giờ rời khỏi studio.
Tiếp theo là gì
Phần hai của nhật ký phát triển nói về những quyết định chúng tôi đưa ra để cùng một thế giới chơi được bằng chuột, màn hình cảm ứng và tay cầm. Để làm quen với studio, hãy đọc bài Astronaut Entertainment là ai?; về chính game, hãy xem trang Game.


