1 điểm bởi GN⁺ 2024-12-27 | 1 bình luận | Chia sẻ qua WhatsApp
  • CobolCraft là máy chủ Minecraft được triển khai bằng COBOL, hỗ trợ Minecraft 1.21.4, phiên bản mới nhất tại thời điểm viết
  • Dự án đã triển khai tạo địa hình vô hạn, tải chunk động, lưu dữ liệu thế giới và người chơi xuống đĩa, nhập thế giới có sẵn, multiplayer, hiển thị trạng thái máy chủ, phá/đặt block, inventory, crafting, nhặt item, chat, lệnh, v.v.
  • Các block có nhiều trạng thái, hướng và tương tác cần rất nhiều mã chuyên dụng để hoạt động đúng, và hiện vẫn còn nhiều block chưa được hỗ trợ
  • Được phát triển bằng GnuCOBOL trên Linux x86_64 hoặc arm64; cũng có thể triển khai bằng Docker, nhưng hỗ trợ các hệ điều hành khác như Windows chưa được kiểm thử
  • Trích xuất dữ liệu JSON từ datapack mặc định của Minecraft và các tệp .jar máy chủ/client chính thức để dùng cho việc sinh mã COBOL khi biên dịch và nạp dữ liệu lúc chạy

Các tính năng máy chủ Minecraft mà CobolCraft đã triển khai

  • CobolCraft là máy chủ Minecraft viết bằng COBOL và hỗ trợ Minecraft 1.21.4
  • Các tính năng đã triển khai bao gồm
    • Tạo địa hình vô hạn và tải chunk động
    • Lưu dữ liệu thế giới và người chơi xuống đĩa
    • Hỗ trợ định dạng tệp của Minecraft và nhập thế giới có sẵn
    • Multiplayer với số người chơi đồng thời có thể cấu hình
    • Ping/server status để hiển thị là online trong danh sách máy chủ
    • Phá và đặt block, mã loot table được sinh tự động
    • Tương tác với block dựa trên nhấp chuột phải
    • Inventory của người chơi
    • Crafting 2x2 và 3x3
    • Entity item và nhặt item
    • Chat
    • Lệnh trong game và lệnh console tương tác
    • Cấu hình dựa trên server.properties
    • Whitelist bền vững được lưu trong whitelist.json
    • Va chạm block/người chơi và vật lý entity ở mức rất cơ bản
    • Sát thương khi rơi, sát thương do void, chết, hồi sinh

Phạm vi và giới hạn hỗ trợ block

  • Các block có nhiều trạng thái, hướng và tương tác cần nhiều mã chuyên biệt để hoạt động đúng
  • Hiện vẫn còn nhiều block chưa được hỗ trợ
  • Các block hoạt động được bao gồm
    • torches
    • slabs
    • stairs
    • rotated pillars như logs
    • buttons không tương tác
    • doors
    • trapdoors
    • beds
    • signs

Môi trường build và chạy

  • CobolCraft được phát triển bằng GnuCOBOL và nhắm tới việc chạy trên Linux
    • Kiến trúc mục tiêu là x86_64 và arm64
    • Hỗ trợ các hệ điều hành khác như Windows chưa được kiểm thử
    • Dùng Docker có thể triển khai độc lập nền tảng
  • Các thành phần cần có để phân phối trên Linux như sau
    • GnuCOBOL 3.1.2 trở lên
    • Khuyến nghị GnuCOBOL 3.2 trở lên vì hiệu năng
    • make
    • gcc, g++
    • zlib
    • curl để tải xuống tệp .jar máy chủ chính thức
    • Java 21 trở lên để trích xuất dữ liệu từ tệp .jar máy chủ
  • Lệnh build và chạy như sau
make --jobs=$(nproc)
make run
  • Có thể dùng image trên Docker Hub hoặc tự build rồi chạy
docker pull meyfa/cobolcraft:latest

