Botcraft 1.21.10
Loading...
Searching...
No Matches
DataComponents.cpp
Go to the documentation of this file.
1#if PROTOCOL_VERSION > 765 /* > 1.20.4 */
4
39#if PROTOCOL_VERSION < 770 /* < 1.21.5 */
41#endif
45#if PROTOCOL_VERSION > 766 /* > 1.20.6 */
47#endif
48#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
55#endif
56#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
65#endif
66#if PROTOCOL_VERSION > 772 /* > 1.21.8 */
68#endif
69
71
72namespace ProtocolCraft
73{
74 namespace Components
75 {
82#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
84#endif
85#if PROTOCOL_VERSION > 765 /* > 1.20.4 */
87#endif
89#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
91#endif
92#if PROTOCOL_VERSION > 766 /* > 1.20.6 */
94#endif
95#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
98#endif
101#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
103#endif
104#if PROTOCOL_VERSION > 772 /* > 1.21.8 */
107#endif
115
150#if PROTOCOL_VERSION < 770 /* < 1.21.5 */
151 DEFINE_NETWORK_TYPE(DataComponentTypeUnbreakable);
152#endif
156#if PROTOCOL_VERSION > 766 /* > 1.20.6 */
158#endif
159#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
166#endif
167#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
176#endif
177#if PROTOCOL_VERSION > 772 /* > 1.21.8 */
179#endif
180
182 {
183 static constexpr std::array<std::string_view, static_cast<size_t>(DataComponentTypes::NUM_DATA_COMPONENT_TYPES)> names = {
184 "custom_data",
185 "max_stack_size",
186 "max_damage",
187 "damage",
188 "unbreakable",
189 "custom_name",
190 "item_name",
191#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
192 "item_model",
193#endif
194 "lore",
195 "rarity",
196 "enchantments",
197 "can_place_on",
198 "can_break",
199 "attribute_modifiers",
200 "custom_model_data",
201#if PROTOCOL_VERSION < 770 /* < 1.21.5 */
202 "hide_additional_tooltip",
203 "hide_tooltip",
204#endif
205#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
206 "tooltip_display",
207#endif
208 "repair_cost",
209 "creative_slot_lock",
210 "enchantment_glint_override",
211 "intangible_projectile",
212 "food",
213#if PROTOCOL_VERSION < 768 /* < 1.21.2 */
214 "fire_resistant",
215#endif
216#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
217 "consumable",
218 "use_remainder",
219 "use_cooldown",
220 "damage_resistant",
221#endif
222 "tool",
223#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
224 "weapon",
225#endif
226#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
227 "enchantable",
228 "equippable",
229 "repairable",
230 "glider",
231 "tooltip_style",
232 "death_protection",
233#endif
234#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
235 "blocks_attacks",
236#endif
237 "stored_enchantments",
238 "dyed_color",
239 "map_color",
240 "map_id",
241 "map_decorations",
242 "map_post_processing",
243 "charged_projectiles",
244 "bundle_contents",
245 "potion_contents",
246#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
247 "potion_duration_scale",
248#endif
249 "suspicious_stew_effects",
250 "writable_book_content",
251 "written_book_content",
252 "trim",
253 "debug_stick_state",
254 "entity_data",
255 "bucket_entity_data",
256 "block_entity_data",
257 "instrument",
258#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
259 "provides_trim_material",
260#endif
261 "ominous_bottle_amplifier",
262#if PROTOCOL_VERSION > 766 /* > 1.20.6 */
263 "jukebox_playable",
264#endif
265#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
266 "provides_banner_patterns",
267#endif
268 "recipes",
269 "lodestone_tracker",
270 "firework_explosion",
271 "fireworks",
272 "profile",
273 "note_block_sound",
274 "banner_patterns",
275 "base_color",
276 "pot_decorations",
277 "container",
278 "block_state",
279 "bees",
280 "lock",
281 "container_loot",
282#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
283 "break_sound",
284 "villager/variant",
285 "wolf/variant",
286 "wolf/sound_variant",
287 "wolf/collar",
288 "fox/variant",
289 "salmon/size",
290 "parrot/variant",
291 "tropical_fish/pattern",
292 "tropical_fish/base_color",
293 "tropical_fish/pattern_color",
294 "mooshroom/variant",
295 "rabbit/variant",
296 "pig/variant",
297 "cow/variant",
298 "chicken/variant",
299 "frog/variant",
300 "horse/variant",
301 "painting/variant",
302 "llama/variant",
303 "axolotl/variant",
304 "cat/variant",
305 "cat/collar",
306 "sheep/color",
307 "shulker/color",
308#endif
309 };
310 if (type <= DataComponentTypes::None || type >= DataComponentTypes::NUM_DATA_COMPONENT_TYPES)
311 {
312 return "";
313 }
314 return names[static_cast<size_t>(type)];
315 }
316
317 std::shared_ptr<DataComponentType> CreateComponentType(const DataComponentTypes type)
318 {
319 if (type <= DataComponentTypes::None || type >= DataComponentTypes::NUM_DATA_COMPONENT_TYPES)
320 {
321 throw std::runtime_error("Unable to create data component with id: " + std::to_string(static_cast<int>(type)) + ".");
322 }
323
324 switch (type)
325 {
328 return std::make_shared<DataComponentTypeAdventureModePredicate>();
330 return std::make_shared<DataComponentTypeArmorTrim>();
332 return std::make_shared<DataComponentTypeBannerPatternLayers>();
334 return std::make_shared<DataComponentTypeBlockItemStateProperties>();
336 return std::make_shared<DataComponentTypeBoolean>();
338 return std::make_shared<DataComponentTypeBundleContents>();
340 return std::make_shared<DataComponentTypeChargedProjectiles>();
343 return std::make_shared<DataComponentTypeComponent>();
345#if PROTOCOL_VERSION < 773 /* < 1.21.9 */
348#endif
349 return std::make_shared<DataComponentTypeCustomData>();
351 return std::make_shared<DataComponentTypeCustomModelData>();
359#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
361#endif
362 // Component with no network serializer specified fallback to NBT
363 return std::make_shared<DataComponentTypeDefault>();
365 return std::make_shared<DataComponentTypeDyeColor>();
367 return std::make_shared<DataComponentTypeDyedItemColor>();
369 return std::make_shared<DataComponentTypeFireworkExplosion>();
371 return std::make_shared<DataComponentTypeFireworks>();
373 return std::make_shared<DataComponentTypeFoodProperties>();
375 return std::make_shared<DataComponentTypeInstrument>();
381#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
383#endif
384 return std::make_shared<DataComponentTypeInteger>();
386 return std::make_shared<DataComponentTypeItemAttributeModifiers>();
388 return std::make_shared<DataComponentTypeItemContainerContents>();
391 return std::make_shared<DataComponentTypeItemEnchantments>();
393 return std::make_shared<DataComponentTypeItemLore>();
394#if PROTOCOL_VERSION > 766 /* > 1.20.6 */
396 return std::make_shared<DataComponentTypeJukeboxPlayable>();
397#endif
399 return std::make_shared<DataComponentTypeListBeehiveBlockEntityOccupant>();
401 return std::make_shared<DataComponentTypeLodestoneTracker>();
403 return std::make_shared<DataComponentTypeMapId>();
405 return std::make_shared<DataComponentTypeMapItemColor>();
407 return std::make_shared<DataComponentTypeMapPostProcessing>();
409 return std::make_shared<DataComponentTypePotDecorations>();
411 return std::make_shared<DataComponentTypePotionContents>();
413 return std::make_shared<DataComponentTypeRarity>();
415 return std::make_shared<DataComponentTypeResolvableProfile>();
417#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
421#endif
422 return std::make_shared<DataComponentTypeResourceLocation>();
424 return std::make_shared<DataComponentTypeSuspiciousStewEffects>();
426 return std::make_shared<DataComponentTypeTool>();
427#if PROTOCOL_VERSION < 770 /* < 1.21.5 */
429 return std::make_shared<DataComponentTypeUnbreakable>();
430#else
431 // From custom Unbreakable to Unit in 1.21.5
433#endif
434#if PROTOCOL_VERSION < 770 /* < 1.21.5 */
435 case DataComponentTypes::HideAdditionalTooltip:
436 case DataComponentTypes::HideTooltip:
437#endif
439#if PROTOCOL_VERSION < 768 /* < 1.21.2 */
440 case DataComponentTypes::FireResistant:
441#endif
442 return std::make_shared<DataComponentTypeUnit>();
444 return std::make_shared<DataComponentTypeWritableBookContent>();
446 return std::make_shared<DataComponentTypeWrittenBookContent>();
447#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
449 return std::make_shared<DataComponentTypeConsumable>();
451 return std::make_shared<DataComponentTypeDeathProtection>();
453 return std::make_shared<DataComponentTypeEquippable>();
455 return std::make_shared<DataComponentTypeRepairable>();
457 return std::make_shared<DataComponentTypeUseCooldown>();
459 return std::make_shared<DataComponentTypeUseRemainder>();
460#endif
461#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
463 return std::make_shared<DataComponentTypeBlocksAttacks>();
465 return std::make_shared<DataComponentTypeBreakSound>();
467 return std::make_shared<DataComponentTypePaintingVariant>();
469 return std::make_shared<DataComponentTypePotionDurationScale>();
471 return std::make_shared<DataComponentTypeProvidesTrimMaterial>();
473 return std::make_shared<DataComponentTypeTooltipDisplay>();
475 return std::make_shared<DataComponentTypeWeapon>();
478 case DataComponentTypes::Chicken_Variant: // TODO: understand why there is an Either thing in MC code for this one?
492 return std::make_shared<DataComponentTypeVariantEnum>();
499 return std::make_shared<DataComponentTypeDyeColor>();
500#endif
501#if PROTOCOL_VERSION > 772 /* > 1.21.8 */
504 return std::make_shared<DataComponentTypeTypedEntityData>();
505#endif
506 default:
507 // Should never happen but will make the compilers happy
508 throw std::runtime_error("Unable to create data component with id: " + std::to_string(static_cast<int>(type)) + ".");
509 }
510 }
511
516
517 const std::map<DataComponentTypes, std::shared_ptr<DataComponentType>>& DataComponentPredicate::GetMap() const
518 {
519 return map;
520 }
521
522 DataComponentPredicate& DataComponentPredicate::SetMap(const std::map<DataComponentTypes, std::shared_ptr<DataComponentType>>& map_)
523 {
524 map = map_;
525 return *this;
526 }
527
529 {
530 // special case, dynamic factory
531 const int map_size = ReadData<VarInt>(iter, length);
532 map.clear();
533 for (int i = 0; i < map_size; ++i)
534 {
535 const DataComponentTypes k = ReadData<DataComponentTypes, VarInt>(iter, length);
536 std::shared_ptr<DataComponentType> v = CreateComponentType(k);
537 if (v != nullptr)
538 {
539 v->Read(iter, length);
540 }
541 map[k] = v;
542 }
543 }
544
546 {
547 // special case, dynamic factory
548 WriteData<VarInt>(static_cast<int>(map.size()), container);
549 for (const auto& [k, v] : map)
550 {
551 WriteData<DataComponentTypes, VarInt>(k, container);
552 if (v != nullptr)
553 {
554 v->Write(container);
555 }
556 }
557 }
558
560 {
561 Json::Value output;
562
563 output["map"] = Json::Array();
564 for (const auto& p : map)
565 {
566 output["map"].push_back({
567 { "name", DataComponentTypesToString(p.first) },
568 { "data", p.second == nullptr ? nullptr : p.second->Serialize() }
569 });
570 }
571
572 return output;
573 }
574
575
580
581 const std::map<DataComponentTypes, std::shared_ptr<DataComponentType>>& DataComponentPatch::GetMap() const
582 {
583 return map;
584 }
585
586 DataComponentPatch& DataComponentPatch::SetMap(const std::map<DataComponentTypes, std::shared_ptr<DataComponentType>>& map_)
587 {
588 map = map_;
589 return *this;
590 }
591
592 void DataComponentPatch::ReadImpl(ReadIterator& iter, size_t& length)
593 {
594 const int num_data = ReadData<VarInt>(iter, length);
595 const int num_void = ReadData<VarInt>(iter, length);
596
597 map.clear();
598
599 for (int i = 0; i < num_data; ++i)
600 {
601 const DataComponentTypes type = ReadData<DataComponentTypes, VarInt>(iter, length);
602 std::shared_ptr<DataComponentType> data = CreateComponentType(type);
603
604 if (data != nullptr)
605 {
606 data->Read(iter, length);
607 }
608 map.insert({ type, data });
609 }
610
611 for (int i = 0; i < num_void; ++i)
612 {
613 const DataComponentTypes type = ReadData<DataComponentTypes, VarInt>(iter, length);
614 map.insert({ type, nullptr });
615 }
616 }
617
619 {
620 int num_data = 0;
621 for (const auto& p : map)
622 {
623 num_data += p.second != nullptr;
624 }
625 const int num_void = static_cast<int>(map.size()) - num_data;
626
627 WriteData<VarInt>(num_data, container);
628 WriteData<VarInt>(num_void, container);
629
630 for (const auto& p : map)
631 {
632 if (p.second == nullptr)
633 {
634 continue;
635 }
636 WriteData<DataComponentTypes, VarInt>(p.first, container);
637 p.second->Write(container);
638 }
639
640 for (const auto& p : map)
641 {
642 if (p.second != nullptr)
643 {
644 continue;
645 }
646 WriteData<DataComponentTypes, VarInt>(p.first, container);
647 }
648 }
649
651 {
652 Json::Value output;
653
654 output["map"] = Json::Array();
655 for (const auto& p : map)
656 {
657 output["map"].push_back({
658 { "name", DataComponentTypesToString(p.first) },
659 { "data", p.second == nullptr ? nullptr : p.second->Serialize() }
660 });
661 }
662
663 return output;
664 }
665
666#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
668 {
669 for (const auto& [k, v] : patch.GetMap())
670 {
671 if (v == nullptr)
672 {
673 RemovedComponents.push_back(k);
674 }
675 else
676 {
677 // TODO: Fix this, this is *NOT* how the components are serialized to bytes
678 std::vector<unsigned char> serialized;
679 WriteData<DataComponentTypes, VarInt>(k, serialized);
680 v->Write(serialized);
681 // This however should be the right CRC32C hash calculation
682 // CRC32c polynomial, from https://en.wikipedia.org/wiki/Cyclic_redundancy_check#Polynomial_representations
683 // no idea why we need the reversed one but it works
684 constexpr unsigned int polynomial = 0x82F63B78;
685
686 unsigned int crc = 0xFFFFFFFF;
687
688 for (const auto byte : serialized)
689 {
690 crc ^= byte;
691 // TODO: replace slow loop with a faster version with lookup table and cool fancy stuff ?
692 for (int i = 0; i < 8; ++i)
693 {
694 // Trick to replace if branch
695 // if (crc & 1) crc = (crc >> 1) ^ polynomial;
696 // else crc = crc >> 1;
697 // Works because a ^ 0 == a
698 crc = (crc >> 1) ^ (crc & 1) * polynomial;
699 }
700 }
701 AddedComponents[k] = static_cast<int>(~crc);
702 }
703 }
704 }
705
707#endif
708 }
709}
710#endif
#define DEFINE_NETWORK_TYPE(ClassName)
virtual Json::Value SerializeImpl() const override
std::map< DataComponentTypes, std::shared_ptr< DataComponentType > > map
const std::map< DataComponentTypes, std::shared_ptr< DataComponentType > > & GetMap() const
virtual void ReadImpl(ReadIterator &iter, size_t &length) override
DataComponentPatch & SetMap(const std::map< DataComponentTypes, std::shared_ptr< DataComponentType > > &map_)
virtual void WriteImpl(WriteContainer &container) const override
virtual void WriteImpl(WriteContainer &container) const override
std::map< DataComponentTypes, std::shared_ptr< DataComponentType > > map
virtual Json::Value SerializeImpl() const override
virtual void ReadImpl(ReadIterator &iter, size_t &length) override
const std::map< DataComponentTypes, std::shared_ptr< DataComponentType > > & GetMap() const
DataComponentPredicate & SetMap(const std::map< DataComponentTypes, std::shared_ptr< DataComponentType > > &map_)
Real class declaration, just a derived class of std::vector<Value>
Definition Json.hpp:180
Main class, basically a JsonVariant with extra utility functions it doesn't inherit JsonVariant direc...
Definition Json.hpp:45
void push_back(const Value &value)
Definition Json.cpp:257
std::shared_ptr< DataComponentType > CreateComponentType(const DataComponentTypes type)
std::string_view DataComponentTypesToString(const DataComponentTypes type)
std::vector< unsigned char > WriteContainer
std::vector< unsigned char >::const_iterator ReadIterator