mcdex 0.1.0.dev0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mcdex/__init__.py +281 -0
- mcdex/advancements/__init__.py +16 -0
- mcdex/advancements/_mc_advancements.py +3558 -0
- mcdex/advancements/advancements.json +12101 -0
- mcdex/attributes/__init__.py +16 -0
- mcdex/attributes/_mc_attributes.py +83 -0
- mcdex/attributes/attributes.json +289 -0
- mcdex/banner_patterns/__init__.py +16 -0
- mcdex/banner_patterns/_mc_banner_patterns.py +86 -0
- mcdex/banner_patterns/banner_patterns.json +310 -0
- mcdex/base/__init__.py +146 -0
- mcdex/base/_advancement_id.py +22 -0
- mcdex/base/_attribute_id.py +22 -0
- mcdex/base/_banner_pattern_id.py +26 -0
- mcdex/base/_biome_id.py +22 -0
- mcdex/base/_block_entity_id.py +22 -0
- mcdex/base/_block_id.py +35 -0
- mcdex/base/_cat_sound_variant_id.py +23 -0
- mcdex/base/_cat_variant_id.py +22 -0
- mcdex/base/_catalogue_meta.py +38 -0
- mcdex/base/_chicken_sound_variant_id.py +23 -0
- mcdex/base/_chicken_variant_id.py +23 -0
- mcdex/base/_cow_sound_variant_id.py +23 -0
- mcdex/base/_cow_variant_id.py +22 -0
- mcdex/base/_damage_type_id.py +21 -0
- mcdex/base/_dimension_id.py +21 -0
- mcdex/base/_effect_id.py +21 -0
- mcdex/base/_enchantment_id.py +22 -0
- mcdex/base/_entity_id.py +35 -0
- mcdex/base/_equipment_slot.py +34 -0
- mcdex/base/_frog_variant_id.py +22 -0
- mcdex/base/_game_id.py +88 -0
- mcdex/base/_game_rule_id.py +21 -0
- mcdex/base/_item_id.py +98 -0
- mcdex/base/_mc_thing.py +289 -0
- mcdex/base/_mc_version.py +140 -0
- mcdex/base/_music_id.py +25 -0
- mcdex/base/_not_in_version.py +68 -0
- mcdex/base/_painting_variant_id.py +23 -0
- mcdex/base/_particle_id.py +21 -0
- mcdex/base/_pig_sound_variant_id.py +23 -0
- mcdex/base/_pig_variant_id.py +22 -0
- mcdex/base/_potion_id.py +25 -0
- mcdex/base/_potion_modifier.py +30 -0
- mcdex/base/_sound_id.py +21 -0
- mcdex/base/_statistic_id.py +22 -0
- mcdex/base/_structure_id.py +21 -0
- mcdex/base/_trim_material_id.py +26 -0
- mcdex/base/_trim_pattern_id.py +25 -0
- mcdex/base/_version.py +188 -0
- mcdex/base/_villager_profession_id.py +24 -0
- mcdex/base/_villager_type_id.py +25 -0
- mcdex/base/_wolf_sound_variant_id.py +23 -0
- mcdex/base/_wolf_variant_id.py +22 -0
- mcdex/base/_zombie_nautilus_variant_id.py +23 -0
- mcdex/biomes/__init__.py +16 -0
- mcdex/biomes/_mc_biomes.py +137 -0
- mcdex/biomes/biomes.json +652 -0
- mcdex/block_entities/__init__.py +16 -0
- mcdex/block_entities/_mc_block_entities.py +95 -0
- mcdex/block_entities/block_entities.json +331 -0
- mcdex/blocks/__init__.py +16 -0
- mcdex/blocks/_mc_blocks.py +1338 -0
- mcdex/blocks/blocks.json +7770 -0
- mcdex/cat_sound_variants/__init__.py +16 -0
- mcdex/cat_sound_variants/_mc_cat_sound_variants.py +47 -0
- mcdex/cat_sound_variants/cat_sound_variants.json +25 -0
- mcdex/cat_variants/__init__.py +16 -0
- mcdex/cat_variants/_mc_cat_variants.py +54 -0
- mcdex/cat_variants/cat_variants.json +91 -0
- mcdex/chicken_sound_variants/__init__.py +17 -0
- mcdex/chicken_sound_variants/_mc_chicken_sound_variants.py +48 -0
- mcdex/chicken_sound_variants/chicken_sound_variants.json +24 -0
- mcdex/chicken_variants/__init__.py +16 -0
- mcdex/chicken_variants/_mc_chicken_variants.py +47 -0
- mcdex/chicken_variants/chicken_variants.json +30 -0
- mcdex/cow_sound_variants/__init__.py +16 -0
- mcdex/cow_sound_variants/_mc_cow_sound_variants.py +47 -0
- mcdex/cow_sound_variants/cow_sound_variants.json +24 -0
- mcdex/cow_variants/__init__.py +16 -0
- mcdex/cow_variants/_mc_cow_variants.py +47 -0
- mcdex/cow_variants/cow_variants.json +30 -0
- mcdex/damage_types/__init__.py +16 -0
- mcdex/damage_types/_mc_damage_types.py +94 -0
- mcdex/damage_types/damage_types.json +317 -0
- mcdex/dimensions/__init__.py +16 -0
- mcdex/dimensions/_mc_dimensions.py +46 -0
- mcdex/dimensions/dimensions.json +29 -0
- mcdex/effects/__init__.py +16 -0
- mcdex/effects/_mc_effects.py +83 -0
- mcdex/effects/effects.json +251 -0
- mcdex/enchantments/__init__.py +16 -0
- mcdex/enchantments/_mc_enchantments.py +86 -0
- mcdex/enchantments/enchantments.json +270 -0
- mcdex/entities/__init__.py +16 -0
- mcdex/entities/_mc_entities.py +206 -0
- mcdex/entities/entities.json +1042 -0
- mcdex/frog_variants/__init__.py +16 -0
- mcdex/frog_variants/_mc_frog_variants.py +47 -0
- mcdex/frog_variants/frog_variants.json +29 -0
- mcdex/game_rules/__init__.py +16 -0
- mcdex/game_rules/_mc_game_rules.py +110 -0
- mcdex/game_rules/game_rules.json +436 -0
- mcdex/items/__init__.py +16 -0
- mcdex/items/_mc_items.py +1842 -0
- mcdex/items/items.json +20060 -0
- mcdex/music/__init__.py +16 -0
- mcdex/music/_music.py +65 -0
- mcdex/music/music.json +143 -0
- mcdex/painting_variants/__init__.py +16 -0
- mcdex/painting_variants/_mc_painting_variants.py +96 -0
- mcdex/painting_variants/painting_variants.json +369 -0
- mcdex/particles/__init__.py +16 -0
- mcdex/particles/_mc_particles.py +184 -0
- mcdex/particles/particles.json +917 -0
- mcdex/pig_sound_variants/__init__.py +16 -0
- mcdex/pig_sound_variants/_mc_pig_sound_variants.py +48 -0
- mcdex/pig_sound_variants/pig_sound_variants.json +30 -0
- mcdex/pig_variants/__init__.py +16 -0
- mcdex/pig_variants/_mc_pig_variants.py +46 -0
- mcdex/pig_variants/pig_variants.json +30 -0
- mcdex/potions/__init__.py +20 -0
- mcdex/potions/_mc_potions.py +101 -0
- mcdex/potions/_modified_potion.py +129 -0
- mcdex/potions/potions.json +297 -0
- mcdex/py.typed +0 -0
- mcdex/sounds/__init__.py +16 -0
- mcdex/sounds/_mc_sounds.py +2395 -0
- mcdex/sounds/sounds.json +13077 -0
- mcdex/statistics/__init__.py +16 -0
- mcdex/statistics/_mc_statistics.py +123 -0
- mcdex/statistics/statistics.json +521 -0
- mcdex/structures/__init__.py +16 -0
- mcdex/structures/_mc_structures.py +99 -0
- mcdex/structures/structures.json +367 -0
- mcdex/trim_materials/__init__.py +16 -0
- mcdex/trim_materials/_mc_trim_materials.py +54 -0
- mcdex/trim_materials/trim_materials.json +77 -0
- mcdex/trim_patterns/__init__.py +16 -0
- mcdex/trim_patterns/_mc_trim_patterns.py +61 -0
- mcdex/trim_patterns/trim_patterns.json +119 -0
- mcdex/villager_professions/__init__.py +17 -0
- mcdex/villager_professions/_mc_villager_professions.py +61 -0
- mcdex/villager_professions/villager_professions.json +125 -0
- mcdex/villager_types/__init__.py +16 -0
- mcdex/villager_types/_mc_villager_types.py +52 -0
- mcdex/villager_types/villager_types.json +54 -0
- mcdex/wolf_sound_variants/__init__.py +17 -0
- mcdex/wolf_sound_variants/_mc_wolf_sound_variants.py +53 -0
- mcdex/wolf_sound_variants/wolf_sound_variants.json +54 -0
- mcdex/wolf_variants/__init__.py +16 -0
- mcdex/wolf_variants/_mc_wolf_variants.py +53 -0
- mcdex/wolf_variants/wolf_variants.json +66 -0
- mcdex/zombie_nautilus_variants/__init__.py +17 -0
- mcdex/zombie_nautilus_variants/_mc_zombie_nautilus_variants.py +48 -0
- mcdex/zombie_nautilus_variants/zombie_nautilus_variants.json +23 -0
- mcdex-0.1.0.dev0.dist-info/METADATA +1285 -0
- mcdex-0.1.0.dev0.dist-info/RECORD +161 -0
- mcdex-0.1.0.dev0.dist-info/WHEEL +5 -0
- mcdex-0.1.0.dev0.dist-info/licenses/LICENSE +201 -0
- mcdex-0.1.0.dev0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1285 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mcdex
|
|
3
|
+
Version: 0.1.0.dev0
|
|
4
|
+
Summary: A typed, version-agnostic catalogue of Minecraft for Python: every item, block and entity as a class with one identity across all versions. Not affiliated with Mojang or Microsoft.
|
|
5
|
+
Author-email: Asger Jon Vistisen <asgerjon2@gmail.com>
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/AsgerJon/mcdex
|
|
8
|
+
Project-URL: Bug Tracker, https://github.com/AsgerJon/mcdex/issues
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
11
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Natural Language :: English
|
|
16
|
+
Classifier: Topic :: Games/Entertainment
|
|
17
|
+
Classifier: Typing :: Typed
|
|
18
|
+
Requires-Python: >=3.14
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: worktoy>=1.2.1.dev1
|
|
22
|
+
Dynamic: license-file
|
|
23
|
+
|
|
24
|
+
[](https://claude.com/claude-code)
|
|
25
|
+
[](https://codecov.io/gh/AsgerJon/mcdex)
|
|
26
|
+
[](https://pypi.org/project/mcdex/)
|
|
27
|
+
[](https://opensource.org/licenses/Apache-2.0)
|
|
28
|
+
|
|
29
|
+
# mcdex v0.1.0-dev0 (development build)
|
|
30
|
+
A typed, version-agnostic catalogue of Minecraft for Python: every item, block and entity with one identity across all versions, carrying what it is, what it does and when it arrived. Name a thing once and it means the same on 1.7.10 and on 26.3. Not affiliated with Mojang or Microsoft.
|
|
31
|
+
|
|
32
|
+
Items, entities, blocks, mob effects, enchantments, potions, biomes, block entities, particles, sounds, attributes, statistics, game rules, villager professions and types, dimensions, damage types, armor trims, music, mob variants, paintings, banner patterns, advancements and structures are in. The data covers every release from 1.7.2 to 26.3.
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from mcdex import MCEntities, MCItems
|
|
36
|
+
|
|
37
|
+
pinkWool = MCItems['pink_wool']
|
|
38
|
+
|
|
39
|
+
pinkWool['1.7.10'].minecraftId # 'minecraft:wool:6'
|
|
40
|
+
pinkWool['1.12.2'].minecraftId # 'minecraft:wool:6'
|
|
41
|
+
pinkWool['1.13'].minecraftId # 'minecraft:pink_wool'
|
|
42
|
+
pinkWool['26.3'].minecraftId # 'minecraft:pink_wool'
|
|
43
|
+
|
|
44
|
+
witherSkeleton = MCEntities['wither_skeleton']
|
|
45
|
+
|
|
46
|
+
witherSkeleton['1.7.10'].minecraftId # 'Skeleton{SkeletonType:1}'
|
|
47
|
+
witherSkeleton['1.10.2'].minecraftId # 'Skeleton{SkeletonType:1}'
|
|
48
|
+
witherSkeleton['1.11'].minecraftId # 'minecraft:wither_skeleton'
|
|
49
|
+
witherSkeleton['26.3'].minecraftId # 'minecraft:wither_skeleton'
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
You write `pink_wool` once. mcdex knows that 1.12.2 calls it `minecraft:wool` with meta 6 and 1.13 calls it `minecraft:pink_wool`, and the same for every other item and version.
|
|
53
|
+
|
|
54
|
+
Entities work the same way, and their ids are what `/summon` takes. Until 1.11 the wither skeleton was a skeleton of type 1, so 1.10.2 summons it as `Skeleton{SkeletonType:1}`. Since 1.11 it is `minecraft:wither_skeleton`.
|
|
55
|
+
|
|
56
|
+
## Contents
|
|
57
|
+
|
|
58
|
+
- [Items](#items)
|
|
59
|
+
- [Finding an item](#finding-an-item)
|
|
60
|
+
- [What a version calls an item](#what-a-version-calls-an-item)
|
|
61
|
+
- [When vanilla has no such item](#when-vanilla-has-no-such-item)
|
|
62
|
+
- [The whole history of an item](#the-whole-history-of-an-item)
|
|
63
|
+
- [One old id, two items](#one-old-id-two-items)
|
|
64
|
+
- [Entities](#entities)
|
|
65
|
+
- [Finding an entity](#finding-an-entity)
|
|
66
|
+
- [What a version calls an entity](#what-a-version-calls-an-entity)
|
|
67
|
+
- [Entities told apart by their data](#entities-told-apart-by-their-data)
|
|
68
|
+
- [When vanilla has no such entity](#when-vanilla-has-no-such-entity)
|
|
69
|
+
- [Blocks](#blocks)
|
|
70
|
+
- [Mob effects](#mob-effects)
|
|
71
|
+
- [Enchantments](#enchantments)
|
|
72
|
+
- [Potions](#potions)
|
|
73
|
+
- [Biomes](#biomes)
|
|
74
|
+
- [Block entities](#block-entities)
|
|
75
|
+
- [Particles](#particles)
|
|
76
|
+
- [Sounds](#sounds)
|
|
77
|
+
- [Attributes](#attributes)
|
|
78
|
+
- [Statistics](#statistics)
|
|
79
|
+
- [Game rules](#game-rules)
|
|
80
|
+
- [Villager professions and types](#villager-professions-and-types)
|
|
81
|
+
- [Dimensions](#dimensions)
|
|
82
|
+
- [Damage types](#damage-types)
|
|
83
|
+
- [Armor trims](#armor-trims)
|
|
84
|
+
- [Music](#music)
|
|
85
|
+
- [Mob variants](#mob-variants)
|
|
86
|
+
- [Paintings](#paintings)
|
|
87
|
+
- [Banner patterns](#banner-patterns)
|
|
88
|
+
- [Advancements](#advancements)
|
|
89
|
+
- [Structures](#structures)
|
|
90
|
+
- [Versions](#versions)
|
|
91
|
+
- [Equipment slots](#equipment-slots)
|
|
92
|
+
- [Item ids](#item-ids)
|
|
93
|
+
- [Entity ids](#entity-ids)
|
|
94
|
+
- [Block ids](#block-ids)
|
|
95
|
+
- [Recipes](#recipes)
|
|
96
|
+
- [Where the data comes from](#where-the-data-comes-from)
|
|
97
|
+
- [Development](#development)
|
|
98
|
+
|
|
99
|
+
## Items
|
|
100
|
+
|
|
101
|
+
### Finding an item
|
|
102
|
+
|
|
103
|
+
`MCItems` is the catalogue, and an enumeration: each item is one of its members, named by the item's unique name in capitals. A member is found by that name, in any case, or by indexing the catalogue with the unique name:
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
from mcdex import MCItems
|
|
107
|
+
|
|
108
|
+
diamond = MCItems.DIAMOND
|
|
109
|
+
diamond # <MCItems>.DIAMOND
|
|
110
|
+
diamond.uniqueName # 'diamond'
|
|
111
|
+
MCItems['diamond'] is diamond # True
|
|
112
|
+
MCItems.Diamond is diamond # True
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Every catalogue of mcdex is such an enumeration, built on worktoy's `KeeNum`, so an editor can complete `MCItems.PINK_WOOL`. A unique name that is no member's name, as the sound `entity.creeper.primed`, is found by indexing: `MCSounds['entity.creeper.primed']` is `MCSounds.ENTITY_CREEPER_PRIMED`.
|
|
116
|
+
|
|
117
|
+
The data ships inside the package, in `mcdex/items/items.json`. Importing mcdex makes the members but reads none of the data: the first use of a catalogue reads its file, in a few milliseconds, and an item's record is read at the item's first use.
|
|
118
|
+
|
|
119
|
+
The class itself is the catalogue. It has a length, it can be searched, and it can be iterated, in the order of the names:
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
len(MCItems) # 1672
|
|
123
|
+
'pink_wool' in MCItems # True
|
|
124
|
+
'grss' in MCItems # False
|
|
125
|
+
|
|
126
|
+
for item in MCItems:
|
|
127
|
+
print(item.uniqueName) # abandoned_camp_map, acacia_boat, acacia_button, ...
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
A name the catalogue lacks raises `KeyError`:
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
MCItems['grss'] # KeyError: "mcdex has no item named 'grss'"
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
A unique name is mcdex's own name for the item, the same in every version, in lowercase words joined by underscores. It is the item's most modern name: the name it has in 26.3, or, for an item removed before 26.3, the last name it had. A name means one thing in every version: `grass` is the short grass growing on top of blocks, in every version, and `grass_block` is the block. A few items have two names. The short grass is both `grass` and `short_grass`, the name 26.3 gives it, and either name gives the same item's ids.
|
|
137
|
+
|
|
138
|
+
### What a version calls an item
|
|
139
|
+
|
|
140
|
+
Index an item with a version to get its `ItemId` in that version:
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
from mcdex import MCItems, MCVersion, Version
|
|
144
|
+
|
|
145
|
+
pinkWool = MCItems['pink_wool']
|
|
146
|
+
|
|
147
|
+
pinkWool[Version.V1_12_2] # ItemId('pink_wool', 'minecraft:wool:6')
|
|
148
|
+
pinkWool['1.12.2'] # the same: the version as the game reports it
|
|
149
|
+
pinkWool['V1_13'] # ItemId('pink_wool', 'minecraft:pink_wool'), by member name
|
|
150
|
+
pinkWool[MCVersion(26, 3)] # ItemId('pink_wool', 'minecraft:pink_wool')
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
An `ItemId` holds two strings: `uniqueName`, mcdex's name, and `minecraftId`, everything that version of the game needs to identify the item. The `minecraftId` is written in the notation of its era:
|
|
154
|
+
|
|
155
|
+
| Versions | Notation | Pink wool | Creeper spawn egg |
|
|
156
|
+
|---|---|---|---|
|
|
157
|
+
| 1.7.2 to 1.8.9 | name, and the meta where it tells items apart | `minecraft:wool:6` | `minecraft:spawn_egg:50` |
|
|
158
|
+
| 1.9 to 1.10.2 | the same, with NBT where the game tells items apart by it | `minecraft:wool:6` | `minecraft:spawn_egg{EntityTag:{id:"Creeper"}}` |
|
|
159
|
+
| 1.11 to 1.12.2 | the same | `minecraft:wool:6` | `minecraft:spawn_egg{EntityTag:{id:"minecraft:creeper"}}` |
|
|
160
|
+
| 1.13 to 26.3 | the name alone | `minecraft:pink_wool` | `minecraft:creeper_spawn_egg` |
|
|
161
|
+
|
|
162
|
+
The meta is part of the id only where it tells items apart: `minecraft:diamond` has none, and neither do tools, whose meta is only their damage. Stone has none in 1.7.10, when there was only one kind, and has `:0` from 1.8, when granite, diorite and andesite joined it as `:1` to `:6`. Before 1.9, a splash potion was a potion with the splash bit set in its meta: `minecraft:potion:16384`.
|
|
163
|
+
|
|
164
|
+
Some items and what they were called over the years:
|
|
165
|
+
|
|
166
|
+
```python
|
|
167
|
+
MCItems['grass']['1.12.2'].minecraftId # 'minecraft:tallgrass:1'
|
|
168
|
+
MCItems['grass']['1.13'].minecraftId # 'minecraft:grass'
|
|
169
|
+
MCItems['grass']['26.3'].minecraftId # 'minecraft:short_grass'
|
|
170
|
+
|
|
171
|
+
MCItems['grass_block']['1.12.2'].minecraftId # 'minecraft:grass'
|
|
172
|
+
MCItems['grass_block']['1.13'].minecraftId # 'minecraft:grass_block'
|
|
173
|
+
|
|
174
|
+
MCItems['red_bed']['1.11.2'].minecraftId # 'minecraft:bed'
|
|
175
|
+
MCItems['red_bed']['1.12.2'].minecraftId # 'minecraft:bed:14'
|
|
176
|
+
MCItems['red_bed']['1.13'].minecraftId # 'minecraft:red_bed'
|
|
177
|
+
|
|
178
|
+
MCItems['cooked_cod']['1.7.10'].minecraftId # 'minecraft:cooked_fished:0'
|
|
179
|
+
MCItems['cooked_cod']['1.8.9'].minecraftId # 'minecraft:cooked_fish:0'
|
|
180
|
+
MCItems['cooked_cod']['1.13'].minecraftId # 'minecraft:cooked_cod'
|
|
181
|
+
|
|
182
|
+
MCItems['oak_door']['1.12.2'].minecraftId # 'minecraft:wooden_door'
|
|
183
|
+
MCItems['dragon_head']['1.12.2'].minecraftId # 'minecraft:skull:5'
|
|
184
|
+
MCItems['iron_chain']['1.20.2'].minecraftId # 'minecraft:chain'
|
|
185
|
+
MCItems['iron_chain']['1.21.9'].minecraftId # 'minecraft:iron_chain'
|
|
186
|
+
MCItems['splash_potion']['1.8.9'].minecraftId # 'minecraft:potion:16384'
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### When vanilla has no such item
|
|
190
|
+
|
|
191
|
+
A version without the item raises `NotInVersion`, a `LookupError`. Its message says when vanilla added the item, or when it removed it:
|
|
192
|
+
|
|
193
|
+
```python
|
|
194
|
+
from mcdex import MCItems, NotInVersion
|
|
195
|
+
|
|
196
|
+
MCItems['elytra']['1.7.10']
|
|
197
|
+
# NotInVersion: Vanilla 1.7.10 has no 'elytra'; vanilla added it in 1.9!
|
|
198
|
+
|
|
199
|
+
MCItems['lit_furnace']['1.10']
|
|
200
|
+
# NotInVersion: Vanilla 1.10 has no 'lit_furnace'; vanilla removed it in 1.9!
|
|
201
|
+
|
|
202
|
+
try:
|
|
203
|
+
MCItems['elytra']['1.7.10']
|
|
204
|
+
except NotInVersion as exception:
|
|
205
|
+
exception.item # <MCItems>.ELYTRA
|
|
206
|
+
exception.version # <Version>.V1_7_10
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
This speaks only of vanilla. A mod may bring the elytra to 1.7.10 under an id of its own, so `NotInVersion` cannot tell whether a given game has the item; it is what a test cites when the game lacks it.
|
|
210
|
+
|
|
211
|
+
Two other failures are not `NotInVersion`. A version before the data raises `ValueError`, and a version that is no release raises `KeeResolveError`:
|
|
212
|
+
|
|
213
|
+
```python
|
|
214
|
+
MCItems['diamond']['1.6.4'] # ValueError: mcdex has no data on 'diamond' before 1.7.2
|
|
215
|
+
MCItems['diamond']['26.4-snapshot-7'] # KeeResolveError
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### The whole history of an item
|
|
219
|
+
|
|
220
|
+
Each item has three tables, built when first read and handed out as copies:
|
|
221
|
+
|
|
222
|
+
- `versionIds`: the id in every version from the first the data covers, `''` where vanilla has no such item.
|
|
223
|
+
- `maxStackSize`: the max stack size in every version that has the item.
|
|
224
|
+
- `equipmentSlot`: the `EquipmentSlot` an entity equips the item to, in every version that has it.
|
|
225
|
+
|
|
226
|
+
```python
|
|
227
|
+
from mcdex import EquipmentSlot, MCItems, Version
|
|
228
|
+
|
|
229
|
+
elytra = MCItems['elytra']
|
|
230
|
+
elytra.versionIds[Version.V1_8_9] # ''
|
|
231
|
+
elytra.versionIds[Version.V1_9] # 'minecraft:elytra'
|
|
232
|
+
len(elytra.versionIds) # 84, from 1.7.2 to 26.3
|
|
233
|
+
elytra.maxStackSize[Version.V1_9] # 1
|
|
234
|
+
elytra.equipmentSlot[Version.V1_9] # <EquipmentSlot>.CHEST
|
|
235
|
+
Version.V1_8_9 in elytra.equipmentSlot # False: vanilla 1.8.9 has no elytra
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Stack sizes and slots change between versions, and mcdex reads them per version:
|
|
239
|
+
|
|
240
|
+
```python
|
|
241
|
+
MCItems['oak_door'].maxStackSize[Version.V1_7_10] # 1
|
|
242
|
+
MCItems['oak_door'].maxStackSize[Version.V1_8] # 64
|
|
243
|
+
|
|
244
|
+
MCItems['shield'].equipmentSlot[Version.V1_9] # <EquipmentSlot>.MAINHAND
|
|
245
|
+
MCItems['shield'].equipmentSlot[Version.V1_10] # <EquipmentSlot>.OFFHAND
|
|
246
|
+
|
|
247
|
+
MCItems['carved_pumpkin'].equipmentSlot[Version.V1_12_2] # <EquipmentSlot>.HEAD
|
|
248
|
+
MCItems['white_carpet'].equipmentSlot[Version.V1_20_5] # <EquipmentSlot>.BODY, for llamas
|
|
249
|
+
MCItems['saddle'].equipmentSlot[Version.V1_21_4] # <EquipmentSlot>.MAINHAND
|
|
250
|
+
MCItems['saddle'].equipmentSlot[Version.V1_21_5] # <EquipmentSlot>.SADDLE
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
The 1.9 shield is no mistake. 1.9 added the offhand, but its code deciding an item's slot had no case for the shield yet; 1.10 added one.
|
|
254
|
+
|
|
255
|
+
### One old id, two items
|
|
256
|
+
|
|
257
|
+
A game id can belong to two items in one version, when the old item was both. In 1.12.2 there was no undyed shulker box, and the purple one was the shulker box; 1.13 added the undyed one. Before 1.13 every pumpkin had a face; 1.13 added the plain one. Until 1.14 the stone slab had the smooth look; 1.14 renamed it and added a plain one.
|
|
258
|
+
|
|
259
|
+
```python
|
|
260
|
+
MCItems['shulker_box']['1.12.2'].minecraftId # 'minecraft:purple_shulker_box'
|
|
261
|
+
MCItems['purple_shulker_box']['1.12.2'].minecraftId # 'minecraft:purple_shulker_box'
|
|
262
|
+
MCItems['shulker_box']['1.13'].minecraftId # 'minecraft:shulker_box'
|
|
263
|
+
|
|
264
|
+
MCItems['pumpkin']['1.12.2'].minecraftId # 'minecraft:pumpkin'
|
|
265
|
+
MCItems['carved_pumpkin']['1.12.2'].minecraftId # 'minecraft:pumpkin'
|
|
266
|
+
MCItems['carved_pumpkin']['1.13'].minecraftId # 'minecraft:carved_pumpkin'
|
|
267
|
+
|
|
268
|
+
MCItems['stone_slab']['1.13'].minecraftId # 'minecraft:stone_slab'
|
|
269
|
+
MCItems['smooth_stone_slab']['1.13'].minecraftId # 'minecraft:stone_slab'
|
|
270
|
+
MCItems['smooth_stone_slab']['1.14'].minecraftId # 'minecraft:smooth_stone_slab'
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
Where a name was reused for a different thing, nothing is shared: 1.12.2's `minecraft:grass` is the grass block alone, and the old `minecraft:stone_stairs` were cobblestone stairs, so `stone_stairs` begins in 1.14.
|
|
274
|
+
|
|
275
|
+
## Entities
|
|
276
|
+
|
|
277
|
+
### Finding an entity
|
|
278
|
+
|
|
279
|
+
`MCEntities` is the catalogue of entities: everything a version of the game knows an entity by, which is what `/summon` takes and what `@e[type=...]` matches. It works like `MCItems`:
|
|
280
|
+
|
|
281
|
+
```python
|
|
282
|
+
from mcdex import MCEntities
|
|
283
|
+
|
|
284
|
+
creeper = MCEntities['creeper']
|
|
285
|
+
creeper.uniqueName # 'creeper'
|
|
286
|
+
MCEntities['creeper'] is creeper # True
|
|
287
|
+
len(MCEntities) # 162
|
|
288
|
+
'stray' in MCEntities # True
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
An entity's unique name is its name in 26.3. An entity removed before 26.3 keeps its last name, as `creaking_transient` does. The player and the fishing bobber are in the catalogue because the game names them, though `/summon` refuses both.
|
|
292
|
+
|
|
293
|
+
### What a version calls an entity
|
|
294
|
+
|
|
295
|
+
```python
|
|
296
|
+
creeper['1.10.2'].minecraftId # 'Creeper'
|
|
297
|
+
creeper['1.11'].minecraftId # 'minecraft:creeper'
|
|
298
|
+
|
|
299
|
+
zombifiedPiglin = MCEntities['zombified_piglin']
|
|
300
|
+
zombifiedPiglin['1.10.2'].minecraftId # 'PigZombie'
|
|
301
|
+
zombifiedPiglin['1.15.2'].minecraftId # 'minecraft:zombie_pigman'
|
|
302
|
+
zombifiedPiglin['1.16'].minecraftId # 'minecraft:zombified_piglin'
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
Up to 1.10.2 the game named its entities in CamelCase: `Creeper`, `EntityHorse`, `MinecartRideable`. 1.11 gave them `minecraft:` names, and later versions renamed some.
|
|
306
|
+
|
|
307
|
+
### Entities told apart by their data
|
|
308
|
+
|
|
309
|
+
Some entities were once one entity, told apart by a value in its data. Before 1.11 the wither skeleton was a skeleton of type 1. Before 1.21.2 every boat was one entity with a wood type. An old id carries that data after the name, as `/summon` takes it:
|
|
310
|
+
|
|
311
|
+
```python
|
|
312
|
+
witherSkeleton = MCEntities['wither_skeleton']
|
|
313
|
+
witherSkeleton['1.10.2'].minecraftId # 'Skeleton{SkeletonType:1}'
|
|
314
|
+
witherSkeleton['1.11'].minecraftId # 'minecraft:wither_skeleton'
|
|
315
|
+
|
|
316
|
+
MCEntities['donkey']['1.10.2'].minecraftId # 'EntityHorse{Type:1}'
|
|
317
|
+
MCEntities['zombie_villager']['1.8.9'].minecraftId # 'Zombie{IsVillager:1b}'
|
|
318
|
+
MCEntities['zombie_villager']['1.10'].minecraftId # 'Zombie{ZombieType:1}'
|
|
319
|
+
MCEntities['cat']['1.13.2'].minecraftId # 'minecraft:ocelot{CatType:1}'
|
|
320
|
+
MCEntities['spruce_boat']['1.21.1'].minecraftId # 'minecraft:boat{Type:"spruce"}'
|
|
321
|
+
MCEntities['lingering_potion']['1.20.4'].minecraftId
|
|
322
|
+
# 'minecraft:potion{Item:{id:"minecraft:lingering_potion",Count:1b}}'
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
The entity without that data is the first of them. A plain `EntityHorse` is the horse, a plain boat is the oak boat, and a plain thrown potion is the splash potion:
|
|
326
|
+
|
|
327
|
+
```python
|
|
328
|
+
MCEntities['horse']['1.10.2'].minecraftId # 'EntityHorse'
|
|
329
|
+
MCEntities['oak_boat']['1.21.1'].minecraftId # 'minecraft:boat'
|
|
330
|
+
MCEntities['splash_potion']['1.21.4'].minecraftId # 'minecraft:potion'
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
Each id uses the data in the form that version's own entity code reads it. A zombie villager is `Zombie{IsVillager:1b}` in 1.8.9, adds the `VillagerProfession` that 1.9 began to read, and becomes `Zombie{ZombieType:1}` in 1.10.
|
|
334
|
+
|
|
335
|
+
### When vanilla has no such entity
|
|
336
|
+
|
|
337
|
+
```python
|
|
338
|
+
MCEntities['stray']['1.9.4']
|
|
339
|
+
# NotInVersion: Vanilla 1.9.4 has no 'stray'; vanilla added it in 1.10!
|
|
340
|
+
|
|
341
|
+
MCEntities['creaking_transient']['26.3']
|
|
342
|
+
# NotInVersion: Vanilla 26.3 has no 'creaking_transient'; vanilla removed it in 1.21.4!
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
A 1.9.4 skeleton of type 2 is no stray: 1.9.4's code tells only type 1 apart. In the same way a spruce boat begins in 1.9, the first version whose boat reads a wood type.
|
|
346
|
+
|
|
347
|
+
One gap is Mojang's own. Before 1.16 a thrown potion kept its item under `Potion`, and nothing in the game's upgrade code turns that into the `Item` that later versions read. So nothing links a lingering potion entity of 1.9 to 1.15.2 to `lingering_potion`, and the data begins it at 1.16.
|
|
348
|
+
|
|
349
|
+
## Blocks
|
|
350
|
+
|
|
351
|
+
`MCBlocks` is the catalogue of blocks: what `/setblock` takes. It works like the others:
|
|
352
|
+
|
|
353
|
+
```python
|
|
354
|
+
from mcdex import MCBlocks
|
|
355
|
+
|
|
356
|
+
pinkWool = MCBlocks['pink_wool']
|
|
357
|
+
pinkWool['1.12.2'].minecraftId # 'minecraft:wool:6'
|
|
358
|
+
pinkWool['1.13'].minecraftId # 'minecraft:pink_wool'
|
|
359
|
+
len(MCBlocks) # 1287
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
Before 1.13 a block was a name and a meta, a number from 0 to 15. The meta is part of the id only where it tells blocks apart: any oak stairs is `minecraft:oak_stairs`, but the pink wool is wool with meta 6. An id takes the smallest meta of its block:
|
|
363
|
+
|
|
364
|
+
```python
|
|
365
|
+
MCBlocks['oak_stairs']['1.12.2'].minecraftId # 'minecraft:oak_stairs'
|
|
366
|
+
MCBlocks['oak_wood']['1.12.2'].minecraftId # 'minecraft:log:12'
|
|
367
|
+
MCBlocks['wall_torch']['1.12.2'].minecraftId # 'minecraft:torch:1'
|
|
368
|
+
MCBlocks['granite']['1.8'].minecraftId # 'minecraft:stone:1'
|
|
369
|
+
MCBlocks['granite']['1.7.10']
|
|
370
|
+
# NotInVersion: Vanilla 1.7.10 has no 'granite'; vanilla added it in 1.8!
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
Some old blocks were told apart by their block entity, the data a block keeps besides its meta. Their ids carry that data:
|
|
374
|
+
- a skull's type,
|
|
375
|
+
- a bed's colour, from 1.12,
|
|
376
|
+
- a banner's base colour,
|
|
377
|
+
- a flower pot's plant.
|
|
378
|
+
|
|
379
|
+
The data is written as that version's own code reads it:
|
|
380
|
+
|
|
381
|
+
```python
|
|
382
|
+
MCBlocks['creeper_head']['1.12.2'].minecraftId # 'minecraft:skull:1{SkullType:4b}'
|
|
383
|
+
MCBlocks['white_bed']['1.12'].minecraftId # 'minecraft:bed{color:0}'
|
|
384
|
+
MCBlocks['red_bed']['1.11.2'].minecraftId # 'minecraft:bed'
|
|
385
|
+
MCBlocks['potted_poppy']['1.7.10'].minecraftId # 'minecraft:flower_pot{Item:38,Data:0}'
|
|
386
|
+
MCBlocks['potted_poppy']['1.8'].minecraftId # 'minecraft:flower_pot{Item:"minecraft:red_flower",Data:0}'
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
A bed before 1.12 was always red, and 1.7's flower pot held its plant's number. Until 1.17 the water cauldron was a cauldron with water in it, and the old pumpkin is both the pumpkin and the carved pumpkin, as for the items:
|
|
390
|
+
|
|
391
|
+
```python
|
|
392
|
+
MCBlocks['water_cauldron']['1.16.5'].minecraftId # 'minecraft:cauldron[level=1]'
|
|
393
|
+
MCBlocks['carved_pumpkin']['1.12.2'].minecraftId # 'minecraft:pumpkin'
|
|
394
|
+
MCBlocks['grass_block']['1.12.2'].minecraftId # 'minecraft:grass'
|
|
395
|
+
MCBlocks['grass']['1.12.2'].minecraftId # 'minecraft:tallgrass:1'
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
Where two old blocks became one, the block takes the old id nearest its default state:
|
|
399
|
+
- the furnace is `minecraft:furnace`, not `minecraft:lit_furnace`;
|
|
400
|
+
- the water is `minecraft:water`, not `minecraft:flowing_water`.
|
|
401
|
+
|
|
402
|
+
## Mob effects
|
|
403
|
+
|
|
404
|
+
`MCEffects` is the catalogue of mob effects: what `/effect` takes. 1.7's command took only an effect's number; from 1.8 it looks the effect up by name:
|
|
405
|
+
|
|
406
|
+
```python
|
|
407
|
+
from mcdex import MCEffects
|
|
408
|
+
|
|
409
|
+
speed = MCEffects['speed']
|
|
410
|
+
speed['1.7.10'].minecraftId # '1'
|
|
411
|
+
speed['1.8'].minecraftId # 'minecraft:speed'
|
|
412
|
+
MCEffects['instant_health']['1.7.10'].minecraftId # '6'
|
|
413
|
+
len(MCEffects) # 40
|
|
414
|
+
MCEffects['glowing']['1.8.9']
|
|
415
|
+
# NotInVersion: Vanilla 1.8.9 has no 'glowing'; vanilla added it in 1.9!
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
Which effect an old number is comes from the game's own table of numbers for upgrading old worlds. Every name 1.8 to 1.13.2 gives agrees with it.
|
|
419
|
+
|
|
420
|
+
## Enchantments
|
|
421
|
+
|
|
422
|
+
`MCEnchantments` is the catalogue of enchantments: what `/enchant` takes. 1.7's command took only an enchantment's number; from 1.8 it looks the enchantment up by name:
|
|
423
|
+
|
|
424
|
+
```python
|
|
425
|
+
from mcdex import MCEnchantments
|
|
426
|
+
|
|
427
|
+
protection = MCEnchantments['protection']
|
|
428
|
+
protection['1.7.10'].minecraftId # '0'
|
|
429
|
+
protection['1.8'].minecraftId # 'minecraft:protection'
|
|
430
|
+
MCEnchantments['sweeping_edge']['1.12.2'].minecraftId # 'minecraft:sweeping'
|
|
431
|
+
MCEnchantments['sweeping_edge']['1.20.5'].minecraftId # 'minecraft:sweeping_edge'
|
|
432
|
+
len(MCEnchantments) # 43
|
|
433
|
+
MCEnchantments['mending']['1.8.9']
|
|
434
|
+
# NotInVersion: Vanilla 1.8.9 has no 'mending'; vanilla added it in 1.9!
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
Since 1.21 the game defines its enchantments as data, in its own data pack. Its code still declares a key for each, and the two agree in every version.
|
|
438
|
+
|
|
439
|
+
## Potions
|
|
440
|
+
|
|
441
|
+
`MCPotions` is the catalogue of potions: the potion a potion item, a tipped arrow or a lingering cloud is made with. From 1.9 a potion is a name, which the item's data carries (`Potion:"minecraft:swiftness"`). Before 1.9 there were no potions apart from the item, and a potion was the potion item's damage value:
|
|
442
|
+
|
|
443
|
+
```python
|
|
444
|
+
from mcdex import MCPotions
|
|
445
|
+
|
|
446
|
+
regeneration = MCPotions.REGENERATION
|
|
447
|
+
regeneration['1.8.9'].minecraftId # '1'
|
|
448
|
+
regeneration['1.9'].minecraftId # 'minecraft:regeneration'
|
|
449
|
+
MCPotions['leaping']['1.7.10']
|
|
450
|
+
# NotInVersion: Vanilla 1.7.10 has no 'leaping'; vanilla added it in 1.8!
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
The catalogue holds the base potions only. A long or a strong potion is a base potion with a `PotionModifier`, as the game makes it: the long night vision is the night vision potion for 9600 ticks instead of 3600. Indexing the catalogue with both gives it, the same object every time:
|
|
454
|
+
|
|
455
|
+
```python
|
|
456
|
+
from mcdex import MCPotions, PotionModifier
|
|
457
|
+
|
|
458
|
+
longNightVision = MCPotions[MCPotions.NIGHT_VISION, PotionModifier.LONG]
|
|
459
|
+
longNightVision['1.12.2'].minecraftId # 'minecraft:long_night_vision'
|
|
460
|
+
longNightVision['1.8.9'].minecraftId # '70'
|
|
461
|
+
MCPotions['regeneration', 'strong']['1.8.9'].minecraftId # '33'
|
|
462
|
+
longNightVision is MCPotions['night_vision', 'long'] # True
|
|
463
|
+
len(MCPotions), len(PotionModifier) # (25, 2)
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
Which base potion and modifier a potion is comes from the game's own code: each long or strong potion is registered with its base potion's name, and its effects last longer or are stronger than the base potion's. Before 1.9 the same shows in the damage value: 64 for long and 32 for strong, on top of the base potion's number. Night vision is 6, so the long night vision is 70.
|
|
467
|
+
|
|
468
|
+
Which potion an old damage value is comes from the game's own table for upgrading old worlds. The table reads only the low seven bits: the smallest value is the id, and the bits for splash (16384) and drinkable (8192) are left out. An old version has a potion only if its own brewing rules can make every effect of the potion. 1.7 could not brew jump boost, so it has no leaping. How it goes inside an item in each version, and the command that gives one: [Ids that go inside an item](#ids-that-go-inside-an-item).
|
|
469
|
+
|
|
470
|
+
## Biomes
|
|
471
|
+
|
|
472
|
+
`MCBiomes` is the catalogue of biomes. Up to 1.8.9 the game knew a biome only by its number; from 1.9 by its name:
|
|
473
|
+
|
|
474
|
+
```python
|
|
475
|
+
from mcdex import MCBiomes
|
|
476
|
+
|
|
477
|
+
windsweptHills = MCBiomes['windswept_hills']
|
|
478
|
+
windsweptHills['1.8.9'].minecraftId # '3'
|
|
479
|
+
windsweptHills['1.12.2'].minecraftId # 'minecraft:extreme_hills'
|
|
480
|
+
windsweptHills['1.17.1'].minecraftId # 'minecraft:mountains'
|
|
481
|
+
windsweptHills['1.18'].minecraftId # 'minecraft:windswept_hills'
|
|
482
|
+
MCBiomes['sunflower_plains']['1.7.10'].minecraftId # '129'
|
|
483
|
+
len(MCBiomes) # 93
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
1.18 folded several biomes into one. Both the mountains and the mountain edge became windswept hills. One of them is the biome renamed:
|
|
487
|
+
- the one already named as the result, if there is one;
|
|
488
|
+
- otherwise the one with the smallest old number, the original biome, numbered before its variants.
|
|
489
|
+
|
|
490
|
+
The others were removed and keep their last names:
|
|
491
|
+
|
|
492
|
+
```python
|
|
493
|
+
MCBiomes['mountain_edge']['1.17.1'].minecraftId # 'minecraft:mountain_edge'
|
|
494
|
+
MCBiomes['mountain_edge']['1.18']
|
|
495
|
+
# NotInVersion: Vanilla 1.18 has no 'mountain_edge'; vanilla removed it in 1.18!
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
## Block entities
|
|
499
|
+
|
|
500
|
+
`MCBlockEntities` is the catalogue of block entities. A block entity is the data some blocks keep besides their state, as a chest keeps its items. Its id is the name the game saves it under, the `id` in its data. Up to 1.10.2 the names were the game's old ones; from 1.11 they are `minecraft:` names:
|
|
501
|
+
|
|
502
|
+
```python
|
|
503
|
+
from mcdex import MCBlockEntities
|
|
504
|
+
|
|
505
|
+
MCBlockEntities['dispenser']['1.10.2'].minecraftId # 'Trap'
|
|
506
|
+
MCBlockEntities['dispenser']['1.11'].minecraftId # 'minecraft:dispenser'
|
|
507
|
+
MCBlockEntities['brewing_stand']['1.10.2'].minecraftId # 'Cauldron'
|
|
508
|
+
MCBlockEntities['trapped_chest']['1.12.2'].minecraftId # 'minecraft:chest'
|
|
509
|
+
MCBlockEntities['trapped_chest']['1.13'].minecraftId # 'minecraft:trapped_chest'
|
|
510
|
+
len(MCBlockEntities) # 52
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
Until 1.13 a trapped chest kept its items in a chest's block entity, so that old id belongs to both. The note block and the flower pot lost their block entities in 1.13, and the bed lost its own in 26.2.
|
|
514
|
+
|
|
515
|
+
## Particles
|
|
516
|
+
|
|
517
|
+
`MCParticles` is the catalogue of particles: what `/particle` takes, from 1.8, when the command came. Up to 1.12.2 a particle had an old name; from 1.13 a registry name:
|
|
518
|
+
|
|
519
|
+
```python
|
|
520
|
+
from mcdex import MCParticles
|
|
521
|
+
|
|
522
|
+
MCParticles['flame']['1.12.2'].minecraftId # 'flame'
|
|
523
|
+
MCParticles['flame']['1.13'].minecraftId # 'minecraft:flame'
|
|
524
|
+
MCParticles['poof']['1.12.2'].minecraftId # 'explode'
|
|
525
|
+
MCParticles['poof']['1.13'].minecraftId # 'minecraft:poof'
|
|
526
|
+
MCParticles['entity_effect']['1.12.2'].minecraftId # 'mobSpell'
|
|
527
|
+
MCParticles['witch']['1.12.2'].minecraftId # 'witchMagic'
|
|
528
|
+
MCParticles['dust']['1.12.2'].minecraftId # 'reddust'
|
|
529
|
+
MCParticles['item']['1.8'].minecraftId # 'iconcrack_'
|
|
530
|
+
MCParticles['item']['1.9'].minecraftId # 'iconcrack'
|
|
531
|
+
MCParticles['item']['1.13'].minecraftId # 'minecraft:item'
|
|
532
|
+
len(MCParticles) # 141
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
No world saves a particle, so the game has no table for upgrading them. Which particle is which comes from the game's own code instead:
|
|
536
|
+
- **1.8 to 1.12.2:** each particle is a constant of one enum, whose name stays while the command's name changes. `iconcrack_` and `iconcrack` are both `ITEM_CRACK`.
|
|
537
|
+
- **Across 1.13, by name:** an old particle is a new one where Mojang's names are the same. `flame` is `minecraft:flame`, and `DAMAGE_INDICATOR` is `minecraft:damage_indicator`.
|
|
538
|
+
- **Across 1.13, by code:** an old particle is also a new one where the same code draws or spawns them. That code is in the server jars and in the client jars, which hold what runs only on a player's computer, where most particles are drawn. Three kinds of code count:
|
|
539
|
+
- **Classes.** The classes of 1.12.2 and 1.13 are paired by the constants they hold, their text and their numbers. The class that spawns `explode` in 1.12.2 spawns `minecraft:poof` in 1.13.
|
|
540
|
+
- **Blocks.** A block's classes are paired by mcdex's own block data. The mycelium block spawns `townaura` in 1.12.2 and `minecraft:mycelium` in 1.13.
|
|
541
|
+
- **Drawing.** The client's particle manager says which code draws each particle. `wake` and `minecraft:fishing` are drawn by the same code.
|
|
542
|
+
- **The rest:** that links 44 of 1.12.2's 49 particles. The other 5 have no 1.13 particle in the code, so they are removed in 1.13: `depthsuspend`, `footstep`, `snowshovel`, `blockdust` and `take`. 1.13 draws its `minecraft:block` with `blockcrack`'s code, and its `minecraft:item_snowball` with `snowballpoof`'s.
|
|
543
|
+
|
|
544
|
+
## Sounds
|
|
545
|
+
|
|
546
|
+
`MCSounds` is the catalogue of sound events: what `/playsound` takes. The game first listed its sounds in 1.9; before, a sound was any name its code handed the client, and the game kept no list, so the data begins at 1.9. A sound's unique name is its name without the namespace, dots and all:
|
|
547
|
+
|
|
548
|
+
```python
|
|
549
|
+
from mcdex import MCSounds
|
|
550
|
+
|
|
551
|
+
primed = MCSounds['entity.creeper.primed']
|
|
552
|
+
primed['1.9'].minecraftId # 'minecraft:entity.creeper.primed'
|
|
553
|
+
MCSounds['item.goat_horn.sound.7']['1.19'].minecraftId # 'minecraft:item.goat_horn.sound.7'
|
|
554
|
+
len(MCSounds) # 2151
|
|
555
|
+
primed['1.8.9']
|
|
556
|
+
# NotInVersion: Vanilla 1.8.9 has no 'entity.creeper.primed'; vanilla added it in 1.9!
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
No world saves a sound, so the game has no table for upgrading them. A sound is the same sound while its name is the same; a renamed sound is one removed and one added.
|
|
560
|
+
|
|
561
|
+
## Attributes
|
|
562
|
+
|
|
563
|
+
`MCAttributes` is the catalogue of attributes: max health, movement speed and the others. Up to 1.15.2 an attribute was a name in an entity's data; from 1.16 it is a registry name, which `/attribute` takes. 1.21.2 dropped the `generic.` in front:
|
|
564
|
+
|
|
565
|
+
```python
|
|
566
|
+
from mcdex import MCAttributes
|
|
567
|
+
|
|
568
|
+
maxHealth = MCAttributes['max_health']
|
|
569
|
+
maxHealth['1.15.2'].minecraftId # 'generic.maxHealth'
|
|
570
|
+
maxHealth['1.16'].minecraftId # 'minecraft:generic.max_health'
|
|
571
|
+
maxHealth['1.21.2'].minecraftId # 'minecraft:max_health'
|
|
572
|
+
MCAttributes['jump_strength']['1.7.10'].minecraftId # 'horse.jumpStrength'
|
|
573
|
+
MCAttributes['jump_strength']['1.20.5'].minecraftId # 'minecraft:generic.jump_strength'
|
|
574
|
+
len(MCAttributes) # 40
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
Which attribute an old name is comes from the game's own renames for upgrading old worlds, its code run for the prefix it dropped.
|
|
578
|
+
|
|
579
|
+
## Statistics
|
|
580
|
+
|
|
581
|
+
`MCStatistics` is the catalogue of custom statistics: the counts the game keeps that are no item's, block's or entity's, as the times a player left the game, which `/scoreboard` objectives count. To 1.12.2 a statistic had a `stat.` name; from 1.13 a registry name:
|
|
582
|
+
|
|
583
|
+
```python
|
|
584
|
+
from mcdex import MCStatistics
|
|
585
|
+
|
|
586
|
+
MCStatistics['leave_game']['1.12.2'].minecraftId # 'stat.leaveGame'
|
|
587
|
+
MCStatistics['leave_game']['1.13'].minecraftId # 'minecraft:leave_game'
|
|
588
|
+
MCStatistics['play_time']['1.16.5'].minecraftId # 'minecraft:play_one_minute'
|
|
589
|
+
MCStatistics['play_time']['1.17'].minecraftId # 'minecraft:play_time'
|
|
590
|
+
len(MCStatistics) # 80
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
Which statistic an old name is comes from the game's own 1.13 table of statistics and its renames since. Two statistics 1.11.1 removed have no later name. Their unique names, mcdex's own, are their old names in lower case, as `junk_fished`; their ids stay the game's.
|
|
594
|
+
|
|
595
|
+
## Game rules
|
|
596
|
+
|
|
597
|
+
`MCGameRules` is the catalogue of game rules: what `/gamerule` takes. Until 1.21.11 a rule had a camelCase name; since, a registry name, and many were renamed then:
|
|
598
|
+
|
|
599
|
+
```python
|
|
600
|
+
from mcdex import MCGameRules
|
|
601
|
+
|
|
602
|
+
MCGameRules['keep_inventory']['1.21.10'].minecraftId # 'keepInventory'
|
|
603
|
+
MCGameRules['keep_inventory']['1.21.11'].minecraftId # 'minecraft:keep_inventory'
|
|
604
|
+
MCGameRules['advance_time']['1.21.10'].minecraftId # 'doDaylightCycle'
|
|
605
|
+
MCGameRules['block_drops']['1.12.2'].minecraftId # 'doTileDrops'
|
|
606
|
+
len(MCGameRules) # 62
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
Which rule an old name is comes from the game's own code for upgrading a world's rules, run on each old rule. Where that code made two old rules one, the one registered first is the rule. `doFireTick` became the fire spread radius; the `allowFireTicksAwayFromPlayer` it was merged with was removed. Removed rules have unique names in lower case words, as `spawn_chunk_radius`.
|
|
610
|
+
|
|
611
|
+
## Villager professions and types
|
|
612
|
+
|
|
613
|
+
`MCVillagerProfessions` and `MCVillagerTypes` are the catalogues of a villager's profession and its type, the look of its home biome. An id is what `/summon` takes for a villager of that profession or type, the villager with its data, as an entity's id is. Both are registries from 1.14, saved in a villager's `VillagerData`. Before 1.14 a profession was its `Profession` number and, from 1.8, its `Career` within it. Every villager before 1.14 is of the plains type, so the villager itself is that type's id:
|
|
614
|
+
|
|
615
|
+
```python
|
|
616
|
+
from mcdex import MCVillagerProfessions, MCVillagerTypes
|
|
617
|
+
|
|
618
|
+
MCVillagerProfessions['farmer']['1.7.10'].minecraftId # 'Villager{Profession:0}'
|
|
619
|
+
MCVillagerProfessions['fisherman']['1.13.2'].minecraftId # 'minecraft:villager{Profession:0,Career:2}'
|
|
620
|
+
MCVillagerProfessions['fisherman']['1.14'].minecraftId
|
|
621
|
+
# 'minecraft:villager{VillagerData:{profession:"minecraft:fisherman"}}'
|
|
622
|
+
MCVillagerTypes['plains']['1.13.2'].minecraftId # 'minecraft:villager'
|
|
623
|
+
MCVillagerTypes['desert']['1.14'].minecraftId
|
|
624
|
+
# 'minecraft:villager{VillagerData:{type:"minecraft:desert"}}'
|
|
625
|
+
len(MCVillagerProfessions), len(MCVillagerTypes) # (15, 7)
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
Which profession an old pair is comes from the game's own code for upgrading old villagers, run on each pair. The pairs an old version has are the ones its own trade table lists. That code also gives every old villager its type: plains.
|
|
629
|
+
|
|
630
|
+
## Dimensions
|
|
631
|
+
|
|
632
|
+
`MCDimensions` is the catalogue of dimensions: what `/execute in` takes, from 1.13, when the command came. Before it, a dimension is the number the game saves it by, as in a player's `Dimension:-1`:
|
|
633
|
+
|
|
634
|
+
```python
|
|
635
|
+
from mcdex import MCDimensions
|
|
636
|
+
|
|
637
|
+
theNether = MCDimensions['the_nether']
|
|
638
|
+
|
|
639
|
+
theNether['1.12.2'].minecraftId # '-1'
|
|
640
|
+
theNether['1.13'].minecraftId # 'minecraft:the_nether'
|
|
641
|
+
MCDimensions['the_end']['1.7.10'].minecraftId # '1'
|
|
642
|
+
len(MCDimensions) # 3
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
Each version's dimensions come from its own code. 1.7 and 1.8 make a dimension's world from its number, and that code is run on every number. 1.9 to 1.13 list them in one enum, and later versions register them by name. Which old number is which dimension comes from the game's own code for upgrading old dimension numbers.
|
|
646
|
+
|
|
647
|
+
## Damage types
|
|
648
|
+
|
|
649
|
+
`MCDamageTypes` is the catalogue of damage types: what `/damage` takes. Damage types came in 1.19.4 with the command, defined in the game's data pack:
|
|
650
|
+
|
|
651
|
+
```python
|
|
652
|
+
from mcdex import MCDamageTypes
|
|
653
|
+
|
|
654
|
+
inFire = MCDamageTypes['in_fire']
|
|
655
|
+
|
|
656
|
+
inFire['1.19.4'].minecraftId # 'minecraft:in_fire'
|
|
657
|
+
MCDamageTypes['mace_smash']['1.21.2'].minecraftId # 'minecraft:mace_smash'
|
|
658
|
+
len(MCDamageTypes) # 51
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
Each version's damage types are the keys its code declares for them, each checked against the version's data pack. None has been renamed or removed yet.
|
|
662
|
+
|
|
663
|
+
## Armor trims
|
|
664
|
+
|
|
665
|
+
`MCTrimPatterns` and `MCTrimMaterials` are the catalogues of an armor trim's pattern and its material, as an armor piece's `trim` takes them. Trims came in 1.19.4 in the experimental 1.20 pack, and are in the game itself from 1.20:
|
|
666
|
+
|
|
667
|
+
```python
|
|
668
|
+
from mcdex import MCTrimMaterials, MCTrimPatterns
|
|
669
|
+
|
|
670
|
+
MCTrimPatterns['coast']['1.19.4'].minecraftId # 'minecraft:coast'
|
|
671
|
+
MCTrimPatterns['bolt']['1.20.5'].minecraftId # 'minecraft:bolt'
|
|
672
|
+
MCTrimMaterials['resin']['1.21.4'].minecraftId # 'minecraft:resin'
|
|
673
|
+
len(MCTrimPatterns), len(MCTrimMaterials) # (18, 11)
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
Each version's patterns and materials are the keys its code declares for them, each checked against the version's data pack or its experimental packs. How it goes inside an item in each version, and the command that gives one: [Ids that go inside an item](#ids-that-go-inside-an-item).
|
|
677
|
+
|
|
678
|
+
## Music
|
|
679
|
+
|
|
680
|
+
`Music` is the catalogue of the songs music discs play: what an item's `jukebox_playable` component takes. Songs came in 1.21, defined in the game's data pack; before, a song was only its music disc, an item. The songs named by a number have the number spelled out: `Music.Thirteen` is the song `13`.
|
|
681
|
+
|
|
682
|
+
```python
|
|
683
|
+
from mcdex import Music
|
|
684
|
+
|
|
685
|
+
pigstep = Music.Pigstep
|
|
686
|
+
|
|
687
|
+
pigstep['1.21'].minecraftId # 'minecraft:pigstep'
|
|
688
|
+
Music['13'] is Music.Thirteen # True
|
|
689
|
+
Music.Tears['1.21.6'].minecraftId # 'minecraft:tears'
|
|
690
|
+
len(Music) # 22
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
Each version's songs are the keys its code declares for them, each checked against the version's data pack. How it goes inside an item in each version, and the command that gives one: [Ids that go inside an item](#ids-that-go-inside-an-item).
|
|
694
|
+
|
|
695
|
+
## Mob variants
|
|
696
|
+
|
|
697
|
+
The mobs that come in variants each have a catalogue of them: their looks, and from 1.21.5 their sounds. A variant's id is what `/summon` takes for a mob of that variant, the mob with its data, as an entity's id is: the variant goes under the key the mob's own code saves it under, `variant` or `sound_variant`. Each kind is defined in the game's data pack, except the cat's and the frog's before 1.21.5, which the code registered. Before a mob had variants of a kind, every one of it was the one variant its code makes it with, its default: every wolf was pale. That variant's id there is the mob itself:
|
|
698
|
+
|
|
699
|
+
```python
|
|
700
|
+
from mcdex import MCCatVariants, MCFrogVariants, MCWolfSoundVariants
|
|
701
|
+
from mcdex import MCWolfVariants
|
|
702
|
+
|
|
703
|
+
black = MCCatVariants['black']
|
|
704
|
+
|
|
705
|
+
black['1.12.2'].minecraftId # 'minecraft:ocelot{CatType:1}'
|
|
706
|
+
black['1.18.2'].minecraftId # 'minecraft:cat{CatType:1}'
|
|
707
|
+
black['1.19'].minecraftId # 'minecraft:cat{variant:"minecraft:black"}'
|
|
708
|
+
MCCatVariants['tabby']['1.14'].minecraftId # 'minecraft:cat{CatType:0}'
|
|
709
|
+
MCFrogVariants['warm']['1.19'].minecraftId # 'minecraft:frog{variant:"minecraft:warm"}'
|
|
710
|
+
MCWolfVariants['pale']['1.12.2'].minecraftId # 'minecraft:wolf'
|
|
711
|
+
MCWolfVariants['ashen']['1.20.5'].minecraftId # 'minecraft:wolf{variant:"minecraft:ashen"}'
|
|
712
|
+
MCWolfSoundVariants['classic']['1.20.4'].minecraftId # 'minecraft:wolf'
|
|
713
|
+
MCWolfSoundVariants['puglin']['1.21.5'].minecraftId # 'minecraft:wolf{sound_variant:"minecraft:puglin"}'
|
|
714
|
+
```
|
|
715
|
+
|
|
716
|
+
Before 1.19 a cat's variant was its number, its `CatType`. Before 1.14, when the cat was not yet an entity of its own, it was a tamed ocelot's number, so only the black, red and siamese cats go back that far. Which number is which variant comes from the game's own code for upgrading old cats: its split of the ocelot, its names for the numbers, and its rename of `british` to `british_shorthair`.
|
|
717
|
+
|
|
718
|
+
So a variant's id splits into a `/summon` command as an entity's does, as the recipe below shows: `minecraft:cat{variant:"minecraft:black"}` is `/summon minecraft:cat ~ ~ ~ {variant:"minecraft:black"}`.
|
|
719
|
+
|
|
720
|
+
| Catalogue | Names from | Default, the mob before | In 26.3 |
|
|
721
|
+
|---|---|---|---|
|
|
722
|
+
| `MCCatVariants` | 1.19 | none: numbers from 1.7.2 | 11 |
|
|
723
|
+
| `MCFrogVariants` | 1.19 | none | 3 |
|
|
724
|
+
| `MCWolfVariants` | 1.20.5 | `pale` | 9 |
|
|
725
|
+
| `MCPigVariants`, `MCCowVariants`, `MCChickenVariants` | 1.21.5 | `temperate` | 3 each |
|
|
726
|
+
| `MCWolfSoundVariants` | 1.21.5 | `classic` | 7 |
|
|
727
|
+
| `MCZombieNautilusVariants` | 1.21.11 | none | 2 |
|
|
728
|
+
| `MCCatSoundVariants`, `MCPigSoundVariants`, `MCCowSoundVariants`, `MCChickenSoundVariants` | 26.1 | `classic` | 2, 3, 2 and 2 |
|
|
729
|
+
|
|
730
|
+
## Paintings
|
|
731
|
+
|
|
732
|
+
`MCPaintingVariants` is the catalogue of paintings, the pictures a painting shows. An id is what `/summon` takes for a painting of that picture, the painting with its data, as the mobs' variants are: its `Motive`, and from 1.19 its `variant`, the key checked against each version's own painting code. Up to 1.12.2 a picture was its title; from 1.13 a registry name, and from 1.21 an entry of the game's data pack:
|
|
733
|
+
|
|
734
|
+
```python
|
|
735
|
+
from mcdex import MCPaintingVariants
|
|
736
|
+
|
|
737
|
+
donkeyKong = MCPaintingVariants['donkey_kong']
|
|
738
|
+
|
|
739
|
+
donkeyKong['1.7.10'].minecraftId # 'Painting{Motive:"DonkeyKong"}'
|
|
740
|
+
donkeyKong['1.12.2'].minecraftId # 'minecraft:painting{Motive:"DonkeyKong"}'
|
|
741
|
+
donkeyKong['1.13'].minecraftId # 'minecraft:painting{Motive:"minecraft:donkey_kong"}'
|
|
742
|
+
MCPaintingVariants['earth']['1.19'].minecraftId # 'minecraft:painting{variant:"minecraft:earth"}'
|
|
743
|
+
len(MCPaintingVariants) # 51
|
|
744
|
+
```
|
|
745
|
+
|
|
746
|
+
Which old title is which painting comes from the game's own code for upgrading old paintings, run on each title. No painting has been removed.
|
|
747
|
+
|
|
748
|
+
## Banner patterns
|
|
749
|
+
|
|
750
|
+
`MCBannerPatterns` is the catalogue of banner patterns: what a banner's patterns take for each, from 1.8, when banners came. Up to 1.20.4 a pattern was its code, as in `Patterns:[{Pattern:"bl",Color:1}]`; from 1.20.5 it is a name, an entry of the game's data pack:
|
|
751
|
+
|
|
752
|
+
```python
|
|
753
|
+
from mcdex import MCBannerPatterns
|
|
754
|
+
|
|
755
|
+
squareBottomLeft = MCBannerPatterns['square_bottom_left']
|
|
756
|
+
|
|
757
|
+
squareBottomLeft['1.8'].minecraftId # 'bl'
|
|
758
|
+
squareBottomLeft['1.20.5'].minecraftId # 'minecraft:square_bottom_left'
|
|
759
|
+
MCBannerPatterns['globe']['1.14'].minecraftId # 'glb'
|
|
760
|
+
len(MCBannerPatterns) # 43
|
|
761
|
+
```
|
|
762
|
+
|
|
763
|
+
Which code is which pattern comes from the game's own table for upgrading old banners. From 1.19 to 1.20.4 the game registered each pattern with its code, and each of those agrees with the table. How it goes inside an item in each version, and the command that gives one: [Ids that go inside an item](#ids-that-go-inside-an-item).
|
|
764
|
+
|
|
765
|
+
## Advancements
|
|
766
|
+
|
|
767
|
+
`MCAdvancements` is the catalogue of advancements: what `/advancement` takes, from 1.12, when advancements came. The advancements that unlock recipes, `recipes/...`, are in too. An advancement's unique name is its name without the namespace, slashes and all:
|
|
768
|
+
|
|
769
|
+
```python
|
|
770
|
+
from mcdex import MCAdvancements
|
|
771
|
+
|
|
772
|
+
mineStone = MCAdvancements['story/mine_stone']
|
|
773
|
+
useLodestone = MCAdvancements['adventure/use_lodestone']
|
|
774
|
+
|
|
775
|
+
mineStone['1.12'].minecraftId # 'minecraft:story/mine_stone'
|
|
776
|
+
useLodestone['1.16'].minecraftId # 'minecraft:nether/use_lodestone'
|
|
777
|
+
useLodestone['1.21.5'].minecraftId # 'minecraft:adventure/use_lodestone'
|
|
778
|
+
len(MCAdvancements) # 1984
|
|
779
|
+
```
|
|
780
|
+
|
|
781
|
+
Each version's advancements are the files of its own data pack, which the game loads them from. Which old advancement is which comes from the game's own advancement renames. Where the game moved or renamed one without such a rename, as many recipe advancements, the old one is removed and the new one added.
|
|
782
|
+
|
|
783
|
+
## Structures
|
|
784
|
+
|
|
785
|
+
`MCStructures` is the catalogue of structures: what `/locate` takes, from 1.11, when the command came, and before it the name the game saves a structure by. Before 1.19 one structure of the game could be several of today's: the village was the village of every kind of biome. There the id is the old structure, with what makes it the one kind, in the game's own data:
|
|
786
|
+
|
|
787
|
+
```python
|
|
788
|
+
from mcdex import MCStructures
|
|
789
|
+
|
|
790
|
+
villagePlains = MCStructures['village_plains']
|
|
791
|
+
|
|
792
|
+
villagePlains['1.7.10'].minecraftId # 'Village{Children:[{Desert:0b}]}'
|
|
793
|
+
villagePlains['1.12.2'].minecraftId # 'Village{Children:[{Type:0b}]}'
|
|
794
|
+
villagePlains['1.14'].minecraftId # 'Village{start_pool:"village/plains/town_centers"}'
|
|
795
|
+
villagePlains['1.19'].minecraftId # 'minecraft:village_plains'
|
|
796
|
+
MCStructures['desert_pyramid']['1.12.2'].minecraftId
|
|
797
|
+
# 'Temple{Children:[{id:"TeDP"}]}'
|
|
798
|
+
MCStructures['mineshaft_mesa']['1.18.2'].minecraftId
|
|
799
|
+
# 'minecraft:mineshaft{Children:[{MST:1}]}'
|
|
800
|
+
len(MCStructures) # 52
|
|
801
|
+
```
|
|
802
|
+
|
|
803
|
+
What makes the kind is the data the structure's pieces are saved with where they carry it: a temple's first piece, a village piece's `Desert` or `Type`, a mineshaft's `MST`, a shipwreck's `isBeached`, an ocean ruin's `BiomeType`. Otherwise it is what the structure is configured with: a village's start pool from 1.14, a ruined portal's type. A kind a version's code does not make is not in that version, as the snowy village before 1.14.
|
|
804
|
+
|
|
805
|
+
Which old structure is which comes from the game's own code: its upgrade of old temples by their first piece, its lower-casing of the old names in 1.16, its renames for 1.19, and the names 1.16.2 to 1.18.2 already give each configured kind, as `village_plains` for the village with the plains start pool. An old village's `Type` is the type 1.13 builds the villages of a biome with, and the game's upgrade code names the village of that biome.
|
|
806
|
+
|
|
807
|
+
## Versions
|
|
808
|
+
|
|
809
|
+
`Version` enumerates every release from 1.0 to 26.3, 103 of them, in the order Mojang released them. Each member holds its `MCVersion`. A member resolves from its name, from its `MCVersion`, or from the text the game reports, and members compare as versions:
|
|
810
|
+
|
|
811
|
+
```python
|
|
812
|
+
from mcdex import MCVersion, Version
|
|
813
|
+
|
|
814
|
+
Version('1.7.10') # <Version>.V1_7_10
|
|
815
|
+
Version('v1_7_10') # <Version>.V1_7_10
|
|
816
|
+
Version(MCVersion(26, 3)) # <Version>.V26_3
|
|
817
|
+
Version.V1_7_10.value # MCVersion(1, 7, 10)
|
|
818
|
+
str(Version.V26_3.value) # '26.3'
|
|
819
|
+
Version.V1_9 < Version.V1_10 # True, as numbers, not text
|
|
820
|
+
len(Version) # 103
|
|
821
|
+
```
|
|
822
|
+
|
|
823
|
+
Only real releases are members: there was never a 1.2 (the first was 1.2.1) nor a 1.5 (1.5.1), and `Version('1.2')` raises `KeeResolveError`. Since 26.1, Mojang numbers its releases by year.
|
|
824
|
+
|
|
825
|
+
`MCVersion` is the version itself, for the ones `Version` leaves out, such as a snapshot's release number:
|
|
826
|
+
|
|
827
|
+
```python
|
|
828
|
+
MCVersion('1.21.11') # MCVersion(1, 21, 11)
|
|
829
|
+
MCVersion(26, 4) > Version.V26_3.value # True
|
|
830
|
+
str(MCVersion(1, 8, 0)) # '1.8'
|
|
831
|
+
```
|
|
832
|
+
|
|
833
|
+
## Equipment slots
|
|
834
|
+
|
|
835
|
+
`EquipmentSlot` enumerates the slots an entity equips an item to, in the order of the game's own enumeration, each holding the name the game serializes it by:
|
|
836
|
+
|
|
837
|
+
```python
|
|
838
|
+
from mcdex import EquipmentSlot
|
|
839
|
+
|
|
840
|
+
list(EquipmentSlot)
|
|
841
|
+
# [<EquipmentSlot>.MAINHAND, <EquipmentSlot>.OFFHAND, <EquipmentSlot>.FEET,
|
|
842
|
+
# <EquipmentSlot>.LEGS, <EquipmentSlot>.CHEST, <EquipmentSlot>.HEAD,
|
|
843
|
+
# <EquipmentSlot>.BODY, <EquipmentSlot>.SADDLE]
|
|
844
|
+
|
|
845
|
+
EquipmentSlot('chest') # <EquipmentSlot>.CHEST
|
|
846
|
+
EquipmentSlot.CHEST.value # 'chest'
|
|
847
|
+
```
|
|
848
|
+
|
|
849
|
+
The offhand arrived in 1.9, the body in 1.20.5 and the saddle in 1.21.5. Before each, an item that would go there went to the main hand.
|
|
850
|
+
|
|
851
|
+
## Item ids
|
|
852
|
+
|
|
853
|
+
`ItemId` is what indexing an item by a version gives: the item's `uniqueName` and its `minecraftId` in that version. Its text is the `minecraftId`, and it compares and hashes by both strings:
|
|
854
|
+
|
|
855
|
+
```python
|
|
856
|
+
from mcdex import ItemId
|
|
857
|
+
|
|
858
|
+
id_ = ItemId('pink_wool', 'minecraft:wool:6')
|
|
859
|
+
id_.uniqueName # 'pink_wool'
|
|
860
|
+
id_.minecraftId # 'minecraft:wool:6'
|
|
861
|
+
str(id_) # 'minecraft:wool:6'
|
|
862
|
+
id_ == ItemId('pink_wool', 'minecraft:wool:6') # True
|
|
863
|
+
```
|
|
864
|
+
|
|
865
|
+
## Entity ids
|
|
866
|
+
|
|
867
|
+
`EntityId` is what indexing an entity by a version gives: the entity's `uniqueName` and its `minecraftId` in that version. It works like `ItemId`, but an entity's id is never an item's, even with the same text:
|
|
868
|
+
|
|
869
|
+
```python
|
|
870
|
+
from mcdex import EntityId, ItemId
|
|
871
|
+
|
|
872
|
+
id_ = EntityId('wither_skeleton', 'Skeleton{SkeletonType:1}')
|
|
873
|
+
id_.uniqueName # 'wither_skeleton'
|
|
874
|
+
id_.minecraftId # 'Skeleton{SkeletonType:1}'
|
|
875
|
+
str(id_) # 'Skeleton{SkeletonType:1}'
|
|
876
|
+
EntityId('pig', 'minecraft:pig') == ItemId('pig', 'minecraft:pig') # False
|
|
877
|
+
```
|
|
878
|
+
|
|
879
|
+
## Block ids
|
|
880
|
+
|
|
881
|
+
`BlockId` is what indexing a block by a version gives, as `ItemId` and `EntityId` are for items and entities. An id of one kind is never equal to an id of another, even with the same text:
|
|
882
|
+
|
|
883
|
+
```python
|
|
884
|
+
from mcdex import BlockId, EntityId
|
|
885
|
+
|
|
886
|
+
BlockId('tnt', 'minecraft:tnt') == EntityId('tnt', 'minecraft:tnt') # False
|
|
887
|
+
```
|
|
888
|
+
|
|
889
|
+
## Recipes
|
|
890
|
+
|
|
891
|
+
### A /summon command for any version
|
|
892
|
+
|
|
893
|
+
`/summon` takes the entity, then the place, then the data:
|
|
894
|
+
|
|
895
|
+
```python
|
|
896
|
+
from mcdex import MCEntities
|
|
897
|
+
|
|
898
|
+
|
|
899
|
+
def summonCommand(name: str, version: str, where: str = '~ ~ ~') -> str:
|
|
900
|
+
minecraftId = MCEntities[name][version].minecraftId
|
|
901
|
+
base, brace, nbt = minecraftId.partition('{')
|
|
902
|
+
return ' '.join(['/summon', base, where] + ([brace + nbt] if nbt else []))
|
|
903
|
+
|
|
904
|
+
|
|
905
|
+
summonCommand('wither_skeleton', '1.10.2')
|
|
906
|
+
# '/summon Skeleton ~ ~ ~ {SkeletonType:1}'
|
|
907
|
+
summonCommand('wither_skeleton', '26.3')
|
|
908
|
+
# '/summon minecraft:wither_skeleton ~ ~ ~'
|
|
909
|
+
summonCommand('spruce_boat', '1.12.2')
|
|
910
|
+
# '/summon minecraft:boat ~ ~ ~ {Type:"spruce"}'
|
|
911
|
+
```
|
|
912
|
+
|
|
913
|
+
### A /give command for any version
|
|
914
|
+
|
|
915
|
+
The command changed shape at 1.13: before it, the meta and the NBT came after the count; since, the NBT follows the name.
|
|
916
|
+
|
|
917
|
+
```python
|
|
918
|
+
from mcdex import MCItems, Version
|
|
919
|
+
|
|
920
|
+
|
|
921
|
+
def giveCommand(name: str, version: str, count: int = 1) -> str:
|
|
922
|
+
version_ = Version(version)
|
|
923
|
+
minecraftId = MCItems[name][version_].minecraftId
|
|
924
|
+
base, brace, nbt = minecraftId.partition('{')
|
|
925
|
+
nbt = brace + nbt
|
|
926
|
+
if version_ < Version.V1_13:
|
|
927
|
+
namespace, path, *meta = base.split(':')
|
|
928
|
+
words = ['/give', '@p', '%s:%s' % (namespace, path), str(count),
|
|
929
|
+
meta[0] if meta else '0']
|
|
930
|
+
return ' '.join(words + ([nbt] if nbt else []))
|
|
931
|
+
return '/give @p %s%s %d' % (base, nbt, count)
|
|
932
|
+
|
|
933
|
+
|
|
934
|
+
giveCommand('pink_wool', '1.7.10')
|
|
935
|
+
# '/give @p minecraft:wool 1 6'
|
|
936
|
+
giveCommand('pink_wool', '26.3')
|
|
937
|
+
# '/give @p minecraft:pink_wool 1'
|
|
938
|
+
giveCommand('creeper_spawn_egg', '1.8.9')
|
|
939
|
+
# '/give @p minecraft:spawn_egg 1 50'
|
|
940
|
+
giveCommand('creeper_spawn_egg', '1.12.2')
|
|
941
|
+
# '/give @p minecraft:spawn_egg 1 0 {EntityTag:{id:"minecraft:creeper"}}'
|
|
942
|
+
giveCommand('splash_potion', '1.8.9')
|
|
943
|
+
# '/give @p minecraft:potion 1 16384'
|
|
944
|
+
```
|
|
945
|
+
|
|
946
|
+
### Ids that go inside an item
|
|
947
|
+
|
|
948
|
+
A potion, a banner pattern, an armor trim and a jukebox song are each right on their own, but a command takes them only inside an item's data: `MCPotions['swiftness']['1.20.4'].minecraftId` is what a potion item's `Potion` holds. Where that data is, and its shape, changed over the versions. Each version's own code was read for it; the colours of a banner's layers come from the game's own upgrade code for banners.
|
|
949
|
+
|
|
950
|
+
| What | Inside the item | Versions |
|
|
951
|
+
|---|---|---|
|
|
952
|
+
| Potion | the damage value: the potion's number, plus 16384 for a splash potion | 1.7.2 to 1.8.9 |
|
|
953
|
+
| | `{Potion:"minecraft:swiftness"}` | 1.9 to 1.20.4 |
|
|
954
|
+
| | `[potion_contents={potion:"minecraft:swiftness"}]` | from 1.20.5 |
|
|
955
|
+
| Banner pattern | `{BlockEntityTag:{Patterns:[{Pattern:"bl",Color:1}]}}`, the colour's number counted from black | 1.8 to 1.12.2 |
|
|
956
|
+
| | `{BlockEntityTag:{Patterns:[{Pattern:"bl",Color:14}]}}`, counted from white | 1.13 to 1.20.4 |
|
|
957
|
+
| | `[banner_patterns=[{pattern:"minecraft:square_bottom_left",color:"red"}]]` | from 1.20.5 |
|
|
958
|
+
| Armor trim | `{Trim:{pattern:"minecraft:coast",material:"minecraft:amethyst"}}` | 1.19.4 to 1.20.4 |
|
|
959
|
+
| | `[trim={pattern:"minecraft:coast",material:"minecraft:amethyst"}]` | from 1.20.5 |
|
|
960
|
+
| Jukebox song | `[jukebox_playable={song:"minecraft:pigstep"}]` | 1.21 to 1.21.4 |
|
|
961
|
+
| | `[jukebox_playable="minecraft:pigstep"]` | from 1.21.5 |
|
|
962
|
+
|
|
963
|
+
The commands, built from mcdex's ids:
|
|
964
|
+
|
|
965
|
+
```python
|
|
966
|
+
from mcdex import MCBannerPatterns, MCItems, MCPotions, Music
|
|
967
|
+
from mcdex import MCTrimMaterials, MCTrimPatterns, Version
|
|
968
|
+
|
|
969
|
+
# The colours as 1.13 to 1.20.4 number them, and 1.20.5 names them.
|
|
970
|
+
DYES = ['white', 'orange', 'magenta', 'light_blue', 'yellow', 'lime', 'pink',
|
|
971
|
+
'gray', 'light_gray', 'cyan', 'purple', 'blue', 'brown', 'green',
|
|
972
|
+
'red', 'black']
|
|
973
|
+
|
|
974
|
+
|
|
975
|
+
def give(item: str, version: str, inside: str = '', meta: int = -1) -> str:
|
|
976
|
+
"""'/give' for an item of a version, with what goes inside it."""
|
|
977
|
+
version_ = Version(version)
|
|
978
|
+
namespace, path, *old = MCItems[item][version_].minecraftId.split(':')
|
|
979
|
+
if version_ < Version.V1_13:
|
|
980
|
+
if meta < 0:
|
|
981
|
+
meta = int(old[0]) if old else 0
|
|
982
|
+
words = ['/give @p %s:%s 1 %d' % (namespace, path, meta)]
|
|
983
|
+
return ' '.join(words + ([inside] if inside else []))
|
|
984
|
+
return '/give @p %s:%s%s 1' % (namespace, path, inside)
|
|
985
|
+
|
|
986
|
+
|
|
987
|
+
def potionCommand(item: str, potion: str | tuple, version: str) -> str:
|
|
988
|
+
"""A potion item of a potion, or of a base potion and a modifier."""
|
|
989
|
+
version_ = Version(version)
|
|
990
|
+
potionId = MCPotions[potion][version_].minecraftId
|
|
991
|
+
if version_ < Version.V1_9:
|
|
992
|
+
old = MCItems[item][version_].minecraftId.split(':')[2:] or ['0']
|
|
993
|
+
return give(item, version, meta=int(old[0]) | int(potionId))
|
|
994
|
+
if version_ < Version.V1_20_5:
|
|
995
|
+
return give(item, version, '{Potion:"%s"}' % potionId)
|
|
996
|
+
return give(item, version, '[potion_contents={potion:"%s"}]' % potionId)
|
|
997
|
+
|
|
998
|
+
|
|
999
|
+
def bannerCommand(banner: str, pattern: str, color: str, version: str) -> str:
|
|
1000
|
+
version_ = Version(version)
|
|
1001
|
+
patternId = MCBannerPatterns[pattern][version_].minecraftId
|
|
1002
|
+
if version_ < Version.V1_20_5:
|
|
1003
|
+
number = DYES.index(color)
|
|
1004
|
+
if version_ < Version.V1_13:
|
|
1005
|
+
number = 15 - number
|
|
1006
|
+
return give(banner, version, '{BlockEntityTag:{Patterns:[{Pattern:"%s",'
|
|
1007
|
+
'Color:%d}]}}' % (patternId, number))
|
|
1008
|
+
return give(banner, version, '[banner_patterns=[{pattern:"%s",color:"%s"}]]'
|
|
1009
|
+
% (patternId, color))
|
|
1010
|
+
|
|
1011
|
+
|
|
1012
|
+
def trimCommand(armor: str, pattern: str, material: str, version: str) -> str:
|
|
1013
|
+
version_ = Version(version)
|
|
1014
|
+
trim = 'pattern:"%s",material:"%s"' % (
|
|
1015
|
+
MCTrimPatterns[pattern][version_].minecraftId,
|
|
1016
|
+
MCTrimMaterials[material][version_].minecraftId)
|
|
1017
|
+
if version_ < Version.V1_20_5:
|
|
1018
|
+
return give(armor, version, '{Trim:{%s}}' % trim)
|
|
1019
|
+
return give(armor, version, '[trim={%s}]' % trim)
|
|
1020
|
+
|
|
1021
|
+
|
|
1022
|
+
def songCommand(item: str, song: str, version: str) -> str:
|
|
1023
|
+
version_ = Version(version)
|
|
1024
|
+
songId = Music[song][version_].minecraftId
|
|
1025
|
+
if version_ < Version.V1_21_5:
|
|
1026
|
+
return give(item, version, '[jukebox_playable={song:"%s"}]' % songId)
|
|
1027
|
+
return give(item, version, '[jukebox_playable="%s"]' % songId)
|
|
1028
|
+
|
|
1029
|
+
|
|
1030
|
+
potionCommand('splash_potion', 'swiftness', '1.8.9')
|
|
1031
|
+
# '/give @p minecraft:potion 1 16386'
|
|
1032
|
+
potionCommand('splash_potion', 'swiftness', '1.12.2')
|
|
1033
|
+
# '/give @p minecraft:splash_potion 1 0 {Potion:"minecraft:swiftness"}'
|
|
1034
|
+
potionCommand('splash_potion', ('night_vision', 'long'), '1.12.2')
|
|
1035
|
+
# '/give @p minecraft:splash_potion 1 0 {Potion:"minecraft:long_night_vision"}'
|
|
1036
|
+
potionCommand('splash_potion', ('night_vision', 'long'), '1.8.9')
|
|
1037
|
+
# '/give @p minecraft:potion 1 16454'
|
|
1038
|
+
potionCommand('potion', 'swiftness', '26.3')
|
|
1039
|
+
# '/give @p minecraft:potion[potion_contents={potion:"minecraft:swiftness"}] 1'
|
|
1040
|
+
bannerCommand('white_banner', 'square_bottom_left', 'red', '1.12.2')
|
|
1041
|
+
# '/give @p minecraft:banner 1 15 {BlockEntityTag:{Patterns:[{Pattern:"bl",Color:1}]}}'
|
|
1042
|
+
bannerCommand('white_banner', 'square_bottom_left', 'red', '1.20.4')
|
|
1043
|
+
# '/give @p minecraft:white_banner{BlockEntityTag:{Patterns:[{Pattern:"bl",Color:14}]}} 1'
|
|
1044
|
+
bannerCommand('white_banner', 'square_bottom_left', 'red', '1.20.5')
|
|
1045
|
+
# '/give @p minecraft:white_banner[banner_patterns=[{pattern:"minecraft:square_bottom_left",color:"red"}]] 1'
|
|
1046
|
+
trimCommand('iron_chestplate', 'coast', 'amethyst', '1.20')
|
|
1047
|
+
# '/give @p minecraft:iron_chestplate{Trim:{pattern:"minecraft:coast",material:"minecraft:amethyst"}} 1'
|
|
1048
|
+
songCommand('diamond', 'pigstep', '1.21.4')
|
|
1049
|
+
# '/give @p minecraft:diamond[jukebox_playable={song:"minecraft:pigstep"}] 1'
|
|
1050
|
+
songCommand('diamond', 'pigstep', '26.3')
|
|
1051
|
+
# '/give @p minecraft:diamond[jukebox_playable="minecraft:pigstep"] 1'
|
|
1052
|
+
```
|
|
1053
|
+
|
|
1054
|
+
A structure's id before 1.19 is the same kind of thing: `/locate` takes the part before the braces, and the braces say which of today's structures it is in that version's data. `Village{Children:[{Type:0b}]}` is found with `/locate Village`.
|
|
1055
|
+
|
|
1056
|
+
### A test that does not know its version
|
|
1057
|
+
|
|
1058
|
+
mcdex exists for tests that run unchanged against any version. This is a test's pre-check, written once for the elytra, which fails with the reason when a version cannot have the elytra glide:
|
|
1059
|
+
|
|
1060
|
+
```python
|
|
1061
|
+
from mcdex import EquipmentSlot, MCItems, NotInVersion, Version
|
|
1062
|
+
|
|
1063
|
+
|
|
1064
|
+
def elytraPreTest(version: str) -> str:
|
|
1065
|
+
elytra = MCItems['elytra']
|
|
1066
|
+
try:
|
|
1067
|
+
id_ = elytra[version]
|
|
1068
|
+
except NotInVersion as exception:
|
|
1069
|
+
return 'FAIL: %s' % exception
|
|
1070
|
+
slot = elytra.equipmentSlot[Version(version)]
|
|
1071
|
+
if slot is not EquipmentSlot.CHEST:
|
|
1072
|
+
return 'FAIL: the elytra goes to %s, not the chest' % slot.value
|
|
1073
|
+
return 'ok: equip %s to the chest' % id_.minecraftId
|
|
1074
|
+
|
|
1075
|
+
|
|
1076
|
+
elytraPreTest('1.7.10') # "FAIL: Vanilla 1.7.10 has no 'elytra'; vanilla added it in 1.9!"
|
|
1077
|
+
elytraPreTest('1.9') # 'ok: equip minecraft:elytra to the chest'
|
|
1078
|
+
elytraPreTest('26.3') # 'ok: equip minecraft:elytra to the chest'
|
|
1079
|
+
```
|
|
1080
|
+
|
|
1081
|
+
### What a version renamed
|
|
1082
|
+
|
|
1083
|
+
```python
|
|
1084
|
+
from mcdex import MCItems, NotInVersion, Version
|
|
1085
|
+
|
|
1086
|
+
|
|
1087
|
+
def renamed(old: str, new: str) -> list[tuple[str, str, str]]:
|
|
1088
|
+
old, new = Version(old), Version(new)
|
|
1089
|
+
found = []
|
|
1090
|
+
for item in MCItems:
|
|
1091
|
+
try:
|
|
1092
|
+
before, after = item[old].minecraftId, item[new].minecraftId
|
|
1093
|
+
except NotInVersion:
|
|
1094
|
+
continue
|
|
1095
|
+
if before != after:
|
|
1096
|
+
found.append((item.uniqueName, before, after))
|
|
1097
|
+
return found
|
|
1098
|
+
|
|
1099
|
+
|
|
1100
|
+
renamed('1.21.8', '1.21.9')
|
|
1101
|
+
# [('iron_chain', 'minecraft:chain', 'minecraft:iron_chain')]
|
|
1102
|
+
renamed('1.20.2', '1.20.3')
|
|
1103
|
+
# [('grass', 'minecraft:grass', 'minecraft:short_grass'),
|
|
1104
|
+
# ('short_grass', 'minecraft:grass', 'minecraft:short_grass')]
|
|
1105
|
+
len(renamed('1.12.2', '1.13'))
|
|
1106
|
+
# 369, the flattening
|
|
1107
|
+
```
|
|
1108
|
+
|
|
1109
|
+
### What a version added
|
|
1110
|
+
|
|
1111
|
+
```python
|
|
1112
|
+
from mcdex import MCItems, NotInVersion, Version
|
|
1113
|
+
|
|
1114
|
+
|
|
1115
|
+
def added(version: str) -> list[str]:
|
|
1116
|
+
versions = list(Version)
|
|
1117
|
+
new = Version(version)
|
|
1118
|
+
old = versions[versions.index(new) - 1]
|
|
1119
|
+
found = []
|
|
1120
|
+
for item in MCItems:
|
|
1121
|
+
try:
|
|
1122
|
+
item[new]
|
|
1123
|
+
except NotInVersion:
|
|
1124
|
+
continue
|
|
1125
|
+
try:
|
|
1126
|
+
item[old]
|
|
1127
|
+
except NotInVersion:
|
|
1128
|
+
found.append(item.uniqueName)
|
|
1129
|
+
return found
|
|
1130
|
+
|
|
1131
|
+
|
|
1132
|
+
added('1.21.5')
|
|
1133
|
+
# ['blue_egg', 'brown_egg', 'bush', 'cactus_flower', 'firefly_bush', 'leaf_litter',
|
|
1134
|
+
# 'short_dry_grass', 'tall_dry_grass', 'test_block', 'test_instance_block', 'wildflowers']
|
|
1135
|
+
```
|
|
1136
|
+
|
|
1137
|
+
### Which items a game id is
|
|
1138
|
+
|
|
1139
|
+
The reverse lookup, for reading what a version reports. It gives a list, since an old id can be two items:
|
|
1140
|
+
|
|
1141
|
+
```python
|
|
1142
|
+
from mcdex import MCItems, NotInVersion, Version
|
|
1143
|
+
|
|
1144
|
+
|
|
1145
|
+
def itemsOf(minecraftId: str, version: str) -> list[str]:
|
|
1146
|
+
version_ = Version(version)
|
|
1147
|
+
found = []
|
|
1148
|
+
for item in MCItems:
|
|
1149
|
+
try:
|
|
1150
|
+
if item[version_].minecraftId == minecraftId:
|
|
1151
|
+
found.append(item.uniqueName)
|
|
1152
|
+
except NotInVersion:
|
|
1153
|
+
pass
|
|
1154
|
+
return found
|
|
1155
|
+
|
|
1156
|
+
|
|
1157
|
+
itemsOf('minecraft:wool:6', '1.12.2') # ['pink_wool']
|
|
1158
|
+
itemsOf('minecraft:grass', '1.12.2') # ['grass_block']
|
|
1159
|
+
itemsOf('minecraft:grass', '1.13') # ['grass', 'short_grass']
|
|
1160
|
+
itemsOf('minecraft:purple_shulker_box', '1.12.2') # ['purple_shulker_box', 'shulker_box']
|
|
1161
|
+
```
|
|
1162
|
+
|
|
1163
|
+
### An item's history, change by change
|
|
1164
|
+
|
|
1165
|
+
```python
|
|
1166
|
+
from mcdex import MCItems
|
|
1167
|
+
|
|
1168
|
+
|
|
1169
|
+
def history(name: str) -> list[tuple[str, str]]:
|
|
1170
|
+
changes, last = [], None
|
|
1171
|
+
for version_, id_ in MCItems[name].versionIds.items():
|
|
1172
|
+
if id_ != last:
|
|
1173
|
+
changes.append((str(version_.value), id_))
|
|
1174
|
+
last = id_
|
|
1175
|
+
return changes
|
|
1176
|
+
|
|
1177
|
+
|
|
1178
|
+
history('grass')
|
|
1179
|
+
# [('1.7.2', 'minecraft:tallgrass:1'), ('1.13', 'minecraft:grass'),
|
|
1180
|
+
# ('1.20.3', 'minecraft:short_grass')]
|
|
1181
|
+
history('red_bed')
|
|
1182
|
+
# [('1.7.2', 'minecraft:bed'), ('1.12', 'minecraft:bed:14'), ('1.13', 'minecraft:red_bed')]
|
|
1183
|
+
```
|
|
1184
|
+
|
|
1185
|
+
### Items by slot, items no longer in the game
|
|
1186
|
+
|
|
1187
|
+
```python
|
|
1188
|
+
from mcdex import EquipmentSlot, MCItems, Version
|
|
1189
|
+
|
|
1190
|
+
[item.uniqueName for item in MCItems
|
|
1191
|
+
if item.equipmentSlot.get(Version.V26_3) is EquipmentSlot.HEAD]
|
|
1192
|
+
# ['carved_pumpkin', 'chainmail_helmet', 'copper_helmet', 'creeper_head',
|
|
1193
|
+
# 'diamond_helmet', 'dragon_head', 'golden_helmet', 'iron_helmet', 'leather_helmet',
|
|
1194
|
+
# 'netherite_helmet', 'piglin_head', 'player_head', 'skeleton_skull', 'turtle_helmet',
|
|
1195
|
+
# 'wither_skeleton_skull', 'zombie_head']
|
|
1196
|
+
|
|
1197
|
+
[item.uniqueName for item in MCItems if not item.versionIds[Version.V26_3]]
|
|
1198
|
+
# ['carrots', 'cocoa', 'double_stone_slab', 'double_wooden_slab', 'end_portal', 'fire',
|
|
1199
|
+
# 'flowing_lava', 'flowing_water', 'lava', 'lit_furnace', 'portal', 'potatoes', 'water']
|
|
1200
|
+
```
|
|
1201
|
+
|
|
1202
|
+
The ones gone by 26.3 are the block items 1.7 had for every block, which 1.8 and 1.9 dropped.
|
|
1203
|
+
|
|
1204
|
+
## Where the data comes from
|
|
1205
|
+
|
|
1206
|
+
All of it comes from Mojang's own files: the server jar of every release, the version manifest that lists them, and, for the particles, the client jars of 1.12.2 and 1.13. No third-party dataset is used.
|
|
1207
|
+
|
|
1208
|
+
- **Ids.** Each version's items are read from its server jar by following the game's own code that registers them, as the game would run it, so that names the game builds while starting up are found too. Jars whose names Mojang obfuscated are read through Mojang's own mappings, or, where Mojang published none, by the structure of the code.
|
|
1209
|
+
- **Stack sizes and slots.** They are read off the objects that same registration makes, and off the game's own code deciding an item's slot.
|
|
1210
|
+
- **Which old id is which item.** This comes from the game's own code for upgrading old worlds, in the 26.3 jar: its renames, the 1.13 flattening, and its fixes for beds, spawn eggs and potions, each applied from the data version of the version an id comes from.
|
|
1211
|
+
- **Blocks.**
|
|
1212
|
+
- Up to 1.12.2, the blocks come from each server jar's numeric block registration. From 1.13 they come from the block registry.
|
|
1213
|
+
- Which old block and meta is which block comes from the game's own 1.13 flattening table, then its later renames and the cauldron split.
|
|
1214
|
+
- A block told apart by its block entity takes its data from the tables of the game's chunk upgrade code. That code is run to build them, and each table is checked against the old version's block entity classes.
|
|
1215
|
+
- **Mob effects.** Up to 1.13.2 they come from each jar's numbered effects, and from 1.14 from the mob effect registry. Which old number is which effect comes from the game's own table of effect numbers.
|
|
1216
|
+
- **Enchantments.** Up to 1.12.2 they come from each jar's numbered enchantments. From 1.13 to 1.20.6 they come from the enchantment registry. From 1.21 they come from the keys the code declares, checked against the jar's data pack. Which old number is which comes from the game's own table, then its rename of sweeping to sweeping_edge.
|
|
1217
|
+
- **Potions.** From 1.9 they come from each jar's potion registration, and from 1.14 from the potion registry. Before 1.9 they are the potion item's damage values, named by the game's own upgrade table, and kept where the version's own brewing rules make every effect.
|
|
1218
|
+
- **Biomes.**
|
|
1219
|
+
- Up to 1.8.9 they come from each jar's numbered biomes and the mutations its code makes of them. To 1.16.1 they come from its numbered registration. From 1.16.2 they come from the keys the code declares, checked against the jar's data packs.
|
|
1220
|
+
- Which old biome is which comes from the game's own table of old biome numbers, then its biome renames. Where a rename folds biomes together, the rule above decides which one was renamed.
|
|
1221
|
+
- **Block entities.**
|
|
1222
|
+
- Up to 1.12.2 they come from the names each jar maps its block entity classes to. From 1.13 they come from the block entity type registry.
|
|
1223
|
+
- Which old name is which comes from the game's own table of old names and its renames. The trapped chest shares the chest's old id, as its upgrade fix shows.
|
|
1224
|
+
- **Particles.** From 1.8 to 1.12.2 they come from each jar's particle enum, and from 1.13 from the particle type registry. They are linked across 1.13 by Mojang's own names and by the code of the server and client jars, as the section above says.
|
|
1225
|
+
- **Sounds.** From 1.9 to 1.13.2 they come from each jar's sound registration method, and from 1.14 from the sound event registry. Sounds the game registers in loops, as the goat horns, come from running those methods on their own.
|
|
1226
|
+
- **Attributes.** To 1.15.2 they come from every attribute any class of each jar makes. From 1.16 they come from the attribute registry. Which old name is which comes from the game's own attribute renames.
|
|
1227
|
+
- **Statistics.** To 1.12.2 they come from each jar's list of statistics, and from 1.13 from the custom stat registry. Which old name is which comes from the game's own table of statistics and its renames.
|
|
1228
|
+
- **Game rules.** Until 1.21.11 they come from every call of the helper each jar adds its rules with, and since from the game rule registry. Which old rule is which comes from running the game's own rule upgrade code on each.
|
|
1229
|
+
- **Villager professions and types.**
|
|
1230
|
+
- From 1.14 they come from the registries, read by structure, through the mappings, or from the keys the code declares.
|
|
1231
|
+
- Before 1.14 a profession is the pairs of profession and career in each jar's own trade table. 1.7 has no careers, only the professions its villagers are given. Which old pair is which comes from running the game's own villager upgrade code, which also gives every old villager the plains type.
|
|
1232
|
+
- **Dimensions.** In 1.7 and 1.8 they come from running each jar's code that makes a dimension's world from its number, on every number. From 1.9 to 1.13 they come from each jar's dimension enum, to 1.15.2 from its registration, and from 1.16 from the keys of its levels. Which old number is which comes from the game's own dimension upgrade code.
|
|
1233
|
+
- **Damage types.** From 1.19.4 they come from the keys each jar's code declares for them, found through Mojang's mappings, each checked against the jar's own data pack.
|
|
1234
|
+
- **Armor trims.** From 1.19.4 the patterns and materials come from the keys each jar's code declares for them, each checked against the jar's own data pack or its experimental packs.
|
|
1235
|
+
- **Music.** From 1.21 the songs come from the keys each jar's code declares for them, each checked against the jar's own data pack.
|
|
1236
|
+
- **Mob variants.** From the version each came in, they come from the keys each jar's code declares for them, or the entries it registers, each checked against the jar's own data pack. From 1.14 to 1.18.2 the cats are the numbers of each jar's own table of cat textures, and before 1.14 the ocelot numbers the game's own upgrade code makes cats. A default variant is the one the mob's code defines its data with, as the wolf's `PALE`. Each id's key is checked against the mob's own code in each version.
|
|
1237
|
+
- **Paintings.** Each id is the painting with its picture, under the key each jar's painting code saves it under. To 1.12.2 they come from each jar's enum of paintings, to 1.14.3 from its registration, and from 1.14.4 from running the code that registers them or declares their keys, found through Mojang's mappings and checked against the jar's own data pack from 1.21. Which old title is which painting comes from running the game's own painting upgrade code.
|
|
1238
|
+
- **Banner patterns.** To 1.18.2 they come from each jar's enum of patterns, to 1.20.4 from the code that registers each with its code, and from 1.20.5 from the keys each jar's code declares, checked against its data pack. Which old code is which pattern comes from the game's own table for upgrading banners.
|
|
1239
|
+
- **Advancements.** From 1.12 they come from the files of each jar's own data pack, which the game loads them from. Which old advancement is which comes from the game's own advancement renames.
|
|
1240
|
+
- **Structures.** To 1.15.2 they come from the names each jar registers its structures' starts with, to 1.18.2 from its structure features, and from 1.19 from the keys its code declares, checked against its data pack. The kinds of an old structure come from the data its pieces are saved with, or what it is configured with. Which old structure is which comes from the game's own upgrade code, and from the names 1.16.2 to 1.18.2 give each configured kind.
|
|
1241
|
+
- **Entities.**
|
|
1242
|
+
- Up to 1.12.2, the names come from each server jar's entity list: every class it registers that is not abstract, and the names its code adds itself, `LightningBolt` and `Player`. From 1.13 they come from the entity type registry, read the same way as the items.
|
|
1243
|
+
- Which old entity is which comes from the game's own entity upgrade code in the 26.3 jar: its renames and its splits. That code is run, instruction by instruction, on each old entity and on the data it reads.
|
|
1244
|
+
- A split entity's old id is then checked against the old version's own entity code. That code must read the key, and must allow the value: a number by the enum it is looked up in or the values it is compared with, a word by naming it.
|
|
1245
|
+
|
|
1246
|
+
Checks made while building the data:
|
|
1247
|
+
- 26.3's items, stack sizes and slots equal the game's own generator report for 26.3, item for item.
|
|
1248
|
+
- 1.7.10's items and numeric ids equal the table of old numeric ids in the 26.3 jar.
|
|
1249
|
+
- 1.14.4 read without its mappings equals 1.14.4 read with them.
|
|
1250
|
+
- Every item that disappears between two versions is a rename in the game's own upgrade code.
|
|
1251
|
+
- 26.3's entities equal the game's own generator report for 26.3, in the same order.
|
|
1252
|
+
- 26.3's blocks equal the generator report, in the same order. 1.14 read without its mappings equals 1.14.4 read with them.
|
|
1253
|
+
- Every block of every version is one block's id there, or merges into one, as the lit furnace does.
|
|
1254
|
+
- 26.3's mob effects equal the generator report, in the same order. 1.14 read without its mappings equals 1.14.4.
|
|
1255
|
+
- 26.3's structures are the 52 its code declares, each with its data-pack file. Every kind of an old structure is named by 1.16.2's configured kinds or by the game's upgrade code.
|
|
1256
|
+
- 26.3's advancements are its 1,866 data-pack files.
|
|
1257
|
+
- 26.3's banner patterns are the 43 its code declares, each with its data-pack file. Every code from 1.8 to 1.20.4 is in the game's own upgrade table.
|
|
1258
|
+
- 26.3's paintings are the 51 its code declares, each with its data-pack file. Every version from 1.7.2 to 1.18.2 has its 26 paintings.
|
|
1259
|
+
- 26.3's mob variants and sound variants are the ones its code declares, each with its data-pack file. Every version from 1.7.2 to 1.13.2 has the black, red and siamese cats, as a tamed ocelot's number.
|
|
1260
|
+
- 26.3's songs are the 22 its code declares, each with its data-pack file.
|
|
1261
|
+
- 26.3's trim patterns and materials are the 18 and 11 its code declares, each with its data-pack file.
|
|
1262
|
+
- 26.3's damage types are the 51 its code declares, each with its data-pack file.
|
|
1263
|
+
- Every version from 1.7.2 to 26.3 has the same three dimensions. The game's own upgrade code makes the old numbers -1, 0 and 1 the nether, the overworld and the end.
|
|
1264
|
+
- 26.3's villager professions and types equal the generator report.
|
|
1265
|
+
- 26.3's game rules equal the generator report, in the same order.
|
|
1266
|
+
- 26.3's statistics equal the generator report, in the same order. 1.14 read without its mappings equals 1.14.4.
|
|
1267
|
+
- 26.3's attributes equal the generator report, in the same order.
|
|
1268
|
+
- 26.3's sounds are the generator report's 1,991. Those not made in loops come in the report's order. 1.14 read without its mappings equals 1.14.4.
|
|
1269
|
+
- 26.3's particles equal the generator report, in the same order. 1.14 read without its mappings equals 1.14.4.
|
|
1270
|
+
- 26.3's block entities equal the generator report, in the same order.
|
|
1271
|
+
- 26.3's biomes are the 67 the code declares, each with its data-pack file. Every version from 1.7.2 to 1.8.9 has its 60 numbered biomes.
|
|
1272
|
+
- 26.3's potions equal the generator report, in the same order. 1.14 read without its mappings equals 1.14.4.
|
|
1273
|
+
- 26.3's enchantments are the 43 the code declares, each with its data-pack file. 1.14 read without its mappings equals 1.14.4.
|
|
1274
|
+
- Every name of every version, 1.7.2 to 26.3, is exactly one entity's id in that version.
|
|
1275
|
+
|
|
1276
|
+
Versions before 1.7.2, when the game had only numbers, are not covered yet.
|
|
1277
|
+
|
|
1278
|
+
## Development
|
|
1279
|
+
|
|
1280
|
+
```
|
|
1281
|
+
pip install -e ".[test]"
|
|
1282
|
+
pytest --cov # 100% branch coverage is required
|
|
1283
|
+
```
|
|
1284
|
+
|
|
1285
|
+
Mutation testing with cosmic-ray rewrites the sources while it runs, so run it on a copy of the repository; `cosmic-ray.toml` lists the commands.
|