git clone https://github.com/meyfa/CobolCraft.git cobolcraft && cd cobolcraft
docker build --tag meyfa/cobolcraft .

Cấu hình máy chủ và truy cập mạng

  • Cấu hình máy chủ được thực hiện bằng cách chỉnh sửa tệp server.properties
  • Tệp này được tự động tạo ở lần chạy đầu tiên cùng với giá trị mặc định của tất cả tùy chọn được hỗ trợ
    • server-port: mặc định 25565
    • level-name: mặc định "world"
    • white-list: mặc định false
    • motd: mặc định "CobolCraft"
    • max-players: mặc định 10, tối đa 100
  • Theo mặc định, máy chủ chỉ có thể truy cập từ chính hệ thống qua localhost:25565
  • Để cho phép truy cập từ bên ngoài như mạng cục bộ, VPN, chuyển tiếp cổng, máy chủ thuê, có thể bind cổng thành 0.0.0.0:25565:25565 khi chạy Docker
docker run --rm -it -p 0.0.0.0:25565:25565 meyfa/cobolcraft

Vì sao tạo máy chủ Minecraft bằng COBOL

  • Trước đây nhà phát triển hoàn toàn chưa có kinh nghiệm với COBOL, nhưng muốn tìm hiểu thêm về ngôn ngữ này sau khi nghe các lời đồn và định kiến về COBOL
  • Họ chọn cách tự viết một thứ gì đó như phương pháp tốt nhất để học ngôn ngữ
  • Do độ phức tạp và quy mô của mã Minecraft, lựa chọn viết máy chủ Minecraft bằng COBOL được đánh giá là vừa là ý tưởng hay vừa là ý tưởng tệ
  • Những việc dễ làm trong các ngôn ngữ khác phải được xây dựng từ đầu
    • Phân tích cú pháp và mã hóa JSON
    • Xử lý nhiều loại dữ liệu nhị phân
    • Networking multiplayer thời gian thực
    • Chuyển hệ thống Minecraft mang tính hướng đối tượng sang một ngôn ngữ thủ tục
  • Đường cong học tập dốc đã khiến họ điều tra và hiểu sâu về COBOL cùng các khái niệm của nó, và họ cho biết quá trình đó rất đáng giá
  • Với người mới dùng COBOL, họ khuyến nghị GnuCOBOL Programmer's Guide
  • Có thể tham khảo wiki.vg documentation để học về giao thức Minecraft
  • Trong một số trường hợp, dùng công cụ như Wireguard để xem lưu lượng máy chủ thực tế cũng có thể giúp hiểu luồng thông tin

Cấu trúc nguồn và binary thực thi

  • Mã nguồn COBOL chủ yếu nằm trong thư mục src/
    • src/main.cob là entry point
    • src/server.cob chứa mã khởi động máy chủ và logic game
  • Thư mục codegen/ chứa bộ sinh mã viết bằng COBOL
    • Sinh thêm mã nguồn từ dữ liệu JSON như datapack mặc định của Minecraft
  • Thư mục cpp/ chứa mã nguồn C++ cho các phần tích hợp hệ điều hành khó xử lý bằng COBOL
    • Quản lý socket TCP cấp thấp
    • Đo thời gian chính xác
    • Xử lý signal của tiến trình
  • Tất cả mã nguồn COBOL và C++ được biên dịch thành một binary cobolcraft

Trích xuất dữ liệu Minecraft và xử lý JSON

  • Ứng dụng máy chủ và client chính thức của Minecraft Java Edition chứa rất nhiều dữ liệu
    • Block, item, loại entity
    • biomes
    • ID protocol của packet
    • tags như các block có thể đào bằng pickaxe
    • recipes
    • loot tables cho biết item nào rơi ra trong điều kiện nào khi phá block
  • Makefile của CobolCraft có target để tải xuống tệp .jar chính thức và trích xuất dữ liệu thành JSON
  • Dữ liệu JSON đã trích xuất được dùng theo hai cách
    • Tự động sinh mã COBOL như loot table của block khi biên dịch
    • Nạp dữ liệu vào bộ nhớ lúc runtime
  • Cả hai công việc đều dùng trình phân tích cú pháp JSON đa dụng viết bằng COBOL và đã hoàn tất unit test

