- 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
Ý 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
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.10sẽ âm thầm được biên dịch thành câu lệnh gánDO10I = 1.10thay 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,10Nế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?”
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
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 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
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
Nói vậy thôi chứ tôi tự xếp mình vào nhóm thứ hai
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 đã 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ô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
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
Í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
Cobol thường được dùng trong các hoạt động nghiệp vụ cực kỳ phức tạp
Nếu không thì chỉ cần làm một trình biên dịch chéo là xong
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ị