BlockTypePalette: Load from TSV or original reports' JSON.
This commit is contained in:
parent
7453a9fbe1
commit
2d6f6a574d
File diff suppressed because one or more lines are too long
8586
Server/Protocol/1.13/base.btp.txt
Normal file
8586
Server/Protocol/1.13/base.btp.txt
Normal file
File diff suppressed because it is too large
Load Diff
11275
Server/Protocol/1.14.4/base.btp.txt
Normal file
11275
Server/Protocol/1.14.4/base.btp.txt
Normal file
File diff suppressed because it is too large
Load Diff
554
Server/Protocol/UpgradeBlockTypePalette.txt
Normal file
554
Server/Protocol/UpgradeBlockTypePalette.txt
Normal file
@ -0,0 +1,554 @@
|
|||||||
|
UpgradeBlockTypePalette
|
||||||
|
FileVersion 1
|
||||||
|
CommonPrefix minecraft:
|
||||||
|
|
||||||
|
0 0 air
|
||||||
|
1 0 stone
|
||||||
|
1 1 granite
|
||||||
|
1 2 polished_granite
|
||||||
|
1 3 diorite
|
||||||
|
1 4 polished_diorite
|
||||||
|
1 5 andesite
|
||||||
|
1 6 polished_andesite
|
||||||
|
2 0 grass_block
|
||||||
|
3 0 dirt
|
||||||
|
3 1 coarse_dirt
|
||||||
|
3 2 podzol
|
||||||
|
4 0 cobblestone
|
||||||
|
5 0 oak_planks
|
||||||
|
5 1 spruce_planks
|
||||||
|
5 2 birch_planks
|
||||||
|
5 3 jungle_planks
|
||||||
|
5 4 acacia_planks
|
||||||
|
5 5 dark_oak_planks
|
||||||
|
6 0 oak_sapling
|
||||||
|
6 1 spruce_sapling
|
||||||
|
6 2 birch_sapling
|
||||||
|
6 3 jungle_sapling
|
||||||
|
6 4 acacia_sapling
|
||||||
|
6 5 dark_oak_sapling
|
||||||
|
7 0 bedrock
|
||||||
|
8 0 flowing_water
|
||||||
|
9 0 water
|
||||||
|
10 0 flowing_lava
|
||||||
|
11 0 lava
|
||||||
|
12 0 sand
|
||||||
|
12 1 red_sand
|
||||||
|
13 0 gravel
|
||||||
|
14 0 gold_ore
|
||||||
|
15 0 iron_ore
|
||||||
|
16 0 coal_ore
|
||||||
|
17 0 oak_log
|
||||||
|
17 1 spruce_log
|
||||||
|
17 2 birch_log
|
||||||
|
17 3 jungle_log
|
||||||
|
18 0 oak_leaves
|
||||||
|
18 1 spruce_leaves
|
||||||
|
18 2 birch_leaves
|
||||||
|
18 3 jungle_leaves
|
||||||
|
19 0 sponge
|
||||||
|
19 1 wet_sponge
|
||||||
|
20 0 glass
|
||||||
|
21 0 lapis_ore
|
||||||
|
22 0 lapis_block
|
||||||
|
23 0 dispenser
|
||||||
|
24 0 sandstone
|
||||||
|
24 1 chiseled_sandstone
|
||||||
|
24 2 smooth_sandstone
|
||||||
|
25 0 note_block
|
||||||
|
26 0 bed
|
||||||
|
27 0 powered_rail
|
||||||
|
28 0 detector_rail
|
||||||
|
29 0 sticky_piston
|
||||||
|
30 0 cobweb
|
||||||
|
31 0 dead_bush
|
||||||
|
31 1 grass
|
||||||
|
31 2 fern
|
||||||
|
32 0 dead_bush
|
||||||
|
33 0 piston
|
||||||
|
34 0 piston_head
|
||||||
|
35 0 white_wool
|
||||||
|
35 1 orange_wool
|
||||||
|
35 2 magenta_wool
|
||||||
|
35 3 light_blue_wool
|
||||||
|
35 4 yellow_wool
|
||||||
|
35 5 lime_wool
|
||||||
|
35 6 pink_wool
|
||||||
|
35 7 gray_wool
|
||||||
|
35 8 light_gray_wool
|
||||||
|
35 9 cyan_wool
|
||||||
|
35 10 purple_wool
|
||||||
|
35 11 blue_wool
|
||||||
|
35 12 brown_wool
|
||||||
|
35 13 green_wool
|
||||||
|
35 14 red_wool
|
||||||
|
35 15 black_wool
|
||||||
|
36 0 moving_piston
|
||||||
|
37 0 dandelion
|
||||||
|
38 0 poppy
|
||||||
|
38 1 blue_orchid
|
||||||
|
38 2 allium
|
||||||
|
38 3 azure_bluet
|
||||||
|
38 4 red_tulip
|
||||||
|
38 5 orange_tulip
|
||||||
|
38 6 white_tulip
|
||||||
|
38 7 pink_tulip
|
||||||
|
38 8 oxeye_daisy
|
||||||
|
39 0 brown_mushroom
|
||||||
|
40 0 red_mushroom
|
||||||
|
41 0 gold_block
|
||||||
|
42 0 iron_block
|
||||||
|
43 0 stone_slab
|
||||||
|
43 1 sandstone_slab
|
||||||
|
43 2 oak_slab
|
||||||
|
43 3 cobblestone_slab
|
||||||
|
43 4 brick_slab
|
||||||
|
43 5 stone_brick_slab
|
||||||
|
43 6 nether_brick_slab
|
||||||
|
43 7 smooth_quartz
|
||||||
|
43 8 stone_slab
|
||||||
|
43 9 sandstone_slab
|
||||||
|
44 0 stone_slab
|
||||||
|
44 1 sandstone_slab
|
||||||
|
44 2 oak_slab
|
||||||
|
44 3 cobblestone_slab
|
||||||
|
44 4 brick_slab
|
||||||
|
44 5 stone_brick_slab
|
||||||
|
44 6 nether_brick_slab
|
||||||
|
44 7 quartz_slab
|
||||||
|
44 8 stone_slab type top
|
||||||
|
44 9 sandstone_slab type top
|
||||||
|
44 10 oak_slab
|
||||||
|
44 11 cobblestone_slab type top
|
||||||
|
44 12 brick_slab type top
|
||||||
|
44 13 stone_brick_slab type top
|
||||||
|
44 14 nether_brick_slab type top
|
||||||
|
44 15 quartz_slab type top
|
||||||
|
45 0 bricks
|
||||||
|
46 0 tnt
|
||||||
|
47 0 bookshelf
|
||||||
|
48 0 mossy_cobblestone
|
||||||
|
49 0 obsidian
|
||||||
|
50 0 torch
|
||||||
|
51 0 fire
|
||||||
|
52 0 spawner
|
||||||
|
53 0 oak_stairs
|
||||||
|
53 4 oak_stairs half top
|
||||||
|
54 0 chest
|
||||||
|
55 0 redstone_wire
|
||||||
|
56 0 diamond_ore
|
||||||
|
57 0 diamond_block
|
||||||
|
58 0 crafting_table
|
||||||
|
59 0 wheat
|
||||||
|
59 0 wheat age 0
|
||||||
|
59 1 wheat age 1
|
||||||
|
59 2 wheat age 2
|
||||||
|
59 3 wheat age 3
|
||||||
|
59 4 wheat age 4
|
||||||
|
59 5 wheat age 5
|
||||||
|
59 6 wheat age 6
|
||||||
|
60 0 farmland
|
||||||
|
60 0 farmland moisture 0
|
||||||
|
61 0 furnace
|
||||||
|
62 0 furnace
|
||||||
|
63 0 sign
|
||||||
|
64 0 oak_door
|
||||||
|
65 0 ladder
|
||||||
|
66 0 rail
|
||||||
|
67 0 cobblestone_stairs
|
||||||
|
67 4 cobblestone_stairs half top
|
||||||
|
68 0 wall_sign
|
||||||
|
69 0 lever
|
||||||
|
70 0 stone_pressure_plate
|
||||||
|
71 0 iron_door
|
||||||
|
72 0 oak_pressure_plate
|
||||||
|
73 0 redstone_ore
|
||||||
|
74 0 redstone_ore
|
||||||
|
75 0 redstone_torch
|
||||||
|
76 0 redstone_torch powered true
|
||||||
|
77 0 stone_button
|
||||||
|
78 0 snow
|
||||||
|
79 0 ice
|
||||||
|
80 0 snow_block
|
||||||
|
81 0 cactus
|
||||||
|
82 0 clay
|
||||||
|
83 0 sugar_cane
|
||||||
|
84 0 jukebox
|
||||||
|
85 0 oak_fence
|
||||||
|
86 0 pumpkin
|
||||||
|
87 0 netherrack
|
||||||
|
88 0 soul_sand
|
||||||
|
89 0 glowstone
|
||||||
|
90 0 nether_portal
|
||||||
|
91 0 jack_o_lantern
|
||||||
|
92 0 cake
|
||||||
|
93 0 repeater
|
||||||
|
94 0 repeater powered true
|
||||||
|
95 0 white_stained_glass
|
||||||
|
95 1 orange_stained_glass
|
||||||
|
95 2 magenta_stained_glass
|
||||||
|
95 3 light_blue_stained_glass
|
||||||
|
95 4 yellow_stained_glass
|
||||||
|
95 5 lime_stained_glass
|
||||||
|
95 6 pink_stained_glass
|
||||||
|
95 7 gray_stained_glass
|
||||||
|
95 8 light_gray_stained_glass
|
||||||
|
95 9 cyan_stained_glass
|
||||||
|
95 10 purple_stained_glass
|
||||||
|
95 11 blue_stained_glass
|
||||||
|
95 12 brown_stained_glass
|
||||||
|
95 13 green_stained_glass
|
||||||
|
95 14 red_stained_glass
|
||||||
|
95 15 black_stained_glass
|
||||||
|
96 0 oak_trapdoor
|
||||||
|
97 0 infested_stone
|
||||||
|
97 1 infested_cobblestone
|
||||||
|
97 2 infested_stone_bricks
|
||||||
|
97 3 infested_mossy_stone_bricks
|
||||||
|
97 4 infested_cracked_stone_bricks
|
||||||
|
97 5 infested_chiseled_stone_bricks
|
||||||
|
98 0 stone_bricks
|
||||||
|
98 1 mossy_stone_bricks
|
||||||
|
98 2 cracked_stone_bricks
|
||||||
|
98 3 chiseled_stone_bricks
|
||||||
|
99 0 brown_mushroom_block up false
|
||||||
|
99 0 brown_mushroom_block
|
||||||
|
99 1 brown_mushroom_block
|
||||||
|
99 2 brown_mushroom_block
|
||||||
|
99 3 brown_mushroom_block
|
||||||
|
99 4 brown_mushroom_block
|
||||||
|
99 5 brown_mushroom_block
|
||||||
|
99 6 brown_mushroom_block
|
||||||
|
99 7 brown_mushroom_block
|
||||||
|
99 8 brown_mushroom_block
|
||||||
|
99 9 brown_mushroom_block
|
||||||
|
99 10 mushroom_stem up false
|
||||||
|
99 14 brown_mushroom_block
|
||||||
|
99 15 mushroom_stem
|
||||||
|
100 0 red_mushroom_block
|
||||||
|
100 0 red_mushroom_block up false
|
||||||
|
100 1 red_mushroom_block
|
||||||
|
100 2 red_mushroom_block
|
||||||
|
100 3 red_mushroom_block
|
||||||
|
100 4 red_mushroom_block
|
||||||
|
100 5 red_mushroom_block
|
||||||
|
100 6 red_mushroom_block
|
||||||
|
100 7 red_mushroom_block
|
||||||
|
100 8 red_mushroom_block
|
||||||
|
100 9 red_mushroom_block
|
||||||
|
100 10 mushroom_stem up false
|
||||||
|
100 14 red_mushroom_block
|
||||||
|
100 15 mushroom_stem
|
||||||
|
101 0 iron_bars
|
||||||
|
102 0 glass_pane
|
||||||
|
103 0 melon
|
||||||
|
104 0 pumpkin_stem
|
||||||
|
105 0 melon_stem
|
||||||
|
106 0 vine
|
||||||
|
107 0 oak_fence_gate
|
||||||
|
108 0 brick_stairs
|
||||||
|
108 4 brick_stairs half top
|
||||||
|
109 0 stone_brick_stairs
|
||||||
|
109 4 stone_brick_stairs half top
|
||||||
|
110 0 mycelium
|
||||||
|
111 0 lily_pad
|
||||||
|
112 0 nether_bricks
|
||||||
|
113 0 nether_brick_fence
|
||||||
|
114 0 nether_brick_stairs
|
||||||
|
114 4 netherbrick_stairs half top
|
||||||
|
115 0 nether_wart
|
||||||
|
115 0 nether_wart age 0
|
||||||
|
115 3 nether_wart age 3
|
||||||
|
116 0 enchanting_table
|
||||||
|
117 0 brewing_stand
|
||||||
|
118 0 cauldron
|
||||||
|
119 0 end_portal
|
||||||
|
120 0 end_portal_frame
|
||||||
|
120 4 end_portal_frame eye true
|
||||||
|
121 0 end_stone
|
||||||
|
122 0 dragon_egg
|
||||||
|
123 0 redstone_lamp
|
||||||
|
124 0 redstone_lamp lit on
|
||||||
|
125 0 oak_slab
|
||||||
|
125 1 spruce_slab
|
||||||
|
125 2 birch_slab
|
||||||
|
125 3 jungle_slab
|
||||||
|
125 4 acacia_slab
|
||||||
|
125 5 dark_oak_slab
|
||||||
|
126 0 oak_slab
|
||||||
|
126 1 spruce_slab
|
||||||
|
126 2 birch_slab
|
||||||
|
126 3 jungle_slab
|
||||||
|
126 4 acacia_slab
|
||||||
|
126 5 dark_oak_slab
|
||||||
|
126 8 oak_slab type top
|
||||||
|
126 9 spruce_slab type top
|
||||||
|
126 10 birch_slab type top
|
||||||
|
126 11 jungle_slab type top
|
||||||
|
126 12 acacia_slab type top
|
||||||
|
126 13 dark_oak_slab type top
|
||||||
|
127 0 cocoa
|
||||||
|
127 8 cocoa
|
||||||
|
128 0 sandstone_stairs
|
||||||
|
128 4 sandstone_stairs half top
|
||||||
|
129 0 emerald_ore
|
||||||
|
130 0 ender_chest
|
||||||
|
131 0 tripwire_hook
|
||||||
|
132 0 tripwire
|
||||||
|
133 0 emerald_block
|
||||||
|
134 0 spruce_stairs
|
||||||
|
134 4 spruce_stairs half top
|
||||||
|
135 0 birch_stairs
|
||||||
|
135 4 birch_stairs half top
|
||||||
|
136 0 jungle_stairs
|
||||||
|
136 4 jungle_stairs half top
|
||||||
|
137 0 command_block
|
||||||
|
138 0 beacon
|
||||||
|
139 0 cobblestone_wall
|
||||||
|
139 1 mossy_cobblestone_wall
|
||||||
|
140 0 flower_pot
|
||||||
|
140 1 potted_poppy
|
||||||
|
140 2 potted_dandelion
|
||||||
|
140 3 potted_oak_sapling
|
||||||
|
140 4 potted_spruce_sapling
|
||||||
|
140 5 potted_birch_sapling
|
||||||
|
140 6 potted_jungle_sapling
|
||||||
|
140 7 potted_red_mushroom
|
||||||
|
140 8 potted_brown_mushroom
|
||||||
|
140 9 potted_cactus
|
||||||
|
140 10 potted_dead_bush
|
||||||
|
140 11 potted_fern
|
||||||
|
140 12 potted_acacia_sapling
|
||||||
|
140 13 potted_dark_oak_sapling
|
||||||
|
141 0 carrots
|
||||||
|
141 0 carrots age 0
|
||||||
|
141 1 carrots age 1
|
||||||
|
141 2 carrots age 2
|
||||||
|
142 0 potatoes age 0
|
||||||
|
142 0 potatoes
|
||||||
|
142 1 potatoes age 1
|
||||||
|
142 2 potatoes age 2
|
||||||
|
142 3 potatoes age 3
|
||||||
|
142 4 potatoes age 4
|
||||||
|
142 5 potatoes age 5
|
||||||
|
142 6 potatoes age 6
|
||||||
|
143 0 oak_button
|
||||||
|
144 0 mob_head
|
||||||
|
145 0 anvil
|
||||||
|
145 4 chipped_anvil
|
||||||
|
145 8 damaged_anvil
|
||||||
|
146 0 trapped_chest
|
||||||
|
147 0 light_weighted_pressure_plate
|
||||||
|
148 0 heavy_weighted_pressure_plate
|
||||||
|
149 0 comparator
|
||||||
|
150 0 comparator powered true
|
||||||
|
151 0 daylight_detector
|
||||||
|
152 0 redstone_block
|
||||||
|
153 0 nether_quartz_ore
|
||||||
|
154 0 hopper
|
||||||
|
155 0 quartz_block
|
||||||
|
155 1 chiseled_quartz_block
|
||||||
|
155 2 quartz_pillar
|
||||||
|
155 3 quartz_pillar
|
||||||
|
155 4 quartz_pillar
|
||||||
|
156 0 quartz_stairs
|
||||||
|
156 4 quartz_stairs half top
|
||||||
|
157 0 activator_rail
|
||||||
|
158 0 dropper
|
||||||
|
159 0 white_terracotta
|
||||||
|
159 1 orange_terracotta
|
||||||
|
159 2 magenta_terracotta
|
||||||
|
159 3 light_blue_terracotta
|
||||||
|
159 4 yellow_terracotta
|
||||||
|
159 5 lime_terracotta
|
||||||
|
159 6 pink_terracotta
|
||||||
|
159 7 gray_terracotta
|
||||||
|
159 8 light_gray_terracotta
|
||||||
|
159 9 cyan_terracotta
|
||||||
|
159 10 purple_terracotta
|
||||||
|
159 11 blue_terracotta
|
||||||
|
159 12 brown_terracotta
|
||||||
|
159 13 green_terracotta
|
||||||
|
159 14 red_terracotta
|
||||||
|
159 15 black_terracotta
|
||||||
|
160 0 white_stained_glass_pane
|
||||||
|
160 1 orange_stained_glass_pane
|
||||||
|
160 2 magenta_stained_glass_pane
|
||||||
|
160 3 light_blue_stained_glass_pane
|
||||||
|
160 4 yellow_stained_glass_pane
|
||||||
|
160 5 lime_stained_glass_pane
|
||||||
|
160 6 pink_stained_glass_pane
|
||||||
|
160 7 gray_stained_glass_pane
|
||||||
|
160 8 light_gray_stained_glass_pane
|
||||||
|
160 9 cyan_stained_glass_pane
|
||||||
|
160 10 purple_stained_glass_pane
|
||||||
|
160 11 blue_stained_glass_pane
|
||||||
|
160 12 brown_stained_glass_pane
|
||||||
|
160 13 green_stained_glass_pane
|
||||||
|
160 14 red_stained_glass_pane
|
||||||
|
160 15 black_stained_glass_pane
|
||||||
|
161 0 acacia_leaves
|
||||||
|
161 1 dark_oak_leaves
|
||||||
|
162 0 acacia_log
|
||||||
|
162 1 dark_oak_log
|
||||||
|
163 0 acacia_stairs
|
||||||
|
163 4 acacia_stairs half top
|
||||||
|
164 0 dark_oak_stairs
|
||||||
|
164 4 dark_oak_stairs half top
|
||||||
|
165 0 slime_block
|
||||||
|
166 0 barrier
|
||||||
|
167 0 iron_trapdoor
|
||||||
|
168 0 prismarine
|
||||||
|
168 1 prismarine_bricks
|
||||||
|
168 2 dark_prismarine
|
||||||
|
169 0 sea_lantern
|
||||||
|
170 0 hay_block
|
||||||
|
171 0 white_carpet
|
||||||
|
171 1 orange_carpet
|
||||||
|
171 2 magenta_carpet
|
||||||
|
171 3 light_blue_carpet
|
||||||
|
171 4 yellow_carpet
|
||||||
|
171 5 lime_carpet
|
||||||
|
171 6 pink_carpet
|
||||||
|
171 7 gray_carpet
|
||||||
|
171 8 light_gray_carpet
|
||||||
|
171 9 cyan_carpet
|
||||||
|
171 10 purple_carpet
|
||||||
|
171 11 blue_carpet
|
||||||
|
171 12 brown_carpet
|
||||||
|
171 13 green_carpet
|
||||||
|
171 14 red_carpet
|
||||||
|
171 15 black_carpet
|
||||||
|
172 0 terracotta
|
||||||
|
173 0 coal_block
|
||||||
|
174 0 packed_ice
|
||||||
|
175 0 sunflower
|
||||||
|
175 1 lilac
|
||||||
|
175 2 tall_grass
|
||||||
|
175 3 large_fern
|
||||||
|
175 4 rose_bush
|
||||||
|
175 5 peony
|
||||||
|
175 8 large_flower_(top_part)
|
||||||
|
175 10 large_flower_(top_part)
|
||||||
|
176 0 white_banner
|
||||||
|
177 0 white_wall_banner
|
||||||
|
178 0 daylight_detector
|
||||||
|
179 0 red_sandstone
|
||||||
|
179 1 chiseled_red_sandstone
|
||||||
|
179 2 smooth_red_sandstone
|
||||||
|
180 0 red_sandstone_stairs
|
||||||
|
180 4 red_sandstone_stairs half top
|
||||||
|
181 0 red_sandstone_slab
|
||||||
|
181 8 red_sandstone_slab
|
||||||
|
182 0 red_sandstone_slab
|
||||||
|
182 8 red_sandstone_slab type top
|
||||||
|
183 0 spruce_fence_gate
|
||||||
|
184 0 birch_fence_gate
|
||||||
|
185 0 jungle_fence_gate
|
||||||
|
186 0 dark_oak_fence_gate
|
||||||
|
187 0 acacia_fence_gate
|
||||||
|
188 0 spruce_fence
|
||||||
|
189 0 birch_fence
|
||||||
|
190 0 jungle_fence
|
||||||
|
191 0 dark_oak_fence
|
||||||
|
192 0 acacia_fence
|
||||||
|
193 0 spruce_door
|
||||||
|
194 0 birch_door
|
||||||
|
195 0 jungle_door
|
||||||
|
196 0 acacia_door
|
||||||
|
197 0 dark_oak_door
|
||||||
|
198 0 end_rod
|
||||||
|
199 0 chorus_plant
|
||||||
|
200 0 chorus_flower
|
||||||
|
200 5 chorus_flower age 5
|
||||||
|
201 0 purpur_block
|
||||||
|
202 0 purpur_pillar
|
||||||
|
203 0 purpur_stairs
|
||||||
|
203 4 purpur_stairs half top
|
||||||
|
204 0 purpur_slab
|
||||||
|
205 0 purpur_slab
|
||||||
|
205 8 purpur_slab type top
|
||||||
|
206 0 end_stone_bricks
|
||||||
|
207 0 beetroots age 0
|
||||||
|
207 0 beetroots
|
||||||
|
207 1 beetroots age 1
|
||||||
|
207 2 beetroots age 2
|
||||||
|
208 0 grass_path
|
||||||
|
209 0 end_gateway
|
||||||
|
210 0 repeating_command_block
|
||||||
|
211 0 chain_command_block
|
||||||
|
212 0 frosted_ice
|
||||||
|
213 0 magma_block
|
||||||
|
214 0 nether_wart_block
|
||||||
|
215 0 red_nether_bricks
|
||||||
|
216 0 bone_block
|
||||||
|
217 0 structure_void
|
||||||
|
218 0 observer
|
||||||
|
219 0 white_shulker_box
|
||||||
|
220 0 orange_shulker_box
|
||||||
|
221 0 magenta_shulker_box
|
||||||
|
222 0 light_blue_shulker_box
|
||||||
|
223 0 yellow_shulker_box
|
||||||
|
224 0 lime_shulker_box
|
||||||
|
225 0 pink_shulker_box
|
||||||
|
226 0 gray_shulker_box
|
||||||
|
227 0 light_gray_shulker_box
|
||||||
|
228 0 cyan_shulker_box
|
||||||
|
229 0 purple_shulker_box
|
||||||
|
230 0 blue_shulker_box
|
||||||
|
231 0 brown_shulker_box
|
||||||
|
232 0 green_shulker_box
|
||||||
|
233 0 red_shulker_box
|
||||||
|
234 0 black_shulker_box
|
||||||
|
235 0 white_glazed_terracotta
|
||||||
|
236 0 orange_glazed_terracotta
|
||||||
|
237 0 magenta_glazed_terracotta
|
||||||
|
238 0 light_blue_glazed_terracotta
|
||||||
|
239 0 yellow_glazed_terracotta
|
||||||
|
240 0 lime_glazed_terracotta
|
||||||
|
241 0 pink_glazed_terracotta
|
||||||
|
242 0 gray_glazed_terracotta
|
||||||
|
243 0 light_gray_glazed_terracotta
|
||||||
|
244 0 cyan_glazed_terracotta
|
||||||
|
245 0 purple_glazed_terracotta
|
||||||
|
246 0 blue_glazed_terracotta
|
||||||
|
247 0 brown_glazed_terracotta
|
||||||
|
248 0 green_glazed_terracotta
|
||||||
|
249 0 red_glazed_terracotta
|
||||||
|
250 0 black_glazed_terracotta
|
||||||
|
251 0 white_concrete
|
||||||
|
251 1 orange_concrete
|
||||||
|
251 2 magenta_concrete
|
||||||
|
251 3 light_blue_concrete
|
||||||
|
251 4 yellow_concrete
|
||||||
|
251 5 lime_concrete
|
||||||
|
251 6 pink_concrete
|
||||||
|
251 7 gray_concrete
|
||||||
|
251 8 light_gray_concrete
|
||||||
|
251 9 cyan_concrete
|
||||||
|
251 10 purple_concrete
|
||||||
|
251 11 blue_concrete
|
||||||
|
251 12 brown_concrete
|
||||||
|
251 13 green_concrete
|
||||||
|
251 14 red_concrete
|
||||||
|
251 15 black_concrete
|
||||||
|
252 0 white_concrete_powder
|
||||||
|
252 1 orange_concrete_powder
|
||||||
|
252 2 magenta_concrete_powder
|
||||||
|
252 3 light_blue_concrete_powder
|
||||||
|
252 4 yellow_concrete_powder
|
||||||
|
252 5 lime_concrete_powder
|
||||||
|
252 6 pink_concrete_powder
|
||||||
|
252 7 gray_concrete_powder
|
||||||
|
252 8 light_gray_concrete_powder
|
||||||
|
252 9 cyan_concrete_powder
|
||||||
|
252 10 purple_concrete_powder
|
||||||
|
252 11 blue_concrete_powder
|
||||||
|
252 12 brown_concrete_powder
|
||||||
|
252 13 green_concrete_powder
|
||||||
|
252 14 red_concrete_powder
|
||||||
|
252 15 black_concrete_powder
|
||||||
|
255 0 structure_block
|
||||||
|
255 1 structure_block
|
||||||
|
255 2 structure_block
|
||||||
|
255 3 structure_block
|
5
Tools/BlockTypePaletteGenerator/.gitignore
vendored
Normal file
5
Tools/BlockTypePaletteGenerator/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Ignore the scripts' outputs:
|
||||||
|
*.json
|
||||||
|
*.btp.txt
|
||||||
|
UpgradeBlockTypePalette.txt
|
||||||
|
|
@ -1,14 +1,33 @@
|
|||||||
-- lib/lunajson/src/ is not in default Lua package paths
|
-- Generator.lua
|
||||||
|
|
||||||
|
--[[
|
||||||
|
Crafts an intermediate block palette format to be read by Cuberite.
|
||||||
|
It processes the blocks.json report file (https://wiki.vg/Data_Generators)
|
||||||
|
into a file that can be loaded into a BlockTypePalette (and is to be stored
|
||||||
|
as Server/Protocol/<version>/base.btp.txt).
|
||||||
|
|
||||||
|
The output format is the regular TSV BlockTypePalette, described in the
|
||||||
|
$/src/BlockTypePalette.h file.
|
||||||
|
--]]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- Allow Lua to load libraries in our subfolder:
|
||||||
package.path = 'lib/lunajson/src/?.lua;' .. package.path;
|
package.path = 'lib/lunajson/src/?.lua;' .. package.path;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Prints usage instructions to stdout.
|
--- Prints usage instructions to stdout.
|
||||||
-- If the optional `message` is passed, output is prepended by message _and_
|
-- If the optional `aMessage` is passed, output is prepended by message _and_
|
||||||
-- redirected to stderr.
|
-- redirected to stderr.
|
||||||
function usage(message)
|
local function usage(aMessage)
|
||||||
if message then
|
if aMessage then
|
||||||
io.output(io.stderr);
|
io.output(io.stderr);
|
||||||
io.write(message, "\n\n");
|
io.write(aMessage, "\n\n");
|
||||||
end
|
end
|
||||||
io.write(
|
io.write(
|
||||||
"Usage: lua Generator.lua INPUTFILE OUTPUTFILE\n"..
|
"Usage: lua Generator.lua INPUTFILE OUTPUTFILE\n"..
|
||||||
@ -22,70 +41,125 @@ function usage(message)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Test whether the script is run in a path where it can load it's libraries
|
|
||||||
if not pcall(function() require("lunajson.decoder") end) then
|
|
||||||
usage("Could not load required libraries, please run `Generator.lua` "..
|
|
||||||
"within its directory and make sure to run `git submodule update`.");
|
--- Parses the JSON registry into a Lua table
|
||||||
|
--[[ The returned array-table has the following format:
|
||||||
|
{
|
||||||
|
{ id = 1, blockTypeName = "minecraft:stone", properties = {key = value, ...} },
|
||||||
|
...
|
||||||
|
}
|
||||||
|
--]]
|
||||||
|
local function parseRegistry(aBlockRegistryJsonStr)
|
||||||
|
assert(type(aBlockRegistryJsonStr) == "string")
|
||||||
|
|
||||||
|
local lj = require("lunajson")
|
||||||
|
local input = lj.decode(aBlockRegistryJsonStr)
|
||||||
|
local registry = {}
|
||||||
|
local idx = 1
|
||||||
|
for blockTypeName, blockData in pairs(input) do
|
||||||
|
for _, state in pairs(blockData.states) do
|
||||||
|
registry[idx] = {
|
||||||
|
id = state.id,
|
||||||
|
blockTypeName = blockTypeName,
|
||||||
|
properties = state.properties,
|
||||||
|
}
|
||||||
|
idx = idx + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return registry
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Serializes the properties from the JSON / array table format into a single output string
|
||||||
|
-- Concatenates all properties with \t as the delimiting character
|
||||||
|
local function serializeProperties(aProperties)
|
||||||
|
local res = {}
|
||||||
|
local idx = 1
|
||||||
|
for k, v in pairs(aProperties or {}) do
|
||||||
|
res[idx] = k
|
||||||
|
res[idx + 1] = v
|
||||||
|
idx = idx + 2
|
||||||
|
end
|
||||||
|
return table.concat(res, "\t")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Returns the prefix that is common for all block type names in the registry
|
||||||
|
-- aRegistry is the parsed registry, as returned from parseRegistry()
|
||||||
|
local function findCommonPrefix(aRegistryTable)
|
||||||
|
local prefix = aRegistryTable[1].blockTypeName
|
||||||
|
local len = string.len(prefix)
|
||||||
|
local sub = string.sub
|
||||||
|
for _, block in ipairs(aRegistryTable) do
|
||||||
|
while (sub(block.blockTypeName, 1, len) ~= prefix) do
|
||||||
|
len = len - 1
|
||||||
|
if (len == 0) then
|
||||||
|
return ""
|
||||||
|
end
|
||||||
|
prefix = sub(prefix, 1, len)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return prefix
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- Test whether the script is run in a path where it can load it's libraries
|
||||||
|
if not(pcall(function() require("lunajson") end)) then
|
||||||
|
usage(
|
||||||
|
"Could not load required libraries, please run `Generator.lua` " ..
|
||||||
|
"within its directory and make sure to run `git submodule update`."
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
-- Check/Prepare CLI arguments
|
-- Check/Prepare CLI arguments
|
||||||
local inpath, outpath = ...;
|
local inpath, outpath = ...;
|
||||||
io.input(io.stdin);
|
inpath = inpath or "blocks.json"
|
||||||
io.output(io.stdout);
|
outpath = outpath or "base.btp.txt"
|
||||||
|
if (inpath ~= "-") then
|
||||||
if select("#", ...) ~= 2 then
|
local handle, err = io.open(inpath, "r")
|
||||||
usage("Incorrect number of arguments.");
|
io.input(handle or usage(err))
|
||||||
|
end
|
||||||
|
if (outpath ~= "-") then
|
||||||
|
local handle, err = io.open(outpath, "w")
|
||||||
|
io.output(handle or usage(err))
|
||||||
end
|
end
|
||||||
|
|
||||||
if inpath ~= "-" then
|
-- Parse the registry:
|
||||||
local handle, err = io.open(inpath, "r");
|
local registry = parseRegistry(io.input():read("*a"))
|
||||||
io.input(handle or usage(err));
|
local commonPrefix = findCommonPrefix(registry)
|
||||||
end
|
|
||||||
|
|
||||||
if outpath ~= "-" then
|
-- Sort the entries:
|
||||||
local handle, err = io.open(outpath, "w");
|
table.sort(registry,
|
||||||
io.output(handle or usage(err));
|
function (entry1, entry2)
|
||||||
end
|
return (entry1.id < entry2.id)
|
||||||
|
|
||||||
|
|
||||||
-- Main program starts here
|
|
||||||
local decode = (require("lunajson.decoder"))();
|
|
||||||
local encode = (require("lunajson.encoder"))();
|
|
||||||
|
|
||||||
local input = decode(io.input():read("*a"));
|
|
||||||
local registry = {};
|
|
||||||
local max_id = -1;
|
|
||||||
|
|
||||||
|
|
||||||
for blockname, blockdata in pairs(input) do
|
|
||||||
for i = 1, #(blockdata.states or {}) do
|
|
||||||
local state = blockdata.states[i];
|
|
||||||
assert(registry[state.id + 1] == nil, "Ensure no duplicate IDs");
|
|
||||||
|
|
||||||
-- needed in the end to verify we got no holes in the array:
|
|
||||||
max_id = math.max(max_id, state.id);
|
|
||||||
|
|
||||||
registry[state.id + 1] = {
|
|
||||||
id = assert(state.id, "id is required."),
|
|
||||||
name = assert(blockname, "Block type name is required."),
|
|
||||||
-- default = state.default or nil, -- may need this later
|
|
||||||
props = state.properties,
|
|
||||||
};
|
|
||||||
end
|
end
|
||||||
|
)
|
||||||
|
|
||||||
|
-- Write out the output format:
|
||||||
|
io.write("BlockTypePalette\n")
|
||||||
|
io.write("FileVersion\t1\n")
|
||||||
|
io.write("CommonPrefix\t", commonPrefix, "\n")
|
||||||
|
io.write("\n")
|
||||||
|
local prefixLen = string.len(commonPrefix) + 1
|
||||||
|
for _, entry in ipairs(registry) do
|
||||||
|
local props = serializeProperties(entry.properties)
|
||||||
|
if (props ~= "") then
|
||||||
|
props = "\t" .. props
|
||||||
|
end
|
||||||
|
io.write(
|
||||||
|
entry.id, "\t",
|
||||||
|
string.sub(entry.blockTypeName, prefixLen),
|
||||||
|
props, "\n"
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- The following assertion is not necessary by the current spec, but is required
|
|
||||||
-- by how lunajson distinguishes objects from arrays. Also if this fails, it is
|
|
||||||
-- _very_ likely that the input file is faulty.
|
|
||||||
assert(#registry == max_id + 1, "Ensure that registry has contiguous keys");
|
|
||||||
|
|
||||||
local out = {
|
|
||||||
Metadata = {
|
|
||||||
ProtocolBlockTypePaletteVersion = 1
|
|
||||||
},
|
|
||||||
Palette = registry
|
|
||||||
};
|
|
||||||
|
|
||||||
io.write(encode(out), "\n");
|
|
||||||
|
@ -1,63 +0,0 @@
|
|||||||
This generator crafts an intermediate index format to be read by cuberite
|
|
||||||
|
|
||||||
# Running
|
|
||||||
|
|
||||||
Run `lua ./Generator.lua`, pass `blocks.json` as first argument to the script
|
|
||||||
and the desired output location as 2nd argument.
|
|
||||||
|
|
||||||
Make sure to run the Generator from within its directory (`cd` into the path
|
|
||||||
where `Generator.lua` is.)
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
```bash
|
|
||||||
SERVER=/path/to/server.jar
|
|
||||||
java -cp "$SERVER" net.minecraft.data.Main --reports &&
|
|
||||||
lua Generator.lua \
|
|
||||||
generated/reports/blocks.json \
|
|
||||||
../../Server/Protocol/1.13/ProtocolBlockTypePalette.json
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
SERVER=/path/to/server.jar
|
|
||||||
java -cp "$SERVER" net.minecraft.data.Main --reports &&
|
|
||||||
lua Generator.lua - -\
|
|
||||||
< generated/reports/blocks.json \
|
|
||||||
> ../Server/Protocol/1.13/ProtocolBlockTypePalette.json
|
|
||||||
```
|
|
||||||
|
|
||||||
## Output format
|
|
||||||
|
|
||||||
The Format is a `JSON` document containing an object with at least two keys at
|
|
||||||
the top level: `Metadata` and `Palette`.
|
|
||||||
|
|
||||||
`Metadata` contains document metadata, namely a key `"ProtocolBlockType": 1`.
|
|
||||||
|
|
||||||
`Palette` contains an array of objects. Each of these objects has at least the
|
|
||||||
keys `id`, `name` and an optional `props` key that contains the individual
|
|
||||||
properties of the current state. These properties are a KV dict of pure strings.
|
|
||||||
|
|
||||||
The order of the array or object elements is not significant. `id` is unique.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"Metadata": {
|
|
||||||
"ProtocolBlockType": 1
|
|
||||||
},
|
|
||||||
"Palette": [{
|
|
||||||
"id": 0,
|
|
||||||
"name": "minecraft:air"
|
|
||||||
}, {
|
|
||||||
"id": 1,
|
|
||||||
"name": "minecraft:stone"
|
|
||||||
}, {
|
|
||||||
"id": 221,
|
|
||||||
"name": "minecraft:dark_oak_leaves",
|
|
||||||
"props": {
|
|
||||||
"persistent": "false",
|
|
||||||
"distance": "4"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
223
Tools/BlockTypePaletteGenerator/UpgradeGenerator.lua
Normal file
223
Tools/BlockTypePaletteGenerator/UpgradeGenerator.lua
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
-- UpgradeGenerator.lua
|
||||||
|
|
||||||
|
--[[ Creates the UpgradeBlockTypePalette out of JSON data of the Minutor project
|
||||||
|
(https://github.com/mrkite/minutor/blob/master/definitions/vanilla_ids.json
|
||||||
|
|
||||||
|
Parses the JSON into memory, then walks each block's "id" member and possibly
|
||||||
|
the "variants" sub-member to read the block types. The name is either present as "flatname",
|
||||||
|
or is synthesized from the internal Minutor "name" by lowercasing and replacing spaces
|
||||||
|
with underscores.
|
||||||
|
|
||||||
|
Expects two parameters, the input file and output file; either can be replaced by
|
||||||
|
a "-" to use stdin / stdout instead. If not given, the input file defaults to
|
||||||
|
"vanilla_ids.json" and the output file defaults to "UpgradeBlockTypePalette.txt"
|
||||||
|
|
||||||
|
The output format is the upgrade TSV BlockTypePalette, described in the
|
||||||
|
$/src/BlockTypePalette.h file.
|
||||||
|
--]]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- Allow Lua to load libraries in our subfolder:
|
||||||
|
package.path = 'lib/lunajson/src/?.lua;' .. package.path;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Splits the full flat name into flat name and properties
|
||||||
|
-- "minecraft:carrots:age:0" -> "minecraft:carrots", {age = 0}
|
||||||
|
local function splitFlatName(aFullFlatName)
|
||||||
|
local props = {}
|
||||||
|
local numParts = 0
|
||||||
|
local flatName = ""
|
||||||
|
local propKey = ""
|
||||||
|
aFullFlatName:gsub("([^:]+)",
|
||||||
|
function (aPart)
|
||||||
|
if (numParts == 0) then
|
||||||
|
flatName = aPart
|
||||||
|
elseif (numParts == 1) then
|
||||||
|
flatName = flatName .. ":" .. aPart
|
||||||
|
elseif (numParts % 2 == 0) then
|
||||||
|
propKey = aPart
|
||||||
|
else
|
||||||
|
props[propKey] = aPart
|
||||||
|
end
|
||||||
|
numParts = numParts + 1
|
||||||
|
end
|
||||||
|
)
|
||||||
|
return flatName, props
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Returns the minecraft block name, created from the flat name if present, or synthesized
|
||||||
|
-- from the Minutor name
|
||||||
|
-- If the flat name contains encoded block properties, it returns those properties as a dict-table
|
||||||
|
-- in the second return value
|
||||||
|
local function processBlockName(aFlatName, aMinutorName)
|
||||||
|
if (aFlatName) then
|
||||||
|
assert(type(aFlatName) == "string")
|
||||||
|
return splitFlatName(aFlatName)
|
||||||
|
end
|
||||||
|
if not(type(aMinutorName) == "string") then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
return "minecraft:" .. (aMinutorName:lower():gsub(" ", "_")), {}
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Serializes the properties from the JSON / array table format into a single output string
|
||||||
|
-- Concatenates all properties with \t as the delimiting character
|
||||||
|
local function serializeProperties(aProperties)
|
||||||
|
local res = {}
|
||||||
|
local idx = 1
|
||||||
|
for k, v in pairs(aProperties or {}) do
|
||||||
|
res[idx] = k
|
||||||
|
res[idx + 1] = v
|
||||||
|
idx = idx + 2
|
||||||
|
end
|
||||||
|
return table.concat(res, "\t")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Parses the vanilla_ids.json into a common registry format
|
||||||
|
-- The returned registry is an array-table of
|
||||||
|
-- {blockType = 1, blockMeta = 2, blockTypeName = "name", properties = {key = value, ...}}
|
||||||
|
local function parseRegistry(aJsonString)
|
||||||
|
assert(type(aJsonString) == "string")
|
||||||
|
|
||||||
|
-- Parse the JSON:
|
||||||
|
local lj = require("lunajson")
|
||||||
|
local input = lj.decode(aJsonString)
|
||||||
|
if (not(input) or (input["type"] ~= "block") or not(input["data"])) then
|
||||||
|
error("The input file doesn't contain vanilla IDs.")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Create the registry:
|
||||||
|
local registry = {}
|
||||||
|
local idx = 1
|
||||||
|
for _, entry in pairs(input["data"]) do
|
||||||
|
local id = entry["id"]
|
||||||
|
local parentBlockTypeName, props = processBlockName(entry["flatname"], entry["name"])
|
||||||
|
registry[idx] =
|
||||||
|
{
|
||||||
|
blockType = id,
|
||||||
|
blockMeta = 0,
|
||||||
|
blockTypeName = parentBlockTypeName,
|
||||||
|
properties = props,
|
||||||
|
}
|
||||||
|
idx = idx + 1
|
||||||
|
for _, variant in pairs(entry["variants"] or {}) do
|
||||||
|
local blockTypeName, props = processBlockName(variant["flatname"], variant["name"])
|
||||||
|
if not(blockTypeName) then
|
||||||
|
-- Some blocks don't have all their variants named ("brown mushroom block"), use the parent name in such a case
|
||||||
|
blockTypeName = parentBlockTypeName
|
||||||
|
end
|
||||||
|
registry[idx] =
|
||||||
|
{
|
||||||
|
blockType = id,
|
||||||
|
blockMeta = variant["data"],
|
||||||
|
blockTypeName = blockTypeName,
|
||||||
|
properties = props,
|
||||||
|
}
|
||||||
|
idx = idx + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return registry
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Returns the prefix that is common for all block type names in the registry
|
||||||
|
-- aRegistry is the parsed registry, as returned from parseRegistry()
|
||||||
|
local function findCommonPrefix(aRegistryTable)
|
||||||
|
local prefix = aRegistryTable[1].blockTypeName
|
||||||
|
local len = string.len(prefix)
|
||||||
|
local sub = string.sub
|
||||||
|
for _, block in ipairs(aRegistryTable) do
|
||||||
|
while (sub(block.blockTypeName, 1, len) ~= prefix) do
|
||||||
|
len = len - 1
|
||||||
|
if (len == 0) then
|
||||||
|
return ""
|
||||||
|
end
|
||||||
|
prefix = sub(prefix, 1, len)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return prefix
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- Test whether the script is run in a path where it can load it's libraries
|
||||||
|
if not(pcall(function() require("lunajson") end)) then
|
||||||
|
error(
|
||||||
|
"Could not load required libraries, please run `UpgradeGenerator.lua` " ..
|
||||||
|
"within its directory and make sure to run `git submodule update`."
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check/Prepare CLI arguments
|
||||||
|
local inpath, outpath = ...;
|
||||||
|
inpath = inpath or "vanilla_ids.json"
|
||||||
|
outpath = outpath or "UpgradeBlockTypePalette.txt"
|
||||||
|
if (inpath ~= "-") then
|
||||||
|
local handle, err = io.open(inpath, "r")
|
||||||
|
io.input(handle or usage(err))
|
||||||
|
end
|
||||||
|
if (outpath ~= "-") then
|
||||||
|
local handle, err = io.open(outpath, "w")
|
||||||
|
io.output(handle or usage(err))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Parse the registry:
|
||||||
|
local registry = parseRegistry(io.input():read("*a"))
|
||||||
|
local commonPrefix = findCommonPrefix(registry)
|
||||||
|
|
||||||
|
-- Sort the entries:
|
||||||
|
table.sort(registry,
|
||||||
|
function (entry1, entry2)
|
||||||
|
if (entry1.blockType < entry2.blockType) then
|
||||||
|
return true
|
||||||
|
elseif (entry1.blockType > entry2.blockType) then
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
return (entry1.blockMeta < entry2.blockMeta)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)
|
||||||
|
|
||||||
|
-- Write out the output format:
|
||||||
|
io.write("UpgradeBlockTypePalette\n")
|
||||||
|
io.write("FileVersion\t1\n")
|
||||||
|
io.write("CommonPrefix\t", commonPrefix, "\n")
|
||||||
|
io.write("\n")
|
||||||
|
local prefixLen = string.len(commonPrefix) + 1
|
||||||
|
for _, entry in ipairs(registry) do
|
||||||
|
local props = serializeProperties(entry.properties)
|
||||||
|
if (props ~= "") then
|
||||||
|
props = "\t" .. props
|
||||||
|
end
|
||||||
|
io.write(
|
||||||
|
entry.blockType, "\t", entry.blockMeta, "\t",
|
||||||
|
string.sub(entry.blockTypeName, prefixLen),
|
||||||
|
props, "\n"
|
||||||
|
)
|
||||||
|
end
|
@ -123,7 +123,18 @@ std::map<UInt32, UInt32> BlockTypePalette::createTransformMapWithFallback(const
|
|||||||
|
|
||||||
void BlockTypePalette::loadFromString(const AString & aString)
|
void BlockTypePalette::loadFromString(const AString & aString)
|
||||||
{
|
{
|
||||||
// TODO: Detect format (Json vs Lua)
|
static const AString hdrTsvRegular = "BlockTypePalette";
|
||||||
|
static const AString hdrTsvUpgrade = "UpgradeBlockTypePalette";
|
||||||
|
|
||||||
|
// Detect format by checking the header line (none -> JSON):
|
||||||
|
if (aString.substr(0, hdrTsvRegular.length()) == hdrTsvRegular)
|
||||||
|
{
|
||||||
|
return loadFromTsv(aString, false);
|
||||||
|
}
|
||||||
|
else if (aString.substr(0, hdrTsvUpgrade.length()) == hdrTsvUpgrade)
|
||||||
|
{
|
||||||
|
return loadFromTsv(aString, true);
|
||||||
|
}
|
||||||
return loadFromJsonString(aString);
|
return loadFromJsonString(aString);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,55 +154,144 @@ void BlockTypePalette::loadFromJsonString(const AString & aJsonPalette)
|
|||||||
throw LoadFailedException(errs);
|
throw LoadFailedException(errs);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the JSON's metadata + version:
|
// Sanity-check the JSON's structure:
|
||||||
if (!root.isObject() ||
|
if (!root.isObject())
|
||||||
!root.isMember("Metadata") ||
|
|
||||||
!root["Metadata"].isMember("ProtocolBlockTypePaletteVersion") ||
|
|
||||||
!root.isMember("Palette") ||
|
|
||||||
!root["Palette"].isArray())
|
|
||||||
{
|
{
|
||||||
throw LoadFailedException("Incorrect palette format, wrong or missing metadata.");
|
throw LoadFailedException("Incorrect palette format, expected an object at root.");
|
||||||
}
|
|
||||||
auto version = root["Metadata"]["ProtocolBlockTypePaletteVersion"].asUInt();
|
|
||||||
if (version != 1)
|
|
||||||
{
|
|
||||||
throw(Printf("Palette format version %d not supported.", version));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the palette:
|
// Load the palette:
|
||||||
auto len = root["Palette"].size();
|
for (auto itr = root.begin(), end = root.end(); itr != end; ++itr)
|
||||||
for (decltype(len) i = 0; i < len; ++i)
|
|
||||||
{
|
{
|
||||||
const auto & record = root["Palette"][i];
|
const auto & blockTypeName = itr.name();
|
||||||
if (!record.isObject())
|
const auto & states = (*itr)["states"];
|
||||||
|
if (states == Json::Value())
|
||||||
{
|
{
|
||||||
throw LoadFailedException(Printf("Palette record #%u is not a JSON object.", i));
|
throw LoadFailedException(Printf("Missing \"states\" for block type \"%s\"", blockTypeName));
|
||||||
}
|
}
|
||||||
|
for (const auto & state: states)
|
||||||
auto blockTypeName = record["name"].asString();
|
|
||||||
auto id = static_cast<UInt32>(std::stoul(record["id"].asString()));
|
|
||||||
std::map<AString, AString> state;
|
|
||||||
|
|
||||||
if (record.isMember("props"))
|
|
||||||
{
|
{
|
||||||
const auto & props = record["props"];
|
auto id = static_cast<UInt32>(std::stoul(state["id"].asString()));
|
||||||
if (!props.isObject())
|
std::map<AString, AString> props;
|
||||||
|
if (state.isMember("properties"))
|
||||||
{
|
{
|
||||||
throw LoadFailedException(Printf("Palette record #%u: \"props\" value is not a JSON object.", i));
|
const auto & properties = state["properties"];
|
||||||
}
|
if (!properties.isObject())
|
||||||
for (const auto & key: props.getMemberNames())
|
{
|
||||||
{
|
throw LoadFailedException(Printf("Member \"properties\" is not a JSON object (block type \"%s\", id %u).", blockTypeName, id));
|
||||||
state[key] = props[key].asString();
|
}
|
||||||
|
for (const auto & key: properties.getMemberNames())
|
||||||
|
{
|
||||||
|
props[key] = properties[key].asString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
addMapping(id, blockTypeName, props);
|
||||||
}
|
}
|
||||||
BlockState blockState(state);
|
}
|
||||||
|
}
|
||||||
// Insert / update in the maps:
|
|
||||||
mNumberToBlock[id] = {blockTypeName, blockState};
|
|
||||||
mBlockToNumber[blockTypeName][blockState] = id;
|
|
||||||
if (id > mMaxIndex)
|
|
||||||
{
|
|
||||||
mMaxIndex = id;
|
void BlockTypePalette::loadFromTsv(const AString & aTsvPalette, bool aIsUpgrade)
|
||||||
}
|
{
|
||||||
} // for i - Palette[]
|
auto lines = StringSplitAndTrim(aTsvPalette, "\n");
|
||||||
|
|
||||||
|
// Parse the header:
|
||||||
|
int fileVersion = 0;
|
||||||
|
AString commonPrefix;
|
||||||
|
auto numLines = lines.size();
|
||||||
|
for (size_t idx = 1; idx < numLines; ++idx)
|
||||||
|
{
|
||||||
|
const auto & line = lines[idx];
|
||||||
|
if (line.empty())
|
||||||
|
{
|
||||||
|
// End of headers, erase them from lines[] and go parse the data
|
||||||
|
lines.erase(lines.begin(), lines.begin() + static_cast<AStringVector::difference_type>(idx) + 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
auto s = StringSplit(line, "\t");
|
||||||
|
if (s.size() != 2)
|
||||||
|
{
|
||||||
|
throw LoadFailedException(Printf("Invalid header format on line %u", idx + 1));
|
||||||
|
}
|
||||||
|
if (s[0] == "FileVersion")
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
fileVersion = std::stoi(s[1]);
|
||||||
|
}
|
||||||
|
catch (const std::exception & exc)
|
||||||
|
{
|
||||||
|
throw LoadFailedException(Printf("Invalid file version: \"%d\" (%s)", s[1], exc.what()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (s[0] == "CommonPrefix")
|
||||||
|
{
|
||||||
|
commonPrefix = s[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fileVersion != 1)
|
||||||
|
{
|
||||||
|
throw LoadFailedException(Printf("Unknown file version (%d), only version 1 is supported", fileVersion));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the data:
|
||||||
|
size_t minSplit = aIsUpgrade ? 3 : 2;
|
||||||
|
for (const auto & line: lines)
|
||||||
|
{
|
||||||
|
auto s = StringSplit(line, "\t");
|
||||||
|
auto numSplit = s.size();
|
||||||
|
if (numSplit < minSplit)
|
||||||
|
{
|
||||||
|
throw LoadFailedException(Printf("Not enough values on data line: \"%s\"", line));
|
||||||
|
}
|
||||||
|
UInt32 id;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
id = static_cast<UInt32>(std::stoi(s[0]));
|
||||||
|
}
|
||||||
|
catch (const std::exception & exc)
|
||||||
|
{
|
||||||
|
throw LoadFailedException(Printf("Invalid block ID: \"%s\" (%s)", s[0], exc.what()));
|
||||||
|
}
|
||||||
|
size_t idx = 1;
|
||||||
|
if (aIsUpgrade)
|
||||||
|
{
|
||||||
|
id = id * 16;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
id = id + static_cast<UInt32>(Clamp(std::stoi(s[1]), 0, 15));
|
||||||
|
}
|
||||||
|
catch (const std::exception & exc)
|
||||||
|
{
|
||||||
|
throw LoadFailedException(Printf("Invalid block meta: \"%s\" (%s)", s[1], exc.what()));
|
||||||
|
}
|
||||||
|
idx = 2;
|
||||||
|
}
|
||||||
|
const auto & blockTypeName = s[idx];
|
||||||
|
idx += 1;
|
||||||
|
std::map<AString, AString> state;
|
||||||
|
while (idx + 1 < numSplit)
|
||||||
|
{
|
||||||
|
state[s[idx]] = s[idx + 1];
|
||||||
|
idx += 2;
|
||||||
|
}
|
||||||
|
addMapping(id, commonPrefix + blockTypeName, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void BlockTypePalette::addMapping(UInt32 aID, const AString & aBlockTypeName, const BlockState & aBlockState)
|
||||||
|
{
|
||||||
|
mNumberToBlock[aID] = {aBlockTypeName, aBlockState};
|
||||||
|
mBlockToNumber[aBlockTypeName][aBlockState] = aID;
|
||||||
|
if (aID > mMaxIndex)
|
||||||
|
{
|
||||||
|
mMaxIndex = aID;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,25 @@ The object itself provides no thread safety, users of this class need to handle
|
|||||||
Note that the palette itself doesn't support erasing;
|
Note that the palette itself doesn't support erasing;
|
||||||
to erase, create a new instance and re-add only the wanted items.
|
to erase, create a new instance and re-add only the wanted items.
|
||||||
|
|
||||||
Internally, the object uses two synced maps, one for each translation direction. */
|
Internally, the object uses two synced maps, one for each translation direction.
|
||||||
|
|
||||||
|
The palette can be loaded from a string (file). The loader supports either the blocks.json file exported by
|
||||||
|
the vanilla server itself (https://wiki.vg/Data_Generators), or a processed text file generated by
|
||||||
|
our tool $/Tools/BlockTypePaletteGenerator/, or a hand-written text file describing the upgrade from
|
||||||
|
1.12 BlockType + BlockMeta to 1.13 string representations.
|
||||||
|
The text file is a TSV (tab-separated values), which basically means the data is generally structured as
|
||||||
|
<value1><tab><value2><tab><value3><tab>...<valueN><eol>, where eol is the platform's CR / CRLF / LF lineend.
|
||||||
|
The file starts with a single value on the first line, "BlockTypePalette" or "UpgradeBlockTypePalette", which
|
||||||
|
is used to detect the file format. The following lines are "headers", simple <key><tab><value><eol> entries
|
||||||
|
that contain the metadata about the file. "FileVersion" is a compulsory key, "CommonPrefix" is supported, others
|
||||||
|
are ignored.
|
||||||
|
The headers are followed by an empty line (that signalizes the end of headers) and then the actual data.
|
||||||
|
For regular BlockTypePalette TSV file of version 1, the data is in the format:
|
||||||
|
<index><tab><blockTypeName><tab><state1Name><tab><state1Value><tab><state2Name> ... <eol>
|
||||||
|
For the UpgradeBlockTypePalette TSV file of version 1, the data is in the format:
|
||||||
|
<blockType><tab><blockMeta><tab><blockTypeName><tab><state1Name><tab><state1Value><tab><state2Name> ... <eol>
|
||||||
|
If a CommonPrefix header is present, its value is pre-pended to each blockTypeName loaded (thus allowing
|
||||||
|
the file to be overall smaller). */
|
||||||
class BlockTypePalette
|
class BlockTypePalette
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -78,10 +96,11 @@ public:
|
|||||||
std::map<UInt32, UInt32> createTransformMapWithFallback(const BlockTypePalette & aFrom, UInt32 aFallbackIndex) const;
|
std::map<UInt32, UInt32> createTransformMapWithFallback(const BlockTypePalette & aFrom, UInt32 aFallbackIndex) const;
|
||||||
|
|
||||||
/** Loads the palette from the string representation.
|
/** Loads the palette from the string representation.
|
||||||
Throws a LoadFailedException if the loading fails hard (bad string format).
|
Throws a LoadFailedException if the loading fails hard (bad string format);
|
||||||
|
but still a part of the data may already be loaded at that point.
|
||||||
If the string specifies duplicate entries (either to already existing entries, or to itself),
|
If the string specifies duplicate entries (either to already existing entries, or to itself),
|
||||||
the duplicates replace the current values silently (this allows us to chain multiple files as "overrides".
|
the duplicates replace the current values silently (this allows us to chain multiple files as "overrides".
|
||||||
Currently handles only JSON representation, expected to handle also Lua representation in the future. */
|
Auto-detects the string format (json / tsv, normal / upgrade palette) and calls the appropriate load function. */
|
||||||
void loadFromString(const AString & aString);
|
void loadFromString(const AString & aString);
|
||||||
|
|
||||||
|
|
||||||
@ -100,9 +119,21 @@ protected:
|
|||||||
UInt32 mMaxIndex;
|
UInt32 mMaxIndex;
|
||||||
|
|
||||||
|
|
||||||
/** Loads the palette from the JSON representation.
|
/** Loads the palette from the JSON representation, https://wiki.vg/Data_Generators
|
||||||
Throws a LoadFailedException if the loading fails hard (bad string format).
|
Throws a LoadFailedException if the loading fails hard (bad string format);
|
||||||
If the string specifies duplicate entries (either to already existing entries, or to itself),
|
but still a part of the data may already be loaded at that point.
|
||||||
the duplicates replace the current values silently (this allows us to chain multiple files as "overrides". */
|
See also: loadFromString(). */
|
||||||
void loadFromJsonString(const AString & aJsonPalette);
|
void loadFromJsonString(const AString & aJsonPalette);
|
||||||
|
|
||||||
|
/** Loads the palette from the regular or upgrade TSV representation.
|
||||||
|
aIsUpgrade specifies whether the format is an upgrade TSV (true) or a regular one (false)
|
||||||
|
Throws a LoadFailedException if the loading fails hard (bad string format);
|
||||||
|
but still a part of the data may already be loaded at that point.
|
||||||
|
See also: loadFromString(). */
|
||||||
|
void loadFromTsv(const AString & aTsvPalette, bool aIsUpgrade);
|
||||||
|
|
||||||
|
/** Adds a mapping between the numeric and stringular representation into both maps,
|
||||||
|
updates the mMaxIndex, if appropriate.
|
||||||
|
Silently overwrites any previous mapping for the ID, if present, but keeps the old string->id mapping. */
|
||||||
|
void addMapping(UInt32 aID, const AString & aBlockTypeName, const BlockState & aBlockState);
|
||||||
};
|
};
|
||||||
|
@ -24,10 +24,8 @@ public:
|
|||||||
|
|
||||||
~cStopwatch()
|
~cStopwatch()
|
||||||
{
|
{
|
||||||
#ifdef _DEBUG
|
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - m_StartTime).count();
|
||||||
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - m_StartTime).count();
|
LOG("Stopwatch: %s took %.03f sec", m_Name, static_cast<double>(duration) / 1000);
|
||||||
LOGD("Stopwatch: %s took %.03f sec", m_Name.c_str(), static_cast<double>(duration) / 1000);
|
|
||||||
#endif // _DEBUG
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "../TestHelpers.h"
|
#include "../TestHelpers.h"
|
||||||
#include "BlockTypePalette.h"
|
#include "BlockTypePalette.h"
|
||||||
|
#include "Stopwatch.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -123,31 +124,7 @@ static void testTransformWithFallback()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Tests that loading a simple JSON palette succeeds. */
|
/** Tests that loading fails for nonsense input */
|
||||||
static void testLoadSimpleSuccess(void)
|
|
||||||
{
|
|
||||||
LOG("Testing loading a simple JSON palette");
|
|
||||||
|
|
||||||
BlockTypePalette palette;
|
|
||||||
|
|
||||||
auto example = "{\"Metadata\":{\"ProtocolBlockTypePaletteVersion\":1}, \"Palette\":[{\
|
|
||||||
\"props\": {\
|
|
||||||
\"foo\": \"bar\"\
|
|
||||||
}, \
|
|
||||||
\"name\": \"b\", \
|
|
||||||
\"id\": \"0\"\
|
|
||||||
}]}";
|
|
||||||
|
|
||||||
palette.loadFromString(example);
|
|
||||||
TEST_EQUAL(palette.maybeIndex("b", BlockState({{"foo", "bar"}})), (std::make_pair<UInt32, bool>(0, true)));
|
|
||||||
TEST_EQUAL(palette.maybeIndex("b", BlockState({{"foo", "baz"}})), (std::make_pair<UInt32, bool>(0, false)));
|
|
||||||
TEST_EQUAL(palette.maybeIndex("a", BlockState({{"foo", "bar"}})), (std::make_pair<UInt32, bool>(0, false)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void testLoadErrors(void)
|
static void testLoadErrors(void)
|
||||||
{
|
{
|
||||||
LOG("Testing palette load error reporting.");
|
LOG("Testing palette load error reporting.");
|
||||||
@ -164,69 +141,154 @@ static void testLoadErrors(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void testLoadComplex1(void)
|
/** Tests that loading a simple JSON palette succeeds. */
|
||||||
|
static void testLoadJsonSimple(void)
|
||||||
{
|
{
|
||||||
LOG("Testing loading a complex palette (1)");
|
LOG("Testing loading a simple JSON palette");
|
||||||
|
|
||||||
BlockTypePalette palette;
|
BlockTypePalette palette;
|
||||||
auto str = "{\"Metadata\":{\"ProtocolBlockTypePaletteVersion\":1}, \"Palette\":[{\
|
|
||||||
\"props\": {\
|
auto example = " \
|
||||||
\"foo\": \"bar\", \
|
{ \
|
||||||
\"moo\": \"baz\"\
|
\"minecraft:air\": { \
|
||||||
|
\"states\": [ \
|
||||||
|
{ \
|
||||||
|
\"id\": 0, \
|
||||||
|
\"default\": true \
|
||||||
|
} \
|
||||||
|
] \
|
||||||
|
} \
|
||||||
|
}";
|
||||||
|
|
||||||
|
palette.loadFromString(example);
|
||||||
|
TEST_EQUAL(palette.maybeIndex("minecraft:air", BlockState()), (std::make_pair<UInt32, bool>(0, true)));
|
||||||
|
TEST_EQUAL(palette.maybeIndex("minecraft:air", BlockState({{"foo", "baz"}})).second, false);
|
||||||
|
TEST_EQUAL(palette.maybeIndex("minecraft:a", BlockState()).second, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Tests loading a complex block with multiple states and duplicates. */
|
||||||
|
static void testLoadJsonComplex(void)
|
||||||
|
{
|
||||||
|
LOG("Testing loading a complex JSON palette");
|
||||||
|
BlockTypePalette palette;
|
||||||
|
auto str = " \
|
||||||
|
{ \
|
||||||
|
\"minecraft:oak_sapling\": { \
|
||||||
|
\"properties\": { \
|
||||||
|
\"stage\": [ \
|
||||||
|
\"0\", \
|
||||||
|
\"1\" \
|
||||||
|
] \
|
||||||
}, \
|
}, \
|
||||||
\"id\": \"0\", \
|
\"states\": [ \
|
||||||
\"name\": \"b\"\
|
{ \
|
||||||
}, {\
|
\"properties\": { \
|
||||||
\"props\": {\
|
\"stage\": \"0\" \
|
||||||
\"foo\": \"baz\", \
|
}, \
|
||||||
\"moo\": \"bar\"\
|
\"id\" : 21, \
|
||||||
}, \
|
\"default\" : true \
|
||||||
\"id\": \"1\", \
|
}, \
|
||||||
\"name\": \"b\"\
|
{ \
|
||||||
}, {\
|
\"properties\": { \
|
||||||
\"props\": {\
|
\"stage\": \"1\" \
|
||||||
\"foo\": \"baz\", \
|
}, \
|
||||||
\"moo\": \"bar\"\
|
\"id\" : 22 \
|
||||||
}, \
|
}, \
|
||||||
\"id\": \"1001\", \
|
{ \
|
||||||
\"name\": \"b\"\
|
\"properties\": { \
|
||||||
}]}";
|
\"stage\": \"1\" \
|
||||||
|
}, \
|
||||||
|
\"id\" : 23 \
|
||||||
|
}\
|
||||||
|
] \
|
||||||
|
} \
|
||||||
|
}";
|
||||||
|
|
||||||
// Note: The palette has a duplicate entry with differrent IDs, the latter ID wins
|
// Note: The palette has a duplicate entry with differrent IDs, the latter ID wins
|
||||||
palette.loadFromString(str);
|
palette.loadFromString(str);
|
||||||
TEST_EQUAL(palette.maybeIndex("b", {{"foo", "bar"}}).second, false);
|
TEST_EQUAL(palette.maybeIndex("minecraft:oak_sapling", {{"stage", "10"}}).second, false);
|
||||||
TEST_EQUAL(palette.maybeIndex("b", {{"foo", "bar"}, {"moo", "baz"}}), (std::make_pair<UInt32, bool>(0, true)));
|
TEST_EQUAL(palette.maybeIndex("minecraft:oak_sapling", {{"stage", "0"}}), (std::make_pair<UInt32, bool>(21, true)));
|
||||||
TEST_EQUAL(palette.maybeIndex("b", {{"foo", "baz"}, {"moo", "bar"}}), (std::make_pair<UInt32, bool>(1001, true)));
|
TEST_EQUAL(palette.maybeIndex("minecraft:oak_sapling", {{"stage", "1"}}), (std::make_pair<UInt32, bool>(23, true)));
|
||||||
TEST_EQUAL(palette.maybeIndex("c", {{"foo", "baz"}, {"moo", "bar"}}).second, false);
|
TEST_EQUAL(palette.maybeIndex("minecraft:oak_sapling", {{"foo", "baz"}}).second, false);
|
||||||
|
TEST_EQUAL(palette.maybeIndex("minecraft:oak_sap", {{"stage", "0"}}).second, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void testLoadComplex2(void)
|
/** Tests loading a palette from simple regular TSV text data. */
|
||||||
|
static void testLoadTsvRegular(void)
|
||||||
{
|
{
|
||||||
LOG("Testing loading a complex palette (2)");
|
LOG("Testing loading a simple regular TSV palette");
|
||||||
BlockTypePalette palette;
|
BlockTypePalette palette;
|
||||||
auto str = "{\"Metadata\":{\"ProtocolBlockTypePaletteVersion\":1}, \"Palette\":[{\
|
auto str = "\
|
||||||
\"id\": \"0\", \
|
BlockTypePalette\r\n\
|
||||||
\"name\": \"a\"\
|
FileVersion\t1\n\
|
||||||
}, {\
|
CommonPrefix\tminecraft:\r\n\
|
||||||
\"id\": \"1\", \
|
\n\
|
||||||
\"name\": \"b\"\
|
0\tair\r\n\
|
||||||
}]}";
|
1\tstone\n\
|
||||||
|
2\tgrass\tsnow_covered\t0\n\
|
||||||
|
3\tgrass\tsnow_covered\t1\n\
|
||||||
|
";
|
||||||
palette.loadFromString(str);
|
palette.loadFromString(str);
|
||||||
TEST_EQUAL(palette.maybeIndex("a", BlockState()), (std::make_pair<UInt32, bool>(0, true)));
|
TEST_EQUAL(palette.maybeIndex("minecraft:air", BlockState()), (std::make_pair<UInt32, bool>(0, true)));
|
||||||
TEST_EQUAL(palette.maybeIndex("b", BlockState()), (std::make_pair<UInt32, bool>(1, true)));
|
TEST_EQUAL(palette.maybeIndex("minecraft:stone", BlockState()), (std::make_pair<UInt32, bool>(1, true)));
|
||||||
|
TEST_EQUAL(palette.maybeIndex("minecraft:grass", BlockState({{"snow_covered", "0"}})), (std::make_pair<UInt32, bool>(2, true)));
|
||||||
|
TEST_EQUAL(palette.maybeIndex("minecraft:grass", BlockState({{"snow_covered", "1"}})), (std::make_pair<UInt32, bool>(3, true)));
|
||||||
|
TEST_EQUAL(palette.maybeIndex("minecraft:air", BlockState({{"snow_covered", "0"}})).second, false);
|
||||||
|
TEST_EQUAL(palette.maybeIndex("minecraft:grass", BlockState({{"snow_covered", "2"}})).second, false);
|
||||||
|
TEST_EQUAL(palette.maybeIndex("minecraft:grass", BlockState()).second, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void testLoadFromFile1(void)
|
/** Tests loading a palette from simple upgrade TSV text data. */
|
||||||
|
static void testLoadTsvUpgrade(void)
|
||||||
{
|
{
|
||||||
LOG("Testing loading a palette from file \"test.btp.json\"");
|
LOG("Testing loading a simple upgrade TSV palette");
|
||||||
BlockTypePalette palette;
|
BlockTypePalette palette;
|
||||||
palette.loadFromString(cFile::ReadWholeFile("test.btp.json"));
|
auto str = "\
|
||||||
|
UpgradeBlockTypePalette\r\n\
|
||||||
|
FileVersion\t1\n\
|
||||||
|
CommonPrefix\tminecraft:\r\n\
|
||||||
|
\n\
|
||||||
|
0\t0\tair\r\n\
|
||||||
|
1\t0\tstone\n\
|
||||||
|
2\t0\tgrass\tsnow_covered\t0\n\
|
||||||
|
2\t1\tgrass\tsnow_covered\t1\n\
|
||||||
|
";
|
||||||
|
palette.loadFromString(str);
|
||||||
|
TEST_EQUAL(palette.maybeIndex("minecraft:air", BlockState()), (std::make_pair<UInt32, bool>(0, true)));
|
||||||
|
TEST_EQUAL(palette.maybeIndex("minecraft:stone", BlockState()), (std::make_pair<UInt32, bool>(16, true)));
|
||||||
|
TEST_EQUAL(palette.maybeIndex("minecraft:grass", BlockState({{"snow_covered", "0"}})), (std::make_pair<UInt32, bool>(32, true)));
|
||||||
|
TEST_EQUAL(palette.maybeIndex("minecraft:grass", BlockState({{"snow_covered", "1"}})), (std::make_pair<UInt32, bool>(33, true)));
|
||||||
|
TEST_EQUAL(palette.maybeIndex("minecraft:air", BlockState({{"snow_covered", "0"}})).second, false);
|
||||||
|
TEST_EQUAL(palette.maybeIndex("minecraft:grass", BlockState({{"snow_covered", "2"}})).second, false);
|
||||||
|
TEST_EQUAL(palette.maybeIndex("minecraft:grass", BlockState()).second, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Tests loading a palette from a real-life protocol base file (1.13). */
|
||||||
|
static void testLoadFromBaseFile(void)
|
||||||
|
{
|
||||||
|
LOG("Testing loading a palette from file \"base.btp.txt\" (1.13)");
|
||||||
|
BlockTypePalette palette;
|
||||||
|
{
|
||||||
|
auto fileContents = cFile::ReadWholeFile("base.btp.txt");
|
||||||
|
cStopwatch sw("Loading palette");
|
||||||
|
palette.loadFromString(fileContents);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_EQUAL(palette.maybeIndex("minecraft:air", BlockState()), (std::make_pair<UInt32, bool>(0, true)));
|
TEST_EQUAL(palette.maybeIndex("minecraft:air", BlockState()), (std::make_pair<UInt32, bool>(0, true)));
|
||||||
TEST_EQUAL(palette.maybeIndex("minecraft:stone", BlockState()), (std::make_pair<UInt32, bool>(1, true)));
|
TEST_EQUAL(palette.maybeIndex("minecraft:stone", BlockState()), (std::make_pair<UInt32, bool>(1, true)));
|
||||||
@ -250,15 +312,19 @@ static void testLoadFromFile1(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void testLoadFromFile2(void)
|
/** Tests loading an upgrade-palette from a real-life upgrade file. */
|
||||||
|
static void testLoadFromUpgradeFile(void)
|
||||||
{
|
{
|
||||||
LOG("Testing loading a palette from file \"base.btp.json\" (version 1.13)");
|
LOG("Testing loading an upgrade palette from file \"UpgradeBlockTypePalette.txt\".");
|
||||||
BlockTypePalette palette;
|
BlockTypePalette palette;
|
||||||
palette.loadFromString(cFile::ReadWholeFile("base.btp.json"));
|
{
|
||||||
|
auto fileContents = cFile::ReadWholeFile("UpgradeBlockTypePalette.txt");
|
||||||
|
cStopwatch sw("Loading upgrade palette");
|
||||||
|
palette.loadFromString(fileContents);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_EQUAL(palette.maybeIndex("minecraft:air", BlockState()), (std::make_pair<UInt32, bool>(0, true)));
|
TEST_EQUAL(palette.entry(0), (std::make_pair<AString, BlockState>("minecraft:air", {})));
|
||||||
TEST_EQUAL(palette.maybeIndex("minecraft:stone", BlockState()), (std::make_pair<UInt32, bool>(1, true)));
|
TEST_EQUAL(palette.entry(44 * 16 + 8), (std::make_pair<AString, BlockState>("minecraft:stone_slab", {{"type", "top"}})));
|
||||||
TEST_EQUAL(palette.maybeIndex("minecraft:dirt", BlockState()), (std::make_pair<UInt32, bool>(10, true)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -269,12 +335,13 @@ IMPLEMENT_TEST_MAIN("BlockTypePalette",
|
|||||||
testBasic();
|
testBasic();
|
||||||
testTransformAddMissing();
|
testTransformAddMissing();
|
||||||
testTransformWithFallback();
|
testTransformWithFallback();
|
||||||
testLoadSimpleSuccess();
|
|
||||||
testLoadErrors();
|
testLoadErrors();
|
||||||
testLoadComplex1();
|
testLoadJsonSimple();
|
||||||
testLoadComplex2();
|
testLoadJsonComplex();
|
||||||
testLoadFromFile1();
|
testLoadTsvRegular();
|
||||||
testLoadFromFile2();
|
testLoadTsvUpgrade();
|
||||||
|
testLoadFromBaseFile();
|
||||||
|
testLoadFromUpgradeFile();
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -58,8 +58,8 @@ target_link_libraries(PalettedBlockAreaTest fmt::fmt jsoncpp_lib_static)
|
|||||||
|
|
||||||
# Extra files for BlockTypePalette test:
|
# Extra files for BlockTypePalette test:
|
||||||
file (COPY
|
file (COPY
|
||||||
test.btp.json
|
../../Server/Protocol/1.13/base.btp.txt
|
||||||
../../Server/Protocol/1.13/base.btp.json
|
../../Server/Protocol/UpgradeBlockTypePalette.txt
|
||||||
DESTINATION ./
|
DESTINATION ./
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1,146 +0,0 @@
|
|||||||
{
|
|
||||||
"Metadata": {
|
|
||||||
"ProtocolBlockTypePaletteVersion": 1
|
|
||||||
},
|
|
||||||
"Palette": [{
|
|
||||||
"id": 0,
|
|
||||||
"name": "minecraft:air"
|
|
||||||
}, {
|
|
||||||
"id": 1,
|
|
||||||
"name": "minecraft:stone"
|
|
||||||
}, {
|
|
||||||
"id": 221,
|
|
||||||
"name": "minecraft:dark_oak_leaves",
|
|
||||||
"props": {
|
|
||||||
"persistent": "false",
|
|
||||||
"distance": "4"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"id": 222,
|
|
||||||
"name": "minecraft:dark_oak_leaves",
|
|
||||||
"props": {
|
|
||||||
"persistent": "true",
|
|
||||||
"distance": "5"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"id": 223,
|
|
||||||
"name": "minecraft:dark_oak_leaves",
|
|
||||||
"props": {
|
|
||||||
"persistent": "false",
|
|
||||||
"distance": "5"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"id": 224,
|
|
||||||
"name": "minecraft:dark_oak_leaves",
|
|
||||||
"props": {
|
|
||||||
"persistent": "true",
|
|
||||||
"distance": "6"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"id": 225,
|
|
||||||
"name": "minecraft:dark_oak_leaves",
|
|
||||||
"props": {
|
|
||||||
"persistent": "false",
|
|
||||||
"distance": "6"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"id": 226,
|
|
||||||
"name": "minecraft:dark_oak_leaves",
|
|
||||||
"props": {
|
|
||||||
"persistent": "true",
|
|
||||||
"distance": "7"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"id": 227,
|
|
||||||
"name": "minecraft:dark_oak_leaves",
|
|
||||||
"props": {
|
|
||||||
"persistent": "false",
|
|
||||||
"distance": "7"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"id": 9988,
|
|
||||||
"name": "minecraft:powered_rail",
|
|
||||||
"props": {
|
|
||||||
"powered": "true",
|
|
||||||
"shape": "north_south"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"id": 9989,
|
|
||||||
"name": "minecraft:powered_rail",
|
|
||||||
"props": {
|
|
||||||
"powered": "true",
|
|
||||||
"shape": "east_west"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"id": 9990,
|
|
||||||
"name": "minecraft:powered_rail",
|
|
||||||
"props": {
|
|
||||||
"powered": "true",
|
|
||||||
"shape": "ascending_east"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"id": 9991,
|
|
||||||
"name": "minecraft:powered_rail",
|
|
||||||
"props": {
|
|
||||||
"powered": "true",
|
|
||||||
"shape": "ascending_west"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"id": 9992,
|
|
||||||
"name": "minecraft:powered_rail",
|
|
||||||
"props": {
|
|
||||||
"powered": "true",
|
|
||||||
"shape": "ascending_north"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"id": 9993,
|
|
||||||
"name": "minecraft:powered_rail",
|
|
||||||
"props": {
|
|
||||||
"powered": "true",
|
|
||||||
"shape": "ascending_south"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"id": 9994,
|
|
||||||
"name": "minecraft:powered_rail",
|
|
||||||
"props": {
|
|
||||||
"powered": "false",
|
|
||||||
"shape": "north_south"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"id": 9995,
|
|
||||||
"name": "minecraft:powered_rail",
|
|
||||||
"props": {
|
|
||||||
"powered": "false",
|
|
||||||
"shape": "east_west"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"id": 9996,
|
|
||||||
"name": "minecraft:powered_rail",
|
|
||||||
"props": {
|
|
||||||
"powered": "false",
|
|
||||||
"shape": "ascending_east"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"id": 9997,
|
|
||||||
"name": "minecraft:powered_rail",
|
|
||||||
"props": {
|
|
||||||
"powered": "false",
|
|
||||||
"shape": "ascending_west"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"id": 9998,
|
|
||||||
"name": "minecraft:powered_rail",
|
|
||||||
"props": {
|
|
||||||
"powered": "false",
|
|
||||||
"shape": "ascending_north"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"id": 9999,
|
|
||||||
"name": "minecraft:powered_rail",
|
|
||||||
"props": {
|
|
||||||
"powered": "false",
|
|
||||||
"shape": "ascending_south"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user