Kiểm thử và cập nhật

  • Unit test nằm trong thư mục tests/
  • Các bài test dùng framework kiểm thử tùy chỉnh dựa trên copybook
    • Theo dõi test suite, unit, assertion
    • Cung cấp bản tóm tắt khi chạy xong
  • Lệnh chạy test là make test
  • Mục tiêu chính của test là kiểm chứng những khu vực khó debug như mã hóa và giải mã JSON/dữ liệu nhị phân
  • Logic game tự thân được xem là không quan trọng bằng để kiểm thử
  • Quy trình cập nhật máy chủ lên phiên bản Minecraft mới và các bước kiểm thử nằm trong Updating.md

Giấy phép và nhãn hiệu

  • CobolCraft được phân phối theo MIT License
  • “Minecraft” là nhãn hiệu của Mojang Synergies AB
  • CobolCraft không liên kết với Mojang và cũng không phải dự án được Mojang chứng thực

1 bình luận

 
GN⁺ 2024-12-27
Ý kiến trên Hacker News
  • Có rất nhiều lời đồn và định kiến xoay quanh COBOL, nên sẽ rất hay nếu bạn viết về những điều mình thật sự rút ra được
    Tôi cũng chỉ nghe những câu chuyện kiểu đó, và khá tò mò một người mới học COBOL sẽ gặp phải điều gì khi triển khai một dự án đầu tay khá phức tạp

    • Một định kiến mang tính đùa cợt về biến thể hướng đối tượng của COBOL là nó có dạng khó dùng với cái tên ADD ONE TO COBOL YIELDING COBOL
      Dù vậy, ít ra nó không như FORTRAN ngày xưa, nơi khoảng trắng bị bỏ qua nên DO 10 I=1.10 sẽ âm thầm được biên dịch thành câu lệnh gán DO10I = 1.10 thay vì báo lỗi cú pháp vòng lặp. Mã mà người ta định viết hẳn là DO 10 I=1,10
    • Những góc nhìn như vậy rất hay
      Nếu quan tâm, đây là những gì tôi rút ra khi làm một trình biên dịch từ COBOL sang C#: https://github.com/otterkit/otterkit-cobol/issues/40
      Giờ tôi đã tin chắc rằng COBOL chỉ là assembly cấp cao
  • Thật sự rất ngầu
    Tôi từng làm cả một hệ thống COBOL để tự động hóa tỷ lệ cược bóng đá cho đồ án tốt nghiệp trung học. Lúc đó công nghệ này đã lỗi thời rồi, nhưng trường tôi thì vẫn chưa theo kịp thời đại
    Nó vô lý đến mức buồn cười, nhưng tôi thích từng dòng một. Có gì đó rất thỏa mãn ở một ngôn ngữ mà mỗi lần gõ phím lại như đang thì thầm “còn nhớ thẻ đục lỗ không?”

    • Việc bạn dùng COBOL VIẾT HOA trong một dự án cấp ba thật sự rất đúng chất thời đại. Chắc hẳn đó là một kỷ niệm trung học tuyệt vời. Mong là bạn đã đặt toàn bộ tên biến theo tên các vị thần Hy Lạp
  • Có thể tôi nhầm, nhưng tôi có cảm giác mình khá thường xuyên thấy những dự án phụ nhỏ mà ấn tượng được viết bằng các ngôn ngữ đơn giản, bình thường như C hay COBOL ở đây
    Trong khi đó, các dự án Rust tương tự thì thường dài gấp 10 lần số dòng code mà vẫn gần như chẳng chạy được gì
    Giả thuyết của tôi là ngôn ngữ đơn giản giúp phác nhanh ý tưởng như bản vẽ và dễ làm cho cả một codebase lộn xộn vẫn chạy được. Còn các ngôn ngữ hiện đại thì ép bạn viết thứ code bền hơn về lâu dài. Hoặc cũng có thể là các ngôn ngữ hiện đại đang làm gì đó sai sai

    • Nói chính xác thì máy chủ Minecraft không phải là một dự án phụ nhỏ
      Có những máy chủ đã được phát triển 3-5 năm mà vẫn chưa hoàn thiện, và cũng có những cái tập trung vào một tính năng cụ thể để trình diễn redstone, như https://github.com/MCHPR/MCHPRS
      Máy chủ COBOL này vẫn chưa triển khai xử lý ánh sáng, và việc sinh mob phụ thuộc vào đó, nên đây là một trong những phần khó nhất. Một số block cũng chưa được triển khai đầy đủ. Để hoàn thành một máy chủ Minecraft cần nhiều năm, nên việc làm ra thứ gì đó thật nhanh không phải lúc nào cũng là con đường tốt
    • Tôi không nghĩ đó hẳn là ảo giác
      Tôi có 2 game đang làm bằng Rust, và nếu chọn đúng engine thì việc tạo một bản prototype gameplay tối thiểu thực ra khá dễ. Nhưng càng thêm tính năng thì code càng phình to, và quá trình chuyển từ chơi đơn sang nhiều người chơi thì hỗn loạn. Tôi cũng từng lãng phí thời gian chạy theo mốt rồi lại gỡ bỏ nó
      Rust thật sự rất ghét các cấu trúc đồ thị nơi các đối tượng game liên kết phức tạp với nhau. Mỗi khi một sự kiện trong game dẫn đến việc cập nhật nhiều kiểu dữ liệu khác nhau là lại có ma sát. Tôi có thể đơn giản chấp nhận điều đó và viết thêm chút code, hoặc tìm một lời giải có hệ thống, viết nhiều code hơn lúc đầu để tiết kiệm thời gian về sau
      Tôi đã chọn cách thứ hai và thử nghiệm vài thứ, nhưng điểm hòa vốn có vẻ quá xa đối với các dự án nhỏ chỉ có 1 người
      Ngay trong cùng một ngôn ngữ, khác biệt cũng có thể hơn cả một bậc độ lớn. Rust có 2 engine 3D dùng được: một cái rất nổi tiếng, có nhiều người đóng góp và được tài trợ đủ để thay thế mức lương Bay Area; cái còn lại gần như do một người làm, lúc thì sống bằng tiền tiết kiệm, lúc thì làm toàn thời gian
      Nhưng engine thứ nhất lại tập trung nhiều vào quảng bá và hứa hẹn đủ tính năng trong nhiều năm mà chẳng cho thấy được bao nhiêu, còn cái thứ hai thì vượt trội hơn cả về số lượng tính năng lẫn chất lượng triển khai
      Cuối cùng tôi nghĩ đó là khác biệt về thái độ. Có người code vì vui, có người tập trung vào một mục tiêu rõ ràng và hoàn thành nó, có người làm vì tiền, có người bị thu hút bởi sự công nhận rộng rãi. Codebase bừa bộn không nhất thiết là điều phải có, nhưng có một vùng trung gian vẫn rất hiệu quả. Càng tập trung vào việc phô diễn thì càng dễ chạy theo mốt và những kiến trúc hào nhoáng
    • Rust đã khá chật vật trong việc tìm ra đột phá ở mảng phát triển game
      Tiền đề cốt lõi của Rust là đánh đổi tốc độ phát triển và tính linh hoạt để lấy an toàn bộ nhớ, nhưng trong phát triển game thì tốc độ phát triển và tính linh hoạt lại quan trọng hơn an toàn bộ nhớ rất nhiều
      Nếu bạn đang làm một microkernel có đặc tả hình thức được vạch ra sẵn tới từng chi tiết thì Rust có thể là lựa chọn tuyệt vời. Ngược lại, nếu bạn cần nhanh chóng ném bùn lên tường để xem kiểu gameplay nào là vui, thì Rust khiến quá trình đó khó hơn gần như mọi ngôn ngữ khác mà lợi ích lại không rõ ràng. Thành quả chỉ là một mẩu gameplay nhanh và bẩn mất nhiều thời gian hơn để làm, đổi lại thì an toàn bộ nhớ hơn đôi chút
      Tôi chắc chắn không phải người duy nhất sau khi thử phát triển game bằng Rust rồi quyết định rời bỏ nó cho mục đích đó. Ví dụ có bài “Leaving Rust gamedev after 3 years” [0], đây là một trong những bài về Rust được thảo luận và upvote nhiều nhất trên Hacker News cho tới nay
      Nhìn rộng hơn, rõ ràng Rust được thổi phồng hơn COBOL rất nhiều. Vì thế có khá nhiều lập trình viên dễ bị cuốn theo làn sóng cường điệu, thường là những người mới đầy nhiệt huyết, đã mạnh dạn chọn Rust cho các dự án mã nguồn mở hay sở thích cá nhân. Ngược lại, để viết một máy chủ Minecraft bằng COBOL thì cần nhiều sự lập dị và gan hơn một chút, điều này thường đi cùng với nhiều kinh nghiệm hơn
      [0] https://news.ycombinator.com/item?id=40172033
    • Cuối cùng thì có lẽ đây là khác biệt giữa những hacker đích thực™ yêu thích ngôn ngữ đơn giản và có thể tạo ra cả vũ trụ dù bạn đưa họ thứ gì, với những code monkey chỉ chạy theo mốt mới nhất
      Nói vậy thôi chứ tôi tự xếp mình vào nhóm thứ hai
    • Những người thật sự hoàn thành công việc thường không quá bận tâm đến chất lượng code
      Tôi từng rơi vào trạng thái cố viết code bền vững đến mức rốt cuộc chẳng hoàn thành được gì. Qua nhiều năm tôi đã tìm được sự cân bằng, học được rằng nếu cứ lặp đi lặp lại việc cải thiện một đống code tệ thì cuối cùng nó cũng thành thứ ổn, và từ đó tôi làm theo cách đó
  • https://raw.githubusercontent.com/meyfa/CobolCraft/main/src/...
    Với những người có nền tảng về ngôn ngữ thủ tục, thực ra nó không khó hiểu đến vậy, và hơi gợi nhớ đến những máy chủ game viết bằng VB mà tôi từng thấy khoảng 20 năm trước

  • Từ sau khi ngừng dùng COBOL vào năm 1978, tôi tuyệt đối không bao giờ nhận là mình biết ngôn ngữ này nữa
    Tôi làm dấu thánh và đi uống cà phê đậm, mong rằng mình sẽ không phải nhìn đoạn mã này :-)
    Dù vậy, việc làm được thứ này vẫn rất ấn tượng

  • Có thể đem ra trêu, nhưng mã này khá dễ đọc
    So với một số ngôn ngữ hiện đại, nơi bạn phải ngồi nhìn vài phút mới hiểu được chuyện gì đang diễn ra

    • Tôi từng làm ở một công ty FAANG và có thể tiếp cận các chuyên gia C++ hàng đầu thế giới. Một số người còn thuộc ủy ban tiêu chuẩn ngôn ngữ quốc tế
      Tôi đã hỏi trên danh sách nội bộ về việc một dòng mã cụ thể có gây rò rỉ bộ nhớ hay không; đó là đoạn mã chỉ dùng template STL và ép kiểu. Nhưng các chuyên gia không thể đi đến đồng thuận về việc tôi có làm đúng hay không. Có người nói sẽ bị rò rỉ, có người nói là không
      Câu chuyện có thật nho nhỏ này nói lên rất nhiều điều về C++. JavaScript cũng đầy những chuyện như vậy
    • Đó từng là điểm mạnh của COBOL
      Tôi bắt đầu lập trình vào năm 1976 và học COBOL cùng ICL PLAN, ban đầu dùng thẻ đục lỗ rồi đến lúc kết thúc đào tạo thì chuyển sang dùng terminal. Chương trình lúc đó 100% là chương trình xử lý theo lô
      Có một thiên hướng rất mạnh về tính dễ đọc để bất kỳ ai cũng có thể đọc và hiểu mã nguồn. Tuy nhiên, điều này bị bù trừ phần nào bởi việc phải đọc và hiểu core dump được tạo ra khi chương trình thất bại. Cùng lắm bạn chỉ lần được lỗi tới một dòng mã cụ thể, nên tôi hình thành thói quen chạy chương trình trong đầu
      Khi rời cơ quan nhà nước để chuyển sang lập trình thương mại, cho tới đầu thập niên 80 tôi vẫn làm với COBOL và các chương trình batch. Tôi làm hỗ trợ ca đêm trong 3 năm, và đó là lúc giá trị của COBOL bộc lộ. Chỉ cần cầm một bản liệt kê và core dump chưa từng thấy, tôi thường có thể sửa khá nhanh. Tất nhiên, điều này luôn đi kèm với điều kiện là đó chỉ là bản vá mang tính chiến thuật
    • Vì vậy tôi thích Ada và VHDL
      Chúng có thể hơi dài dòng, nhưng dễ đọc hơn nhiều so với các ngôn ngữ “hiện đại” hơn
    • COBOL được thiết kế để ngay cả người không phải lập trình viên cũng có thể viết và đọc
      Ít nhất thì trên lý thuyết là như vậy
    • MOVE FUNCTION MIN(BLOCK-ENTRY-MINIMUM-STATE-ID(LK-BLOCK), STATE-ID) TO BLOCK-ENTRY-MINIMUM-STATE-ID(LK-BLOCK)
  • Hồi học cấp ba ở một thành phố nhỏ tại Pakistan, tôi đã học qua COBOL một chút
    Nó không tệ, và tôi từng làm một dự án mô phỏng báo cáo tài chính. Nó có vài chỗ kỳ quặc, nhưng với phần lớn con người, tức là những người không phải lập trình viên, thì ngôn ngữ lập trình nào cũng khá kỳ quặc, nên tôi không thật sự hiểu sự kỳ thị gắn với COBOL
    Cùng thời gian đó tôi cũng học C, và cuối cùng thì ngôn ngữ đó ở lại với tôi :-)

  • Tôi luôn nghe nói lập trình viên Cobol nhận lương cao vì rất hiếm
    Không biết dự án này có khiến lời mời làm việc đổ về hay không

    • Thứ hiếm không phải là lập trình viên Cobol mà là người hiểu logic nghiệp vụ
      Cobol thường được dùng trong các hoạt động nghiệp vụ cực kỳ phức tạp
    • Như những người khác đã nói, thứ quan trọng hơn là hiểu độ phức tạp của logic nghiệp vụ sẵn có và hệ thống mainframe mà đoạn mã đó thường chạy trên
      Nếu không thì chỉ cần làm một trình biên dịch chéo là xong
    • Giá trị của những người đó nằm ở kiến thức về môi trường nghiệp vụ cùng các hệ thống cực kỳ phức tạp và phần lớn không được tài liệu hóa, hơn là ở kỹ năng lập trình
  • COBOL thực sự trông như một ngôn ngữ khá ngầu
    Mã nguồn cũng được tổ chức rất gọn gàng

  • Tôi thích việc nó có kiểm thử đơn vị