From c7da79121be41f3da744d87bd35276701e55f89c Mon Sep 17 00:00:00 2001 From: Fabian Meyer <3982806+meyfa@users.noreply.github.com> Date: Thu, 27 Jun 2024 22:52:01 +0200 Subject: [PATCH] feat: Extract proper registry data from vanilla datapack Finally, the entire world is a plains biome! Jokes aside, what this patch does is as follows: It expands the amount of data extracted from the official server to include the vanilla datapack registries, and adds code to parse them at run-time from the file system. This means the application now has a much better understanding of the knowledge shared by both the server and client. For instance, when upgrading to a new version of Minecraft, I would previously have to capture the flow of Registry Data packets from a real server, which CobolCraft would then re-play as a blob. Any data within that packet, such as biome IDs or chat message types, would need to be hard-coded where they were needed, since the server-side aspects of the data would simply be missing. Now, with the "--server" flag added in the Makefile, JSON files are exported for every vanilla registry entry. Using newly-implemented C++ routines to obtain directory listings (why is this not part of GnuCOBOL?), the registries can be filled in at run-time. The Registry Data packet now sends the actual data instead of an opaque blob. As a proof-of-concept, the new methods are used to lookup the "minecraft:plains" biome at chunk allocation such that we get a much nicer tint of the environment (compared to "minecraft:badlands", which happened to be the default ID 0 when using the blob). --- Dockerfile | 1 + Makefile | 14 +- blobs/registry_packets.txt | 219 -------------------------------- cpp/cobolcraft_util.cpp | 61 +++++++++ cpp/cobolcraft_util.h | 18 +++ src/copybooks/DD-REGISTRIES.cpy | 1 + src/copybooks/DD-WORLD.cpy | 4 + src/datapack.cob | 104 +++++++++++++++ src/packets/chunkdata.cob | 7 +- src/packets/registry.cob | 81 ++++++------ src/registries.cob | 118 +++++++++++++++++ src/server.cob | 58 ++++++++- src/world.cob | 15 ++- 13 files changed, 430 insertions(+), 271 deletions(-) delete mode 100644 blobs/registry_packets.txt create mode 100644 src/datapack.cob diff --git a/Dockerfile b/Dockerfile index 777e335..78c3d68 100644 --- a/Dockerfile +++ b/Dockerfile @@ -35,6 +35,7 @@ COPY --from=build cobolcraft . COPY --from=build *.so . COPY --from=build blobs ./blobs COPY --from=build data/generated/reports/*.json ./data/generated/reports/ +COPY --from=build data/generated/data ./data/generated/data # Include runtime dependencies ENV COB_PRE_LOAD=CBL_GC_SOCKET:COBOLCRAFT_UTIL diff --git a/Makefile b/Makefile index 2bb9ef9..16622b3 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,8 @@ CPY = $(wildcard src/copybooks/*.cpy) BIN = cobolcraft # Data extraction from Mojang's server.jar -JSON_DATA = data/generated/reports/registries.json data/generated/reports/blocks.json +SERVER_URL = https://piston-data.mojang.com/v1/objects/450698d1863ab5180c25d7c804ef0fe6369dd1ba/server.jar +SERVER_JAR_EXTRACTED = data/versions/1.21/server-1.21.jar # Test sources and binary TEST_SRC = test.cob $(wildcard tests/*.cob) @@ -23,7 +24,7 @@ TEST_BIN = test .PHONY: all clean data run test -all: $(BIN) $(SOCKET_LIB) $(UTIL_LIB) $(JSON_DATA) +all: $(BIN) $(SOCKET_LIB) $(UTIL_LIB) data clean: rm -rf $(OBJECTS_DIR) @@ -32,8 +33,9 @@ clean: rm -f $(UTIL_LIB) rm -f $(TEST_BIN) rm -f $(JSON_DATA) + rm -rf data -data: $(JSON_DATA) +data: $(SERVER_JAR_EXTRACTED) run: all COB_PRE_LOAD=CBL_GC_SOCKET:COBOLCRAFT_UTIL ./$(BIN) @@ -45,10 +47,10 @@ $(SOCKET_LIB): $(UTIL_LIB): cpp/cobolcraft_util.cpp g++ -shared -Wall -O2 -fPIC -lz -o $@ $< -$(JSON_DATA): +$(SERVER_JAR_EXTRACTED): mkdir -p data - curl -o data/server.jar https://piston-data.mojang.com/v1/objects/450698d1863ab5180c25d7c804ef0fe6369dd1ba/server.jar - cd data && java -DbundlerMainClass="net.minecraft.data.Main" -jar server.jar --reports + curl -o data/server.jar $(SERVER_URL) + cd data && java -DbundlerMainClass="net.minecraft.data.Main" -jar server.jar --reports --server $(OBJECTS): out/%.o: src/%.cob $(CPY) @mkdir -p $(@D) diff --git a/blobs/registry_packets.txt b/blobs/registry_packets.txt deleted file mode 100644 index 1b0b644..0000000 --- a/blobs/registry_packets.txt +++ /dev/null @@ -1,219 +0,0 @@ -9d0c07186d696e6563726166743a776f726c6467656e2f62696f6d6540126d69 -6e6563726166743a6261646c616e647300176d696e6563726166743a62616d62 -6f6f5f6a756e676c6500176d696e6563726166743a626173616c745f64656c74 -6173000f6d696e6563726166743a626561636800166d696e6563726166743a62 -697263685f666f7265737400166d696e6563726166743a6368657272795f6772 -6f766500146d696e6563726166743a636f6c645f6f6365616e00186d696e6563 -726166743a6372696d736f6e5f666f7265737400156d696e6563726166743a64 -61726b5f666f7265737400196d696e6563726166743a646565705f636f6c645f -6f6365616e00136d696e6563726166743a646565705f6461726b001b6d696e65 -63726166743a646565705f66726f7a656e5f6f6365616e001d6d696e65637261 -66743a646565705f6c756b657761726d5f6f6365616e00146d696e6563726166 -743a646565705f6f6365616e00106d696e6563726166743a6465736572740019 -6d696e6563726166743a6472697073746f6e655f636176657300156d696e6563 -726166743a656e645f62617272656e7300176d696e6563726166743a656e645f -686967686c616e647300166d696e6563726166743a656e645f6d69646c616e64 -7300196d696e6563726166743a65726f6465645f6261646c616e647300176d69 -6e6563726166743a666c6f7765725f666f7265737400106d696e656372616674 -3a666f7265737400166d696e6563726166743a66726f7a656e5f6f6365616e00 -166d696e6563726166743a66726f7a656e5f7065616b7300166d696e65637261 -66743a66726f7a656e5f7269766572000f6d696e6563726166743a67726f7665 -00146d696e6563726166743a6963655f7370696b657300166d696e6563726166 -743a6a61676765645f7065616b7300106d696e6563726166743a6a756e676c65 -00186d696e6563726166743a6c756b657761726d5f6f6365616e00146d696e65 -63726166743a6c7573685f636176657300186d696e6563726166743a6d616e67 -726f76655f7377616d7000106d696e6563726166743a6d6561646f7700196d69 -6e6563726166743a6d757368726f6f6d5f6669656c647300176d696e65637261 -66743a6e65746865725f776173746573000f6d696e6563726166743a6f636561 -6e00216d696e6563726166743a6f6c645f67726f7774685f62697263685f666f -72657374001f6d696e6563726166743a6f6c645f67726f7774685f70696e655f -746169676100216d696e6563726166743a6f6c645f67726f7774685f73707275 -63655f746169676100106d696e6563726166743a706c61696e73000f6d696e65 -63726166743a726976657200116d696e6563726166743a736176616e6e610019 -6d696e6563726166743a736176616e6e615f706c6174656175001b6d696e6563 -726166743a736d616c6c5f656e645f69736c616e647300156d696e6563726166 -743a736e6f77795f626561636800166d696e6563726166743a736e6f77795f70 -6c61696e7300166d696e6563726166743a736e6f77795f736c6f70657300156d -696e6563726166743a736e6f77795f7461696761001a6d696e6563726166743a -736f756c5f73616e645f76616c6c657900176d696e6563726166743a73706172 -73655f6a756e676c6500156d696e6563726166743a73746f6e795f7065616b73 -00156d696e6563726166743a73746f6e795f73686f7265001a6d696e65637261 -66743a73756e666c6f7765725f706c61696e73000f6d696e6563726166743a73 -77616d70000f6d696e6563726166743a746169676100116d696e656372616674 -3a7468655f656e6400126d696e6563726166743a7468655f766f696400146d69 -6e6563726166743a7761726d5f6f6365616e00176d696e6563726166743a7761 -727065645f666f72657374001a6d696e6563726166743a77696e647377657074 -5f666f7265737400226d696e6563726166743a77696e6473776570745f677261 -76656c6c795f68696c6c7300196d696e6563726166743a77696e647377657074 -5f68696c6c73001b6d696e6563726166743a77696e6473776570745f73617661 -6e6e6100196d696e6563726166743a776f6f6465645f6261646c616e647300e0 -0107136d696e6563726166743a636861745f74797065070e6d696e6563726166 -743a6368617400176d696e6563726166743a656d6f74655f636f6d6d616e6400 -1e6d696e6563726166743a6d73675f636f6d6d616e645f696e636f6d696e6700 -1e6d696e6563726166743a6d73675f636f6d6d616e645f6f7574676f696e6700 -156d696e6563726166743a7361795f636f6d6d616e6400236d696e6563726166 -743a7465616d5f6d73675f636f6d6d616e645f696e636f6d696e6700236d696e -6563726166743a7465616d5f6d73675f636f6d6d616e645f6f7574676f696e67 -00c70207166d696e6563726166743a7472696d5f7061747465726e120e6d696e -6563726166743a626f6c74000f6d696e6563726166743a636f617374000e6d69 -6e6563726166743a64756e65000d6d696e6563726166743a657965000e6d696e -6563726166743a666c6f77000e6d696e6563726166743a686f737400106d696e -6563726166743a726169736572000d6d696e6563726166743a72696200106d69 -6e6563726166743a73656e74727900106d696e6563726166743a736861706572 -00116d696e6563726166743a73696c656e6365000f6d696e6563726166743a73 -6e6f7574000f6d696e6563726166743a7370697265000e6d696e656372616674 -3a74696465000d6d696e6563726166743a766578000e6d696e6563726166743a -7761726400136d696e6563726166743a77617966696e646572000e6d696e6563 -726166743a77696c6400d20107176d696e6563726166743a7472696d5f6d6174 -657269616c0a126d696e6563726166743a616d65746879737400106d696e6563 -726166743a636f7070657200116d696e6563726166743a6469616d6f6e640011 -6d696e6563726166743a656d6572616c64000e6d696e6563726166743a676f6c -64000e6d696e6563726166743a69726f6e000f6d696e6563726166743a6c6170 -697300136d696e6563726166743a6e657468657269746500106d696e65637261 -66743a71756172747a00126d696e6563726166743a72656473746f6e6500b801 -07166d696e6563726166743a776f6c665f76617269616e74090f6d696e656372 -6166743a617368656e000f6d696e6563726166743a626c61636b00126d696e65 -63726166743a63686573746e7574000e6d696e6563726166743a70616c65000f -6d696e6563726166743a7275737479000f6d696e6563726166743a736e6f7779 -00116d696e6563726166743a73706f7474656400116d696e6563726166743a73 -747269706564000f6d696e6563726166743a776f6f647300c207071a6d696e65 -63726166743a7061696e74696e675f76617269616e74320f6d696e6563726166 -743a616c62616e000f6d696e6563726166743a617a74656300106d696e656372 -6166743a617a7465633200126d696e6563726166743a6261636b796172640011 -6d696e6563726166743a6261726f717565000e6d696e6563726166743a626f6d -6200116d696e6563726166743a626f757175657400176d696e6563726166743a -6275726e696e675f736b756c6c000e6d696e6563726166743a6275737400126d -696e6563726166743a636176656269726400126d696e6563726166743a636861 -6e67696e67000f6d696e6563726166743a636f74616e00116d696e6563726166 -743a636f757262657400116d696e6563726166743a6372656562657400156d69 -6e6563726166743a646f6e6b65795f6b6f6e67000f6d696e6563726166743a65 -6172746800116d696e6563726166743a656e64626f7373000e6d696e65637261 -66743a6665726e00126d696e6563726166743a666967687465727300116d696e -6563726166743a66696e64696e67000e6d696e6563726166743a666972650010 -6d696e6563726166743a67726168616d00106d696e6563726166743a68756d62 -6c65000f6d696e6563726166743a6b6562616200116d696e6563726166743a6c -6f776d697374000f6d696e6563726166743a6d6174636800146d696e65637261 -66743a6d656469746174697665000d6d696e6563726166743a6f726200126d69 -6e6563726166743a6f776c656d6f6e7300116d696e6563726166743a70617373 -61676500126d696e6563726166743a7069677363656e65000f6d696e65637261 -66743a706c616e7400116d696e6563726166743a706f696e746572000e6d696e -6563726166743a706f6e64000e6d696e6563726166743a706f6f6c00166d696e -6563726166743a707261697269655f72696465000d6d696e6563726166743a73 -656100126d696e6563726166743a736b656c65746f6e00196d696e6563726166 -743a736b756c6c5f616e645f726f736573000f6d696e6563726166743a737461 -676500146d696e6563726166743a73756e666c6f7765727300106d696e656372 -6166743a73756e736574000f6d696e6563726166743a746964657300126d696e -6563726166743a756e7061636b6564000e6d696e6563726166743a766f696400 -126d696e6563726166743a77616e646572657200136d696e6563726166743a77 -617374656c616e64000f6d696e6563726166743a7761746572000e6d696e6563 -726166743a77696e6400106d696e6563726166743a776974686572007407186d -696e6563726166743a64696d656e73696f6e5f7479706504136d696e65637261 -66743a6f766572776f726c6400196d696e6563726166743a6f766572776f726c -645f636176657300116d696e6563726166743a7468655f656e6400146d696e65 -63726166743a7468655f6e6574686572009e0807156d696e6563726166743a64 -616d6167655f747970652f0f6d696e6563726166743a6172726f77001b6d696e -6563726166743a6261645f7265737061776e5f706f696e7400106d696e656372 -6166743a63616374757300126d696e6563726166743a63616d70666972650012 -6d696e6563726166743a6372616d6d696e6700176d696e6563726166743a6472 -61676f6e5f627265617468000f6d696e6563726166743a64726f776e00116d69 -6e6563726166743a6472795f6f757400136d696e6563726166743a6578706c6f -73696f6e000e6d696e6563726166743a66616c6c00176d696e6563726166743a -66616c6c696e675f616e76696c00176d696e6563726166743a66616c6c696e67 -5f626c6f636b001c6d696e6563726166743a66616c6c696e675f7374616c6163 -7469746500126d696e6563726166743a6669726562616c6c00136d696e656372 -6166743a66697265776f726b7300176d696e6563726166743a666c795f696e74 -6f5f77616c6c00106d696e6563726166743a667265657a6500116d696e656372 -6166743a67656e6572696300166d696e6563726166743a67656e657269635f6b -696c6c00136d696e6563726166743a686f745f666c6f6f7200116d696e656372 -6166743a696e5f6669726500116d696e6563726166743a696e5f77616c6c0018 -6d696e6563726166743a696e6469726563745f6d61676963000e6d696e656372 -6166743a6c61766100186d696e6563726166743a6c696768746e696e675f626f -6c74000f6d696e6563726166743a6d6167696300146d696e6563726166743a6d -6f625f61747461636b001d6d696e6563726166743a6d6f625f61747461636b5f -6e6f5f616767726f00186d696e6563726166743a6d6f625f70726f6a65637469 -6c6500116d696e6563726166743a6f6e5f6669726500166d696e656372616674 -3a6f75745f6f665f776f726c6400186d696e6563726166743a6f757473696465 -5f626f7264657200176d696e6563726166743a706c617965725f61747461636b -001a6d696e6563726166743a706c617965725f6578706c6f73696f6e00146d69 -6e6563726166743a736f6e69635f626f6f6d000e6d696e6563726166743a7370 -697400146d696e6563726166743a7374616c61676d69746500106d696e656372 -6166743a737461727665000f6d696e6563726166743a7374696e67001a6d696e -6563726166743a73776565745f62657272795f6275736800106d696e65637261 -66743a74686f726e7300106d696e6563726166743a7468726f776e00116d696e -6563726166743a74726964656e74001f6d696e6563726166743a756e61747472 -6962757465645f6669726562616c6c00156d696e6563726166743a77696e645f -63686172676500106d696e6563726166743a77697468657200166d696e656372 -6166743a7769746865725f736b756c6c008c0807186d696e6563726166743a62 -616e6e65725f7061747465726e2b0e6d696e6563726166743a6261736500106d -696e6563726166743a626f7264657200106d696e6563726166743a627269636b -7300106d696e6563726166743a636972636c6500116d696e6563726166743a63 -726565706572000f6d696e6563726166743a63726f737300166d696e65637261 -66743a6375726c795f626f7264657200176d696e6563726166743a646961676f -6e616c5f6c65667400186d696e6563726166743a646961676f6e616c5f726967 -6874001a6d696e6563726166743a646961676f6e616c5f75705f6c656674001b -6d696e6563726166743a646961676f6e616c5f75705f7269676874000e6d696e -6563726166743a666c6f7700106d696e6563726166743a666c6f776572000f6d -696e6563726166743a676c6f626500126d696e6563726166743a677261646965 -6e7400156d696e6563726166743a6772616469656e745f757000106d696e6563 -726166743a67757374657200196d696e6563726166743a68616c665f686f7269 -7a6f6e74616c00206d696e6563726166743a68616c665f686f72697a6f6e7461 -6c5f626f74746f6d00176d696e6563726166743a68616c665f76657274696361 -6c001d6d696e6563726166743a68616c665f766572746963616c5f7269676874 -00106d696e6563726166743a6d6f6a616e6700106d696e6563726166743a7069 -676c696e00116d696e6563726166743a72686f6d627573000f6d696e65637261 -66743a736b756c6c00176d696e6563726166743a736d616c6c5f737472697065 -73001c6d696e6563726166743a7371756172655f626f74746f6d5f6c65667400 -1d6d696e6563726166743a7371756172655f626f74746f6d5f72696768740019 -6d696e6563726166743a7371756172655f746f705f6c656674001a6d696e6563 -726166743a7371756172655f746f705f726967687400186d696e656372616674 -3a73747261696768745f63726f737300176d696e6563726166743a7374726970 -655f626f74746f6d00176d696e6563726166743a7374726970655f63656e7465 -7200196d696e6563726166743a7374726970655f646f776e6c656674001a6d69 -6e6563726166743a7374726970655f646f776e726967687400156d696e656372 -6166743a7374726970655f6c65667400176d696e6563726166743a7374726970 -655f6d6964646c6500166d696e6563726166743a7374726970655f7269676874 -00146d696e6563726166743a7374726970655f746f7000196d696e6563726166 -743a747269616e676c655f626f74746f6d00166d696e6563726166743a747269 -616e676c655f746f70001a6d696e6563726166743a747269616e676c65735f62 -6f74746f6d00176d696e6563726166743a747269616e676c65735f746f7000b7 -0707156d696e6563726166743a656e6368616e746d656e742a176d696e656372 -6166743a617175615f616666696e697479001c6d696e6563726166743a62616e -655f6f665f61727468726f706f647300176d696e6563726166743a62696e6469 -6e675f6375727365001a6d696e6563726166743a626c6173745f70726f746563 -74696f6e00106d696e6563726166743a62726561636800146d696e6563726166 -743a6368616e6e656c696e6700116d696e6563726166743a64656e7369747900 -176d696e6563726166743a64657074685f7374726964657200146d696e656372 -6166743a656666696369656e637900196d696e6563726166743a666561746865 -725f66616c6c696e6700156d696e6563726166743a666972655f617370656374 -00196d696e6563726166743a666972655f70726f74656374696f6e000f6d696e -6563726166743a666c616d6500116d696e6563726166743a666f7274756e6500 -166d696e6563726166743a66726f73745f77616c6b657200126d696e65637261 -66743a696d70616c696e6700126d696e6563726166743a696e66696e69747900 -136d696e6563726166743a6b6e6f636b6261636b00116d696e6563726166743a -6c6f6f74696e6700116d696e6563726166743a6c6f79616c747900196d696e65 -63726166743a6c75636b5f6f665f7468655f736561000e6d696e656372616674 -3a6c75726500116d696e6563726166743a6d656e64696e6700136d696e656372 -6166743a6d756c746973686f7400126d696e6563726166743a7069657263696e -67000f6d696e6563726166743a706f776572001f6d696e6563726166743a7072 -6f6a656374696c655f70726f74656374696f6e00146d696e6563726166743a70 -726f74656374696f6e000f6d696e6563726166743a70756e636800166d696e65 -63726166743a717569636b5f63686172676500156d696e6563726166743a7265 -737069726174696f6e00116d696e6563726166743a7269707469646500136d69 -6e6563726166743a73686172706e65737300146d696e6563726166743a73696c -6b5f746f756368000f6d696e6563726166743a736d69746500146d696e656372 -6166743a736f756c5f737065656400176d696e6563726166743a737765657069 -6e675f6564676500156d696e6563726166743a73776966745f736e65616b0010 -6d696e6563726166743a74686f726e7300146d696e6563726166743a756e6272 -65616b696e6700196d696e6563726166743a76616e697368696e675f63757273 -6500146d696e6563726166743a77696e645f627572737400e50207166d696e65 -63726166743a6a756b65626f785f736f6e67130c6d696e6563726166743a3131 -000c6d696e6563726166743a3133000b6d696e6563726166743a3500106d696e -6563726166743a626c6f636b73000d6d696e6563726166743a636174000f6d69 -6e6563726166743a636869727000116d696e6563726166743a63726561746f72 -001b6d696e6563726166743a63726561746f725f6d757369635f626f78000d6d -696e6563726166743a666172000e6d696e6563726166743a6d616c6c00116d69 -6e6563726166743a6d656c6c6f686900136d696e6563726166743a6f74686572 -7369646500116d696e6563726166743a7069677374657000136d696e65637261 -66743a707265636970696365000f6d696e6563726166743a72656c6963000e6d -696e6563726166743a7374616c000f6d696e6563726166743a7374726164000e -6d696e6563726166743a77616974000e6d696e6563726166743a7761726400 diff --git a/cpp/cobolcraft_util.cpp b/cpp/cobolcraft_util.cpp index 0dfe556..8ccbad5 100644 --- a/cpp/cobolcraft_util.cpp +++ b/cpp/cobolcraft_util.cpp @@ -1,8 +1,10 @@ #include "cobolcraft_util.h" +#include #include #include #include #include +#include #include #define ERRNO_PARAMS 99 @@ -90,6 +92,65 @@ EXTERN_DECL int LeadingZeros32(unsigned long *value, unsigned long *count) return 0; } +EXTERN_DECL int OpenDirectory(char *path, unsigned long *path_length, unsigned long long *handle) +{ + static char buffer[65536]; + if (!path || !path_length || *path_length == 0 || *path_length >= sizeof(buffer)) + { + return ERRNO_PARAMS; + } + memcpy(buffer, path, *path_length); + buffer[*path_length] = '\0'; + DIR *dir; + if ((dir = opendir(buffer)) == NULL) + { + return ERRNO_SYSTEM; + } + *handle = (unsigned long long)dir; + return 0; +} + +EXTERN_DECL int ReadDirectory(unsigned long long *handle, char *entry) +{ + if (!handle || !entry) + { + return ERRNO_PARAMS; + } + DIR *dir = (DIR *)(*handle); + struct dirent *result; + do + { + result = readdir(dir); + if (result == NULL) + { + return ERRNO_SYSTEM; + } + } while (strcmp(result->d_name, ".") == 0 || strcmp(result->d_name, "..") == 0); + // Invariant: entry is at least 255 bytes long - but it will be space-padded instead of null-terminated. + size_t length = strlen(result->d_name); + if (length > 255) + { + length = 255; + } + memcpy(entry, result->d_name, length); + memset(entry + length, ' ', 255 - length); + return 0; +} + +EXTERN_DECL int CloseDirectory(unsigned long long *handle) +{ + if (!handle) + { + return ERRNO_PARAMS; + } + DIR *dir = (DIR *)(*handle); + if (closedir(dir) != 0) + { + return ERRNO_SYSTEM; + } + return 0; +} + EXTERN_DECL int ZlibCompress(char *decompressed, unsigned long *decompressed_length, char *compressed, unsigned long *compressed_length) { if (!decompressed || !decompressed_length || !compressed || !compressed_length) diff --git a/cpp/cobolcraft_util.h b/cpp/cobolcraft_util.h index efa3df2..5bb677a 100644 --- a/cpp/cobolcraft_util.h +++ b/cpp/cobolcraft_util.h @@ -26,6 +26,24 @@ EXTERN_DECL int ReadConsole(char *buffer, unsigned long *count); */ EXTERN_DECL int LeadingZeros32(unsigned long *value, unsigned long *count); +/** + * Open a directory for reading (e.g., to obtain a directory listing). The first parameter is the directory path; the + * second parameter is its length; the third parameter is the resulting directory handle (as a 64-bit integer). + */ +EXTERN_DECL int OpenDirectory(char *path, unsigned long *path_length, unsigned long long *handle); + +/** + * Read the next entry in a directory listing. The first parameter is the directory handle; the second parameter is + * the resulting entry name, which must be pre-allocated by the caller with at least 255 bytes capacity. The entry + * name will be padded with trailing spaces for names shorter than 255 bytes. The entries "." and ".." are skipped. + */ +EXTERN_DECL int ReadDirectory(unsigned long long *handle, char *entry); + +/** + * Close a directory handle. + */ +EXTERN_DECL int CloseDirectory(unsigned long long *handle); + /** * Compress a buffer using zlib (deflate). The compressed length indicates the size of the compressed buffer; after compression, * it contains the actual size of the compressed data. diff --git a/src/copybooks/DD-REGISTRIES.cpy b/src/copybooks/DD-REGISTRIES.cpy index c8988e9..3a31c24 100644 --- a/src/copybooks/DD-REGISTRIES.cpy +++ b/src/copybooks/DD-REGISTRIES.cpy @@ -4,6 +4,7 @@ 02 REGISTRY OCCURS 100 TIMES. 03 REGISTRY-NAME PIC X(100). 03 REGISTRY-ID BINARY-LONG UNSIGNED. + 03 REGISTRY-REQUIRES-PACKET BINARY-CHAR UNSIGNED. 03 REGISTRY-ENTRIES-COUNT BINARY-LONG UNSIGNED. 03 REGISTRY-ENTRY OCCURS 2000 TIMES. 04 REGISTRY-ENTRY-NAME PIC X(100). diff --git a/src/copybooks/DD-WORLD.cpy b/src/copybooks/DD-WORLD.cpy index eb6df81..a47ac9c 100644 --- a/src/copybooks/DD-WORLD.cpy +++ b/src/copybooks/DD-WORLD.cpy @@ -19,6 +19,10 @@ 04 WORLD-SECTION-BLOCKS. 05 WORLD-BLOCK OCCURS 4096 TIMES. 06 WORLD-BLOCK-ID BINARY-LONG UNSIGNED. + *> section biome ID + *> TODO: This is kind of a hack, just to get a default "plains" biome instead of whatever is added first to + *> the biome registry (usually badlands). We should have a separate biome array. + 04 WORLD-SECTION-BIOME-ID BINARY-LONG UNSIGNED. 03 WORLD-BLOCK-ENTITY-COUNT BINARY-LONG UNSIGNED. *> block entity IDs for each block 03 WORLD-BLOCK-ENTITIES. diff --git a/src/datapack.cob b/src/datapack.cob new file mode 100644 index 0000000..6122fca --- /dev/null +++ b/src/datapack.cob @@ -0,0 +1,104 @@ +*> --- Datapack-Load --- +*> Load registry contents from a datapack path. +IDENTIFICATION DIVISION. +PROGRAM-ID. Datapack-Load. + +DATA DIVISION. +WORKING-STORAGE SECTION. + 01 REGISTRY-COUNT BINARY-LONG UNSIGNED. + 01 REGISTRY-INDEX BINARY-LONG UNSIGNED. + 01 REGISTRY-NAME PIC X(255). +LINKAGE SECTION. + 01 LK-ROOT-PATH PIC X ANY LENGTH. + 01 LK-PACK-NAME PIC X ANY LENGTH. + 01 LK-FAILURE BINARY-CHAR UNSIGNED. + +PROCEDURE DIVISION USING LK-ROOT-PATH LK-PACK-NAME LK-FAILURE. + *> For each known registry, load the contents from the datapack (if it exists). + CALL "Registries-GetCount" USING REGISTRY-COUNT + PERFORM VARYING REGISTRY-INDEX FROM 1 BY 1 UNTIL REGISTRY-INDEX > REGISTRY-COUNT + CALL "Registries-Iterate-Name" USING REGISTRY-INDEX REGISTRY-NAME + *> We want to remove the "minecraft:" prefix from registry names to match the directory structure + IF REGISTRY-NAME(1:10) = "minecraft:" + CALL "Datapack-Load-Registry" USING LK-ROOT-PATH LK-PACK-NAME REGISTRY-NAME(11:) REGISTRY-INDEX LK-FAILURE + IF LK-FAILURE NOT = 0 + GOBACK + END-IF + END-IF + END-PERFORM + + GOBACK. + + IDENTIFICATION DIVISION. + PROGRAM-ID. Datapack-Load-Registry. + + DATA DIVISION. + WORKING-STORAGE SECTION. + 01 DIR-PATH PIC X(255). + 01 DIR-PATH-LENGTH BINARY-LONG UNSIGNED. + 01 DIR-HANDLE PIC X(8). + 01 EOF BINARY-CHAR UNSIGNED. + 01 DIR-ENTRY PIC X(255). + 01 ENTRY-ID BINARY-LONG UNSIGNED. + 01 ENTRY-NAME PIC X(255). + 01 CHAR-INDEX BINARY-LONG UNSIGNED. + LINKAGE SECTION. + 01 LK-ROOT-PATH PIC X ANY LENGTH. + 01 LK-PACK-NAME PIC X ANY LENGTH. + 01 LK-REGISTRY-NAME PIC X ANY LENGTH. + 01 LK-REGISTRY-INDEX BINARY-LONG UNSIGNED. + 01 LK-FAILURE BINARY-CHAR UNSIGNED. + + PROCEDURE DIVISION USING LK-ROOT-PATH LK-PACK-NAME LK-REGISTRY-NAME LK-REGISTRY-INDEX LK-FAILURE. + INITIALIZE DIR-PATH + STRING + FUNCTION TRIM(LK-ROOT-PATH) + FUNCTION TRIM(LK-PACK-NAME) + "/" + FUNCTION TRIM(LK-REGISTRY-NAME) + DELIMITED BY SIZE INTO DIR-PATH + END-STRING + MOVE FUNCTION STORED-CHAR-LENGTH(DIR-PATH) TO DIR-PATH-LENGTH + + CALL "OpenDirectory" USING DIR-PATH DIR-PATH-LENGTH DIR-HANDLE GIVING LK-FAILURE + IF LK-FAILURE NOT = 0 + *> The directory is likely missing, which isn't an error. + MOVE 0 TO LK-FAILURE + GOBACK + END-IF + + *> The entry protocol IDs will be numbered starting from the registry length. + CALL "Registries-GetRegistryLength" USING LK-REGISTRY-INDEX ENTRY-ID + + PERFORM UNTIL EXIT + CALL "ReadDirectory" USING DIR-HANDLE DIR-ENTRY GIVING EOF + IF EOF NOT = 0 + EXIT PERFORM + END-IF + + *> Prepend the namespace and remove the file extension + INITIALIZE ENTRY-NAME + STRING + FUNCTION TRIM(LK-PACK-NAME) + ":" + FUNCTION TRIM(DIR-ENTRY) + DELIMITED BY SIZE INTO ENTRY-NAME + END-STRING + PERFORM VARYING CHAR-INDEX FROM 1 BY 1 UNTIL CHAR-INDEX > FUNCTION STORED-CHAR-LENGTH(ENTRY-NAME) + IF ENTRY-NAME(CHAR-INDEX:1) = "." + MOVE SPACES TO ENTRY-NAME(CHAR-INDEX:) + END-IF + END-PERFORM + + *> Register the entry + CALL "Registries-CreateEntry" USING LK-REGISTRY-INDEX ENTRY-NAME ENTRY-ID + ADD 1 TO ENTRY-ID + END-PERFORM + + CALL "CloseDirectory" USING DIR-HANDLE + + GOBACK. + + END PROGRAM Datapack-Load-Registry. + +END PROGRAM Datapack-Load. diff --git a/src/packets/chunkdata.cob b/src/packets/chunkdata.cob index 86fbc28..c26a443 100644 --- a/src/packets/chunkdata.cob +++ b/src/packets/chunkdata.cob @@ -32,6 +32,7 @@ LINKAGE SECTION. *> block IDs (16x16x16) - X increases fastest, then Z, then Y 03 LK-BLOCK OCCURS 4096 TIMES. 04 LK-BLOCK-ID BINARY-LONG UNSIGNED. + 03 LK-BIOME-ID BINARY-LONG UNSIGNED. 02 LK-CHUNK-BLOCK-ENTITY-COUNT BINARY-LONG UNSIGNED. *> block entity IDs for each block 02 LK-CHUNK-BLOCK-ENTITIES. @@ -177,6 +178,7 @@ PROCEDURE DIVISION USING LK-CLIENT LK-CHUNK. 02 LK-NON-AIR BINARY-LONG UNSIGNED. 02 LK-BLOCK OCCURS 4096 TIMES. 03 LK-BLOCK-ID BINARY-LONG UNSIGNED. + 02 LK-BIOME-ID BINARY-LONG UNSIGNED. 01 LK-BUFFER PIC X ANY LENGTH. 01 LK-BUFFERPOS BINARY-LONG UNSIGNED. @@ -223,9 +225,8 @@ PROCEDURE DIVISION USING LK-CLIENT LK-CHUNK. MOVE X"00" TO LK-BUFFER(LK-BUFFERPOS:1) ADD 1 TO LK-BUFFERPOS *> - palette: id of the biome - *> TODO: use plains biome - MOVE 0 TO INT32 - CALL "Encode-VarInt" USING INT32 LK-BUFFER LK-BUFFERPOS + *> TODO: use actual biome data + CALL "Encode-VarInt" USING LK-BIOME-ID LK-BUFFER LK-BUFFERPOS *> - data array length: 0, since we have a single-valued palette MOVE 0 TO INT32 CALL "Encode-VarInt" USING INT32 LK-BUFFER LK-BUFFERPOS diff --git a/src/packets/registry.cob b/src/packets/registry.cob index 0bea0f5..400dc44 100644 --- a/src/packets/registry.cob +++ b/src/packets/registry.cob @@ -1,52 +1,51 @@ IDENTIFICATION DIVISION. PROGRAM-ID. SendPacket-Registry. -ENVIRONMENT DIVISION. -INPUT-OUTPUT SECTION. -FILE-CONTROL. -SELECT FD-REGISTRY-BLOB ASSIGN TO "blobs/registry_packets.txt" - ORGANIZATION IS LINE SEQUENTIAL. - DATA DIVISION. -FILE SECTION. - FD FD-REGISTRY-BLOB. - 01 REGISTRY-BLOB-REC PIC X(64). WORKING-STORAGE SECTION. - COPY DD-CLIENTS. - 01 HNDL PIC X(4). - 01 ERRNO PIC 9(3). - 01 HEX PIC X(64). - 01 HEXLEN BINARY-LONG UNSIGNED. - 01 BUFFER PIC X(32). - 01 BUFFERLEN BINARY-LONG UNSIGNED. + 01 PACKET-ID BINARY-LONG VALUE H'07'. + *> buffer used to store the packet data + 01 PAYLOAD PIC X(60000). + 01 PAYLOADPOS BINARY-LONG UNSIGNED. + 01 PAYLOADLEN BINARY-LONG UNSIGNED. + *> temporary data + 01 REGISTRY-NAME PIC X(255). + 01 REGISTRY-ENTRY-COUNT BINARY-LONG UNSIGNED. + 01 REGISTRY-ENTRY-INDEX BINARY-LONG UNSIGNED. + 01 REGISTRY-ENTRY-NAME PIC X(255). + 01 INT32 BINARY-LONG. LINKAGE SECTION. - 01 LK-CLIENT BINARY-LONG UNSIGNED. - -PROCEDURE DIVISION USING LK-CLIENT. - *> Don't send packet if the client is already in an error state. It will be disconnected on the next tick. - IF CLIENT-ERRNO-SEND(LK-CLIENT) NOT = 0 - EXIT PROGRAM - END-IF - MOVE CLIENT-HNDL(LK-CLIENT) TO HNDL - - OPEN INPUT FD-REGISTRY-BLOB - MOVE 64 TO HEXLEN - PERFORM UNTIL HEXLEN = 0 - MOVE SPACES TO HEX(1:64) - READ FD-REGISTRY-BLOB INTO HEX - AT END - MOVE 0 TO HEXLEN - NOT AT END - CALL "DecodeHexString" USING HEX HEXLEN BUFFER BUFFERLEN - CALL "Socket-Write" USING HNDL ERRNO BUFFERLEN BUFFER - IF ERRNO NOT = 0 - MOVE 0 TO HEXLEN - MOVE ERRNO TO CLIENT-ERRNO-SEND(LK-CLIENT) - END-IF - END-READ + 01 LK-CLIENT BINARY-LONG UNSIGNED. + 01 LK-REGISTRY-INDEX BINARY-LONG UNSIGNED. + +PROCEDURE DIVISION USING LK-CLIENT LK-REGISTRY-INDEX. + MOVE 1 TO PAYLOADPOS + + *> registry name + CALL "Registries-Iterate-Name" USING LK-REGISTRY-INDEX REGISTRY-NAME + MOVE FUNCTION STORED-CHAR-LENGTH(REGISTRY-NAME) TO INT32 + CALL "Encode-String" USING REGISTRY-NAME INT32 PAYLOAD PAYLOADPOS + + *> entry count + CALL "Registries-GetRegistryLength" USING LK-REGISTRY-INDEX REGISTRY-ENTRY-COUNT + CALL "Encode-VarInt" USING REGISTRY-ENTRY-COUNT PAYLOAD PAYLOADPOS + + *> entries + PERFORM VARYING REGISTRY-ENTRY-INDEX FROM 1 BY 1 UNTIL REGISTRY-ENTRY-INDEX > REGISTRY-ENTRY-COUNT + *> TODO: This assumes that entries are sorted by protocol ID. This is the case for all registries that we care + *> about with this packet, but shouldn't be relied upon. + CALL "Registries-Iterate-EntryName" USING LK-REGISTRY-INDEX REGISTRY-ENTRY-INDEX REGISTRY-ENTRY-NAME + MOVE FUNCTION STORED-CHAR-LENGTH(REGISTRY-ENTRY-NAME) TO INT32 + CALL "Encode-String" USING REGISTRY-ENTRY-NAME INT32 PAYLOAD PAYLOADPOS + + *> has data (always false) + MOVE X"00" TO PAYLOAD(PAYLOADPOS:1) + ADD 1 TO PAYLOADPOS END-PERFORM - CLOSE FD-REGISTRY-BLOB + *> send packet + COMPUTE PAYLOADLEN = PAYLOADPOS - 1 + CALL "SendPacket" USING LK-CLIENT PACKET-ID PAYLOAD PAYLOADLEN GOBACK. END PROGRAM SendPacket-Registry. diff --git a/src/registries.cob b/src/registries.cob index 5fa5380..acb8e19 100644 --- a/src/registries.cob +++ b/src/registries.cob @@ -53,6 +53,7 @@ PROCEDURE DIVISION USING LK-JSON LK-JSON-LEN LK-FAILURE. 01 LK-REGISTRY BINARY-LONG UNSIGNED. PROCEDURE DIVISION USING LK-JSON LK-OFFSET LK-FAILURE LK-REGISTRY. + MOVE 0 TO REGISTRY-REQUIRES-PACKET(LK-REGISTRY) MOVE 0 TO REGISTRY-ENTRIES-COUNT(LK-REGISTRY) *> Read the registry name. @@ -197,6 +198,85 @@ PROCEDURE DIVISION USING LK-JSON LK-JSON-LEN LK-FAILURE. END PROGRAM Registries-Parse. +*> --- Registries-Create --- +*> Create a new, empty registry. The registry's protocol ID will be the current highest ID + 1. +IDENTIFICATION DIVISION. +PROGRAM-ID. Registries-Create. + +DATA DIVISION. +WORKING-STORAGE SECTION. + 01 REGISTRY-LOOP-INDEX BINARY-LONG UNSIGNED. + 01 MAX-REGISTRY-ID BINARY-LONG UNSIGNED. + *> shared data + COPY DD-REGISTRIES. +LINKAGE SECTION. + 01 LK-REGISTRY-NAME PIC X ANY LENGTH. + 01 LK-PACKET-REQUIRED BINARY-CHAR UNSIGNED. + +PROCEDURE DIVISION USING LK-REGISTRY-NAME LK-PACKET-REQUIRED. + *> On the first call, determine the current highest protocol ID. + IF MAX-REGISTRY-ID = 0 + PERFORM VARYING REGISTRY-LOOP-INDEX FROM 1 BY 1 UNTIL REGISTRY-LOOP-INDEX > REGISTRIES-COUNT + IF REGISTRY-ID(REGISTRY-LOOP-INDEX) > MAX-REGISTRY-ID + MOVE REGISTRY-ID(REGISTRY-LOOP-INDEX) TO MAX-REGISTRY-ID + END-IF + END-PERFORM + END-IF + + *> Assign the new protocol ID. + ADD 1 TO MAX-REGISTRY-ID + + *> Create the new registry. + ADD 1 TO REGISTRIES-COUNT + MOVE LK-REGISTRY-NAME TO REGISTRY-NAME(REGISTRIES-COUNT) + MOVE MAX-REGISTRY-ID TO REGISTRY-ID(REGISTRIES-COUNT) + MOVE LK-PACKET-REQUIRED TO REGISTRY-REQUIRES-PACKET(REGISTRIES-COUNT) + MOVE 0 TO REGISTRY-ENTRIES-COUNT(REGISTRIES-COUNT) + + GOBACK. + +END PROGRAM Registries-Create. + +*> --- Registries-CreateEntry --- +*> Create a new entry in a registry. +IDENTIFICATION DIVISION. +PROGRAM-ID. Registries-CreateEntry. + +DATA DIVISION. +WORKING-STORAGE SECTION. + *> shared data + COPY DD-REGISTRIES. +LINKAGE SECTION. + 01 LK-REGISTRY-INDEX BINARY-LONG UNSIGNED. + 01 LK-ENTRY-NAME PIC X ANY LENGTH. + 01 LK-ENTRY-ID BINARY-LONG. + +PROCEDURE DIVISION USING LK-REGISTRY-INDEX LK-ENTRY-NAME LK-ENTRY-ID. + ADD 1 TO REGISTRY-ENTRIES-COUNT(LK-REGISTRY-INDEX) + MOVE LK-ENTRY-NAME TO REGISTRY-ENTRY-NAME(LK-REGISTRY-INDEX, REGISTRY-ENTRIES-COUNT(LK-REGISTRY-INDEX)) + MOVE LK-ENTRY-ID TO REGISTRY-ENTRY-ID(LK-REGISTRY-INDEX, REGISTRY-ENTRIES-COUNT(LK-REGISTRY-INDEX)) + GOBACK. + +END PROGRAM Registries-CreateEntry. + +*> --- Registries-GetCount --- +*> Get the number of registries. +IDENTIFICATION DIVISION. +PROGRAM-ID. Registries-GetCount. + +DATA DIVISION. +WORKING-STORAGE SECTION. + *> shared data + COPY DD-REGISTRIES. +LINKAGE SECTION. + 01 LK-REGISTRY-COUNT BINARY-LONG UNSIGNED. + +PROCEDURE DIVISION USING LK-REGISTRY-COUNT. + MOVE REGISTRIES-COUNT TO LK-REGISTRY-COUNT + GOBACK. + +END PROGRAM Registries-GetCount. + *> --- Registries-GetRegistryIndex --- *> Get the index of a registry by its name for faster access. IDENTIFICATION DIVISION. @@ -240,6 +320,44 @@ PROCEDURE DIVISION USING LK-REGISTRY-INDEX LK-REGISTRY-LENGTH. END PROGRAM Registries-GetRegistryLength. +*> --- Registries-Iterate-Name --- +*> Get the name of a registry by its index. +IDENTIFICATION DIVISION. +PROGRAM-ID. Registries-Iterate-Name. + +DATA DIVISION. +WORKING-STORAGE SECTION. + *> shared data + COPY DD-REGISTRIES. +LINKAGE SECTION. + 01 LK-REGISTRY-INDEX BINARY-LONG UNSIGNED. + 01 LK-REGISTRY-NAME PIC X ANY LENGTH. + +PROCEDURE DIVISION USING LK-REGISTRY-INDEX LK-REGISTRY-NAME. + MOVE REGISTRY-NAME(LK-REGISTRY-INDEX) TO LK-REGISTRY-NAME + GOBACK. + +END PROGRAM Registries-Iterate-Name. + +*> --- Registries-Iterate-ReqPacket --- +*> Get whether a registry requires a packet by its index. +IDENTIFICATION DIVISION. +PROGRAM-ID. Registries-Iterate-ReqPacket. + +DATA DIVISION. +WORKING-STORAGE SECTION. + *> shared data + COPY DD-REGISTRIES. +LINKAGE SECTION. + 01 LK-REGISTRY-INDEX BINARY-LONG UNSIGNED. + 01 LK-REQUIRES-PACKET BINARY-CHAR UNSIGNED. + +PROCEDURE DIVISION USING LK-REGISTRY-INDEX LK-REQUIRES-PACKET. + MOVE REGISTRY-REQUIRES-PACKET(LK-REGISTRY-INDEX) TO LK-REQUIRES-PACKET + GOBACK. + +END PROGRAM Registries-Iterate-ReqPacket. + *> --- Registries-Iterate-EntryName --- *> Get the name of an entry by its index. IDENTIFICATION DIVISION. diff --git a/src/server.cob b/src/server.cob index 03e87ff..757ca07 100644 --- a/src/server.cob +++ b/src/server.cob @@ -8,8 +8,20 @@ WORKING-STORAGE SECTION. *> File names 01 FILE-REGISTRIES PIC X(255) VALUE "data/generated/reports/registries.json". 01 FILE-BLOCKS PIC X(255) VALUE "data/generated/reports/blocks.json". + 01 FILE-DATAPACK-ROOT PIC X(255) VALUE "data/generated/data/". *> Constants COPY DD-CLIENT-STATES. + 01 C-MINECRAFT-WORLDGEN-BIOME PIC X(50) VALUE "minecraft:worldgen/biome". + 01 C-MINECRAFT-CHAT_TYPE PIC X(50) VALUE "minecraft:chat_type". + 01 C-MINECRAFT-TRIM_PATTERN PIC X(50) VALUE "minecraft:trim_pattern". + 01 C-MINECRAFT-TRIM_MATERIAL PIC X(50) VALUE "minecraft:trim_material". + 01 C-MINECRAFT-WOLF_VARIANT PIC X(50) VALUE "minecraft:wolf_variant". + 01 C-MINECRAFT-PAINTING_VARIANT PIC X(50) VALUE "minecraft:painting_variant". + 01 C-MINECRAFT-DIMENSION_TYPE PIC X(50) VALUE "minecraft:dimension_type". + 01 C-MINECRAFT-DAMAGE_TYPE PIC X(50) VALUE "minecraft:damage_type". + 01 C-MINECRAFT-BANNER_PATTERN PIC X(50) VALUE "minecraft:banner_pattern". + 01 C-MINECRAFT-ENCHANTMENT PIC X(50) VALUE "minecraft:enchantment". + 01 C-MINECRAFT-JUKEBOX_SONG PIC X(50) VALUE "minecraft:jukebox_song". 01 C-MINECRAFT-ITEM PIC X(50) VALUE "minecraft:item". 01 C-COLOR-YELLOW PIC X(16) VALUE "yellow". *> The server sends (2 * VIEW-DISTANCE + 1) * (2 * VIEW-DISTANCE + 1) chunks around the player. @@ -73,6 +85,9 @@ WORKING-STORAGE SECTION. 01 CHUNK-END-Z BINARY-LONG. 01 PREV-CENTER-CHUNK-X BINARY-LONG. 01 PREV-CENTER-CHUNK-Z BINARY-LONG. + *> Variables used for datapack loading + 01 VANILLA-DATAPACK-NAME PIC X(50) VALUE "minecraft". + 01 REGISTRY-COUNT BINARY-LONG UNSIGNED. *> Variables used for item registration 01 REGISTRY-INDEX BINARY-LONG. 01 REGISTRY-LENGTH BINARY-LONG UNSIGNED. @@ -108,6 +123,21 @@ LoadRegistries. DISPLAY "Failed to parse registries" STOP RUN END-IF + + *> Create additional registries not exported by the report generator. + *> Set the flag to 1 to indicate that they need to be part of a Registry Data packet sent to the client. + MOVE 1 TO TEMP-INT8 + CALL "Registries-Create" USING C-MINECRAFT-WORLDGEN-BIOME TEMP-INT8 + CALL "Registries-Create" USING C-MINECRAFT-CHAT_TYPE TEMP-INT8 + CALL "Registries-Create" USING C-MINECRAFT-TRIM_PATTERN TEMP-INT8 + CALL "Registries-Create" USING C-MINECRAFT-TRIM_MATERIAL TEMP-INT8 + CALL "Registries-Create" USING C-MINECRAFT-WOLF_VARIANT TEMP-INT8 + CALL "Registries-Create" USING C-MINECRAFT-PAINTING_VARIANT TEMP-INT8 + CALL "Registries-Create" USING C-MINECRAFT-DIMENSION_TYPE TEMP-INT8 + CALL "Registries-Create" USING C-MINECRAFT-DAMAGE_TYPE TEMP-INT8 + CALL "Registries-Create" USING C-MINECRAFT-BANNER_PATTERN TEMP-INT8 + CALL "Registries-Create" USING C-MINECRAFT-ENCHANTMENT TEMP-INT8 + CALL "Registries-Create" USING C-MINECRAFT-JUKEBOX_SONG TEMP-INT8 . LoadBlocks. @@ -124,6 +154,26 @@ LoadBlocks. END-IF . +LoadDatapack. + DISPLAY "Loading vanilla datapack" + CALL "Datapack-Load" USING FILE-DATAPACK-ROOT VANILLA-DATAPACK-NAME DATA-FAILURE + IF DATA-FAILURE NOT = 0 + DISPLAY "Failed to load datapack" + STOP RUN + END-IF + + *> Sanity check: There shouldn't be any empty registries now. + CALL "Registries-GetCount" USING REGISTRY-COUNT + PERFORM VARYING REGISTRY-INDEX FROM 1 BY 1 UNTIL REGISTRY-INDEX > REGISTRY-COUNT + CALL "Registries-GetRegistryLength" USING REGISTRY-INDEX REGISTRY-LENGTH + IF REGISTRY-LENGTH <= 0 + CALL "Registries-Iterate-Name" USING REGISTRY-INDEX TEMP-IDENTIFIER + DISPLAY "Error: Empty registry '" FUNCTION TRIM(TEMP-IDENTIFIER) "'!" + STOP RUN + END-IF + END-PERFORM + . + RegisterItems. DISPLAY "Registering items" @@ -742,7 +792,13 @@ HandleConfiguration SECTION. *> Send configuration packets CALL "SendPacket-FeatureFlags" USING CLIENT-ID CALL "SendPacket-KnownPacks" USING CLIENT-ID - CALL "SendPacket-Registry" USING CLIENT-ID + CALL "Registries-GetCount" USING REGISTRY-COUNT + PERFORM VARYING REGISTRY-INDEX FROM 1 BY 1 UNTIL REGISTRY-INDEX > REGISTRY-COUNT + CALL "Registries-Iterate-ReqPacket" USING REGISTRY-INDEX TEMP-INT8 + IF TEMP-INT8 = 1 + CALL "SendPacket-Registry" USING CLIENT-ID REGISTRY-INDEX + END-IF + END-PERFORM CALL "SendPacket-UpdateTags" USING CLIENT-ID *> Send finish configuration diff --git a/src/world.cob b/src/world.cob index 1fddbaf..52ffe60 100644 --- a/src/world.cob +++ b/src/world.cob @@ -33,8 +33,12 @@ PROGRAM-ID. World-AllocateChunk. DATA DIVISION. WORKING-STORAGE SECTION. + *> Constants + 01 C-MINECRAFT-WORLDGEN-BIOME PIC X(50) VALUE "minecraft:worldgen/biome". + 01 C-MINECRAFT-PLAINS PIC X(50) VALUE "minecraft:plains". + *> Temporary variables + 01 BIOME-ID BINARY-LONG UNSIGNED. 01 SECTION-INDEX BINARY-LONG UNSIGNED. - 01 BLOCK-INDEX BINARY-LONG UNSIGNED. *> World data COPY DD-WORLD. LINKAGE SECTION. @@ -56,6 +60,14 @@ PROCEDURE DIVISION USING LK-CHUNK-X LK-CHUNK-Z LK-CHUNK-INDEX. MOVE LK-CHUNK-X TO WORLD-CHUNK-X(LK-CHUNK-INDEX) MOVE LK-CHUNK-Z TO WORLD-CHUNK-Z(LK-CHUNK-INDEX) INITIALIZE WORLD-BLOCK-ENTITIES(LK-CHUNK-INDEX) REPLACING NUMERIC BY -1 + + *> Set all sections to the plains biome + *> TODO: This is a hack. We should have a proper biome system. + CALL "Registries-Get-EntryId" USING C-MINECRAFT-WORLDGEN-BIOME C-MINECRAFT-PLAINS BIOME-ID + PERFORM VARYING SECTION-INDEX FROM 1 BY 1 UNTIL SECTION-INDEX > WORLD-SECTION-COUNT + MOVE BIOME-ID TO WORLD-SECTION-BIOME-ID(LK-CHUNK-INDEX, SECTION-INDEX) + END-PERFORM + GOBACK. END PROGRAM World-AllocateChunk. @@ -1004,6 +1016,7 @@ LINKAGE SECTION. PROCEDURE DIVISION USING LK-FAILURE. MOVE 0 TO SAVE-REQUIRED + MOVE 0 TO LK-FAILURE *> Load the world metadata CALL "World-LoadLevel" USING IO-FAILURE