Botcraft 1.21.11
Loading...
Searching...
No Matches
DataComponents.cpp
Go to the documentation of this file.
1#if PROTOCOL_VERSION > 765 /* > 1.20.4 */
4
36#if PROTOCOL_VERSION < 774 /* < 1.21.115 */
38#endif
41#if PROTOCOL_VERSION < 770 /* < 1.21.5 */
43#endif
47#if PROTOCOL_VERSION > 766 /* > 1.20.6 */
49#endif
50#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
57#endif
58#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
68#endif
69#if PROTOCOL_VERSION > 772 /* > 1.21.8 */
71#endif
72#if PROTOCOL_VERSION > 773 /* > 1.21.10 */
79#endif
80
82
83namespace ProtocolCraft
84{
85 namespace Components
86 {
93#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
95#endif
96#if PROTOCOL_VERSION > 765 /* > 1.20.4 */
98#endif
100#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
102#endif
103#if PROTOCOL_VERSION > 766 /* > 1.20.6 */
105#endif
106#if PROTOCOL_VERSION > 773 /* > 1.21.10 */
108#endif
109#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
112#endif
115#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
117#endif
118#if PROTOCOL_VERSION > 772 /* > 1.21.8 */
121#endif
129
161#if PROTOCOL_VERSION < 774 /* < 1.21.11 */
162 DEFINE_NETWORK_TYPE(DataComponentTypeResourceLocation);
163#endif
166#if PROTOCOL_VERSION < 770 /* < 1.21.5 */
167 DEFINE_NETWORK_TYPE(DataComponentTypeUnbreakable);
168#endif
172#if PROTOCOL_VERSION > 766 /* > 1.20.6 */
174#endif
175#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
182#endif
183#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
193#endif
194#if PROTOCOL_VERSION > 772 /* > 1.21.8 */
196#endif
197#if PROTOCOL_VERSION > 773 /* > 1.21.10 */
204#endif
205
207 {
208 static constexpr std::array<std::string_view, static_cast<size_t>(DataComponentTypes::NUM_DATA_COMPONENT_TYPES)> names = {
209 "custom_data",
210 "max_stack_size",
211 "max_damage",
212 "damage",
213 "unbreakable",
214#if PROTOCOL_VERSION > 773 /* > 1.21.10 */
215 "use_effects",
216#endif
217 "custom_name",
218#if PROTOCOL_VERSION > 773 /* > 1.21.10 */
219 "minimum_attack_charge",
220 "damage_type",
221#endif
222 "item_name",
223#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
224 "item_model",
225#endif
226 "lore",
227 "rarity",
228 "enchantments",
229 "can_place_on",
230 "can_break",
231 "attribute_modifiers",
232 "custom_model_data",
233#if PROTOCOL_VERSION < 770 /* < 1.21.5 */
234 "hide_additional_tooltip",
235 "hide_tooltip",
236#endif
237#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
238 "tooltip_display",
239#endif
240 "repair_cost",
241 "creative_slot_lock",
242 "enchantment_glint_override",
243 "intangible_projectile",
244 "food",
245#if PROTOCOL_VERSION < 768 /* < 1.21.2 */
246 "fire_resistant",
247#endif
248#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
249 "consumable",
250 "use_remainder",
251 "use_cooldown",
252 "damage_resistant",
253#endif
254 "tool",
255#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
256 "weapon",
257#endif
258#if PROTOCOL_VERSION > 773 /* > 1.21.10 */
259 "attack_range",
260#endif
261#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
262 "enchantable",
263 "equippable",
264 "repairable",
265 "glider",
266 "tooltip_style",
267 "death_protection",
268#endif
269#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
270 "blocks_attacks",
271#endif
272#if PROTOCOL_VERSION > 773 /* > 1.21.10 */
273 "piercing_weapon",
274 "kinetic_weapon",
275 "swing_animation",
276#endif
277 "stored_enchantments",
278 "dyed_color",
279 "map_color",
280 "map_id",
281 "map_decorations",
282 "map_post_processing",
283 "charged_projectiles",
284 "bundle_contents",
285 "potion_contents",
286#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
287 "potion_duration_scale",
288#endif
289 "suspicious_stew_effects",
290 "writable_book_content",
291 "written_book_content",
292 "trim",
293 "debug_stick_state",
294 "entity_data",
295 "bucket_entity_data",
296 "block_entity_data",
297 "instrument",
298#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
299 "provides_trim_material",
300#endif
301 "ominous_bottle_amplifier",
302#if PROTOCOL_VERSION > 766 /* > 1.20.6 */
303 "jukebox_playable",
304#endif
305#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
306 "provides_banner_patterns",
307#endif
308 "recipes",
309 "lodestone_tracker",
310 "firework_explosion",
311 "fireworks",
312 "profile",
313 "note_block_sound",
314 "banner_patterns",
315 "base_color",
316 "pot_decorations",
317 "container",
318 "block_state",
319 "bees",
320 "lock",
321 "container_loot",
322#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
323 "break_sound",
324 "villager/variant",
325 "wolf/variant",
326 "wolf/sound_variant",
327 "wolf/collar",
328 "fox/variant",
329 "salmon/size",
330 "parrot/variant",
331 "tropical_fish/pattern",
332 "tropical_fish/base_color",
333 "tropical_fish/pattern_color",
334 "mooshroom/variant",
335 "rabbit/variant",
336 "pig/variant",
337 "cow/variant",
338 "chicken/variant",
339#if PROTOCOL_VERSION > 773 /* > 1.21.10 */
340 "zombie_nautilus/variant",
341#endif
342 "frog/variant",
343 "horse/variant",
344 "painting/variant",
345 "llama/variant",
346 "axolotl/variant",
347 "cat/variant",
348 "cat/collar",
349 "sheep/color",
350 "shulker/color",
351#endif
352 };
353 if (type <= DataComponentTypes::None || type >= DataComponentTypes::NUM_DATA_COMPONENT_TYPES)
354 {
355 return "";
356 }
357 return names[static_cast<size_t>(type)];
358 }
359
360 std::shared_ptr<DataComponentType> CreateComponentType(const DataComponentTypes type)
361 {
362 if (type <= DataComponentTypes::None || type >= DataComponentTypes::NUM_DATA_COMPONENT_TYPES)
363 {
364 throw std::runtime_error("Unable to create data component with id: " + std::to_string(static_cast<int>(type)) + ".");
365 }
366
367 switch (type)
368 {
371 return std::make_shared<DataComponentTypeAdventureModePredicate>();
373 return std::make_shared<DataComponentTypeArmorTrim>();
375 return std::make_shared<DataComponentTypeBannerPatternLayers>();
377 return std::make_shared<DataComponentTypeBlockItemStateProperties>();
379 return std::make_shared<DataComponentTypeBoolean>();
381 return std::make_shared<DataComponentTypeBundleContents>();
383 return std::make_shared<DataComponentTypeChargedProjectiles>();
386 return std::make_shared<DataComponentTypeComponent>();
388#if PROTOCOL_VERSION < 773 /* < 1.21.9 */
391#endif
392 return std::make_shared<DataComponentTypeCustomData>();
394 return std::make_shared<DataComponentTypeCustomModelData>();
402#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
404#endif
405 // Component with no network serializer specified fallback to NBT
406 return std::make_shared<DataComponentTypeDefault>();
408 return std::make_shared<DataComponentTypeDyeColor>();
410 return std::make_shared<DataComponentTypeDyedItemColor>();
412 return std::make_shared<DataComponentTypeFireworkExplosion>();
414 return std::make_shared<DataComponentTypeFireworks>();
416 return std::make_shared<DataComponentTypeFoodProperties>();
418 return std::make_shared<DataComponentTypeInstrument>();
424#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
426#endif
427 return std::make_shared<DataComponentTypeInteger>();
429 return std::make_shared<DataComponentTypeItemAttributeModifiers>();
431 return std::make_shared<DataComponentTypeItemContainerContents>();
434 return std::make_shared<DataComponentTypeItemEnchantments>();
436 return std::make_shared<DataComponentTypeItemLore>();
437#if PROTOCOL_VERSION > 766 /* > 1.20.6 */
439 return std::make_shared<DataComponentTypeJukeboxPlayable>();
440#endif
442 return std::make_shared<DataComponentTypeListBeehiveBlockEntityOccupant>();
444 return std::make_shared<DataComponentTypeLodestoneTracker>();
446 return std::make_shared<DataComponentTypeMapId>();
448 return std::make_shared<DataComponentTypeMapItemColor>();
450 return std::make_shared<DataComponentTypeMapPostProcessing>();
452 return std::make_shared<DataComponentTypePotDecorations>();
454 return std::make_shared<DataComponentTypePotionContents>();
456 return std::make_shared<DataComponentTypeRarity>();
458 return std::make_shared<DataComponentTypeResolvableProfile>();
460#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
464#endif
465#if PROTOCOL_VERSION < 774 /* < 1.21.11 */
466 return std::make_shared<DataComponentTypeResourceLocation>();
467#else
468 return std::make_shared<DataComponentTypeIdentifier>();
469#endif
471 return std::make_shared<DataComponentTypeSuspiciousStewEffects>();
473 return std::make_shared<DataComponentTypeTool>();
474#if PROTOCOL_VERSION < 770 /* < 1.21.5 */
476 return std::make_shared<DataComponentTypeUnbreakable>();
477#else
478 // From custom Unbreakable to Unit in 1.21.5
480#endif
481#if PROTOCOL_VERSION < 770 /* < 1.21.5 */
482 case DataComponentTypes::HideAdditionalTooltip:
483 case DataComponentTypes::HideTooltip:
484#endif
486#if PROTOCOL_VERSION < 768 /* < 1.21.2 */
487 case DataComponentTypes::FireResistant:
488#endif
489 return std::make_shared<DataComponentTypeUnit>();
491 return std::make_shared<DataComponentTypeWritableBookContent>();
493 return std::make_shared<DataComponentTypeWrittenBookContent>();
494#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
496 return std::make_shared<DataComponentTypeConsumable>();
498 return std::make_shared<DataComponentTypeDeathProtection>();
500 return std::make_shared<DataComponentTypeEquippable>();
502 return std::make_shared<DataComponentTypeRepairable>();
504 return std::make_shared<DataComponentTypeUseCooldown>();
506 return std::make_shared<DataComponentTypeUseRemainder>();
507#endif
508#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
510 return std::make_shared<DataComponentTypeBlocksAttacks>();
512 return std::make_shared<DataComponentTypeBreakSound>();
514 return std::make_shared<DataComponentTypePaintingVariant>();
516 return std::make_shared<DataComponentTypeFloat>();
518 return std::make_shared<DataComponentTypeProvidesTrimMaterial>();
520 return std::make_shared<DataComponentTypeTooltipDisplay>();
522 return std::make_shared<DataComponentTypeWeapon>();
524 return std::make_shared<DataComponentTypeEitherRegistryVarint>();
540 return std::make_shared<DataComponentTypeVariantEnum>();
547 return std::make_shared<DataComponentTypeDyeColor>();
548#endif
549#if PROTOCOL_VERSION > 772 /* > 1.21.8 */
552 return std::make_shared<DataComponentTypeTypedEntityData>();
553#endif
554#if PROTOCOL_VERSION > 773 /* > 1.21.10 */
556 return std::make_shared<DataComponentTypeUseEffects>();
558 return std::make_shared<DataComponentTypeFloat>();
560 return std::make_shared<DataComponentTypeAttackRange>();
563 return std::make_shared<DataComponentTypeEitherRegistryVarint>();
565 return std::make_shared<DataComponentTypePiercingWeapon>();
567 return std::make_shared<DataComponentTypeKineticWeapon>();
569 return std::make_shared<DataComponentTypeSwingAnimation>();
570#endif
571 default:
572 // Should never happen but will make the compilers happy
573 throw std::runtime_error("Unable to create data component with id: " + std::to_string(static_cast<int>(type)) + ".");
574 }
575 }
576
581
582 const std::map<DataComponentTypes, std::shared_ptr<DataComponentType>>& DataComponentPredicate::GetMap() const
583 {
584 return map;
585 }
586
587 DataComponentPredicate& DataComponentPredicate::SetMap(const std::map<DataComponentTypes, std::shared_ptr<DataComponentType>>& map_)
588 {
589 map = map_;
590 return *this;
591 }
592
594 {
595 // special case, dynamic factory
596 const int map_size = ReadData<VarInt>(iter, length);
597 map.clear();
598 for (int i = 0; i < map_size; ++i)
599 {
600 const DataComponentTypes k = ReadData<DataComponentTypes, VarInt>(iter, length);
601 std::shared_ptr<DataComponentType> v = CreateComponentType(k);
602 if (v != nullptr)
603 {
604 v->Read(iter, length);
605 }
606 map[k] = v;
607 }
608 }
609
611 {
612 // special case, dynamic factory
613 WriteData<VarInt>(static_cast<int>(map.size()), container);
614 for (const auto& [k, v] : map)
615 {
616 WriteData<DataComponentTypes, VarInt>(k, container);
617 if (v != nullptr)
618 {
619 v->Write(container);
620 }
621 }
622 }
623
625 {
626 Json::Value output;
627
628 output["map"] = Json::Array();
629 for (const auto& p : map)
630 {
631 output["map"].push_back({
632 { "name", DataComponentTypesToString(p.first) },
633 { "data", p.second == nullptr ? nullptr : p.second->Serialize() }
634 });
635 }
636
637 return output;
638 }
639
640
645
646 const std::map<DataComponentTypes, std::shared_ptr<DataComponentType>>& DataComponentPatch::GetMap() const
647 {
648 return map;
649 }
650
651 DataComponentPatch& DataComponentPatch::SetMap(const std::map<DataComponentTypes, std::shared_ptr<DataComponentType>>& map_)
652 {
653 map = map_;
654 return *this;
655 }
656
657 void DataComponentPatch::ReadImpl(ReadIterator& iter, size_t& length)
658 {
659 const int num_data = ReadData<VarInt>(iter, length);
660 const int num_void = ReadData<VarInt>(iter, length);
661
662 map.clear();
663
664 for (int i = 0; i < num_data; ++i)
665 {
666 const DataComponentTypes type = ReadData<DataComponentTypes, VarInt>(iter, length);
667 std::shared_ptr<DataComponentType> data = CreateComponentType(type);
668
669 if (data != nullptr)
670 {
671 data->Read(iter, length);
672 }
673 map.insert({ type, data });
674 }
675
676 for (int i = 0; i < num_void; ++i)
677 {
678 const DataComponentTypes type = ReadData<DataComponentTypes, VarInt>(iter, length);
679 map.insert({ type, nullptr });
680 }
681 }
682
684 {
685 int num_data = 0;
686 for (const auto& p : map)
687 {
688 num_data += p.second != nullptr;
689 }
690 const int num_void = static_cast<int>(map.size()) - num_data;
691
692 WriteData<VarInt>(num_data, container);
693 WriteData<VarInt>(num_void, container);
694
695 for (const auto& p : map)
696 {
697 if (p.second == nullptr)
698 {
699 continue;
700 }
701 WriteData<DataComponentTypes, VarInt>(p.first, container);
702 p.second->Write(container);
703 }
704
705 for (const auto& p : map)
706 {
707 if (p.second != nullptr)
708 {
709 continue;
710 }
711 WriteData<DataComponentTypes, VarInt>(p.first, container);
712 }
713 }
714
716 {
717 Json::Value output;
718
719 output["map"] = Json::Array();
720 for (const auto& p : map)
721 {
722 output["map"].push_back({
723 { "name", DataComponentTypesToString(p.first) },
724 { "data", p.second == nullptr ? nullptr : p.second->Serialize() }
725 });
726 }
727
728 return output;
729 }
730
731#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
733 {
734 for (const auto& [k, v] : patch.GetMap())
735 {
736 if (v == nullptr)
737 {
738 RemovedComponents.push_back(k);
739 }
740 else
741 {
742 // TODO: Fix this, this is *NOT* how the components are serialized to bytes
743 std::vector<unsigned char> serialized;
744 WriteData<DataComponentTypes, VarInt>(k, serialized);
745 v->Write(serialized);
746 // This however should be the right CRC32C hash calculation
747 // CRC32c polynomial, from https://en.wikipedia.org/wiki/Cyclic_redundancy_check#Polynomial_representations
748 // no idea why we need the reversed one but it works
749 constexpr unsigned int polynomial = 0x82F63B78;
750
751 unsigned int crc = 0xFFFFFFFF;
752
753 for (const auto byte : serialized)
754 {
755 crc ^= byte;
756 // TODO: replace slow loop with a faster version with lookup table and cool fancy stuff ?
757 for (int i = 0; i < 8; ++i)
758 {
759 // Trick to replace if branch
760 // if (crc & 1) crc = (crc >> 1) ^ polynomial;
761 // else crc = crc >> 1;
762 // Works because a ^ 0 == a
763 crc = (crc >> 1) ^ (crc & 1) * polynomial;
764 }
765 }
766 AddedComponents[k] = static_cast<int>(~crc);
767 }
768 }
769 }
770
772#endif
773 }
774}
775#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