Botcraft 26.2
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 */
58#endif
59#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
70#endif
71#if PROTOCOL_VERSION > 772 /* > 1.21.8 */
73#endif
74#if PROTOCOL_VERSION > 773 /* > 1.21.10 */
81#endif
82#if PROTOCOL_VERSION > 775 /* > 26.1.2 */
84#endif
85
87
88namespace ProtocolCraft
89{
90 namespace Components
91 {
98#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
100#endif
101#if PROTOCOL_VERSION > 765 /* > 1.20.4 */
103#endif
105#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
107#endif
108#if PROTOCOL_VERSION > 766 /* > 1.20.6 */
110#endif
111#if PROTOCOL_VERSION > 773 /* > 1.21.10 */
113#endif
114#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
117#endif
120#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
122#endif
123#if PROTOCOL_VERSION > 772 /* > 1.21.8 */
126#endif
134
166#if PROTOCOL_VERSION < 774 /* < 1.21.11 */
167 DEFINE_NETWORK_TYPE(DataComponentTypeResourceLocation);
168#endif
171#if PROTOCOL_VERSION < 770 /* < 1.21.5 */
172 DEFINE_NETWORK_TYPE(DataComponentTypeUnbreakable);
173#endif
177#if PROTOCOL_VERSION > 766 /* > 1.20.6 */
179#endif
180#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
188#endif
189#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
200#endif
201#if PROTOCOL_VERSION > 772 /* > 1.21.8 */
203#endif
204#if PROTOCOL_VERSION > 773 /* > 1.21.10 */
211#endif
212#if PROTOCOL_VERSION > 775 /* > 26.1.2 */
214#endif
215
217 {
218 static constexpr std::array<std::string_view, static_cast<size_t>(DataComponentTypes::NUM_DATA_COMPONENT_TYPES)> names = {
219 "custom_data",
220 "max_stack_size",
221 "max_damage",
222 "damage",
223 "unbreakable",
224#if PROTOCOL_VERSION > 773 /* > 1.21.10 */
225 "use_effects",
226#endif
227 "custom_name",
228#if PROTOCOL_VERSION > 773 /* > 1.21.10 */
229 "minimum_attack_charge",
230 "damage_type",
231#endif
232 "item_name",
233#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
234 "item_model",
235#endif
236 "lore",
237 "rarity",
238 "enchantments",
239 "can_place_on",
240 "can_break",
241 "attribute_modifiers",
242 "custom_model_data",
243#if PROTOCOL_VERSION < 770 /* < 1.21.5 */
244 "hide_additional_tooltip",
245 "hide_tooltip",
246#endif
247#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
248 "tooltip_display",
249#endif
250 "repair_cost",
251 "creative_slot_lock",
252 "enchantment_glint_override",
253 "intangible_projectile",
254 "food",
255#if PROTOCOL_VERSION < 768 /* < 1.21.2 */
256 "fire_resistant",
257#endif
258#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
259 "consumable",
260 "use_remainder",
261 "use_cooldown",
262 "damage_resistant",
263#endif
264 "tool",
265#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
266 "weapon",
267#endif
268#if PROTOCOL_VERSION > 773 /* > 1.21.10 */
269 "attack_range",
270#endif
271#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
272 "enchantable",
273 "equippable",
274 "repairable",
275 "glider",
276 "tooltip_style",
277 "death_protection",
278#endif
279#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
280 "blocks_attacks",
281#endif
282#if PROTOCOL_VERSION > 773 /* > 1.21.10 */
283 "piercing_weapon",
284 "kinetic_weapon",
285 "swing_animation",
286#endif
287#if PROTOCOL_VERSION > 774 /* > 1.21.11 */
288 "additional_trade_cost",
289#endif
290 "stored_enchantments",
291#if PROTOCOL_VERSION > 774 /* > 1.21.11 */
292 "dye",
293#endif
294 "dyed_color",
295 "map_color",
296 "map_id",
297 "map_decorations",
298 "map_post_processing",
299 "charged_projectiles",
300 "bundle_contents",
301 "potion_contents",
302#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
303 "potion_duration_scale",
304#endif
305 "suspicious_stew_effects",
306 "writable_book_content",
307 "written_book_content",
308 "trim",
309 "debug_stick_state",
310 "entity_data",
311 "bucket_entity_data",
312 "block_entity_data",
313 "instrument",
314#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
315 "provides_trim_material",
316#endif
317 "ominous_bottle_amplifier",
318#if PROTOCOL_VERSION > 766 /* > 1.20.6 */
319 "jukebox_playable",
320#endif
321#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
322 "provides_banner_patterns",
323#endif
324 "recipes",
325 "lodestone_tracker",
326 "firework_explosion",
327 "fireworks",
328 "profile",
329 "note_block_sound",
330 "banner_patterns",
331 "base_color",
332 "pot_decorations",
333 "container",
334 "block_state",
335 "bees",
336#if PROTOCOL_VERSION > 775 /* > 26.1.2 */
337 "sulfur_cube_content"
338#endif
339 "lock",
340 "container_loot",
341#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
342 "break_sound",
343 "villager/variant",
344 "wolf/variant",
345 "wolf/sound_variant",
346 "wolf/collar",
347 "fox/variant",
348 "salmon/size",
349 "parrot/variant",
350 "tropical_fish/pattern",
351 "tropical_fish/base_color",
352 "tropical_fish/pattern_color",
353 "mooshroom/variant",
354 "rabbit/variant",
355 "pig/variant",
356#if PROTOCOL_VERSION > 774 /* > 1.21.11 */
357 "pig/sound_variant",
358#endif
359 "cow/variant",
360#if PROTOCOL_VERSION > 774 /* > 1.21.11 */
361 "cow/sound_variant",
362#endif
363 "chicken/variant",
364#if PROTOCOL_VERSION > 774 /* > 1.21.11 */
365 "chicken/sound_variant",
366#endif
367#if PROTOCOL_VERSION > 773 /* > 1.21.10 */
368 "zombie_nautilus/variant",
369#endif
370 "frog/variant",
371 "horse/variant",
372 "painting/variant",
373 "llama/variant",
374 "axolotl/variant",
375 "cat/variant",
376#if PROTOCOL_VERSION > 774 /* > 1.21.11 */
377 "cat/sound_variant",
378#endif
379 "cat/collar",
380 "sheep/color",
381 "shulker/color",
382#endif
383 };
384 if (type <= DataComponentTypes::None || type >= DataComponentTypes::NUM_DATA_COMPONENT_TYPES)
385 {
386 return "";
387 }
388 return names[static_cast<size_t>(type)];
389 }
390
391 std::shared_ptr<DataComponentType> CreateComponentType(const DataComponentTypes type)
392 {
393 if (type <= DataComponentTypes::None || type >= DataComponentTypes::NUM_DATA_COMPONENT_TYPES)
394 {
395 throw std::runtime_error("Unable to create data component with id: " + std::to_string(static_cast<int>(type)) + ".");
396 }
397
398 switch (type)
399 {
402 return std::make_shared<DataComponentTypeAdventureModePredicate>();
404 return std::make_shared<DataComponentTypeArmorTrim>();
406 return std::make_shared<DataComponentTypeBannerPatternLayers>();
408 return std::make_shared<DataComponentTypeBlockItemStateProperties>();
410 return std::make_shared<DataComponentTypeBoolean>();
412 return std::make_shared<DataComponentTypeBundleContents>();
414 return std::make_shared<DataComponentTypeChargedProjectiles>();
417 return std::make_shared<DataComponentTypeComponent>();
419#if PROTOCOL_VERSION < 773 /* < 1.21.9 */
422#endif
423 return std::make_shared<DataComponentTypeCustomData>();
425 return std::make_shared<DataComponentTypeCustomModelData>();
433#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
435#endif
436 // Component with no network serializer specified fallback to NBT
437 return std::make_shared<DataComponentTypeDefault>();
439 return std::make_shared<DataComponentTypeDyeColor>();
441 return std::make_shared<DataComponentTypeDyedItemColor>();
443 return std::make_shared<DataComponentTypeFireworkExplosion>();
445 return std::make_shared<DataComponentTypeFireworks>();
447 return std::make_shared<DataComponentTypeFoodProperties>();
449 return std::make_shared<DataComponentTypeInstrument>();
455#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
457#endif
458 return std::make_shared<DataComponentTypeInteger>();
460 return std::make_shared<DataComponentTypeItemAttributeModifiers>();
462 return std::make_shared<DataComponentTypeItemContainerContents>();
465 return std::make_shared<DataComponentTypeItemEnchantments>();
467 return std::make_shared<DataComponentTypeItemLore>();
468#if PROTOCOL_VERSION > 766 /* > 1.20.6 */
470 return std::make_shared<DataComponentTypeJukeboxPlayable>();
471#endif
473 return std::make_shared<DataComponentTypeListBeehiveBlockEntityOccupant>();
475 return std::make_shared<DataComponentTypeLodestoneTracker>();
477 return std::make_shared<DataComponentTypeMapId>();
479 return std::make_shared<DataComponentTypeMapItemColor>();
481 return std::make_shared<DataComponentTypeMapPostProcessing>();
483 return std::make_shared<DataComponentTypePotDecorations>();
485 return std::make_shared<DataComponentTypePotionContents>();
487 return std::make_shared<DataComponentTypeRarity>();
489 return std::make_shared<DataComponentTypeResolvableProfile>();
491#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
493 return std::make_shared<DataComponentTypeDamageResistant>();
496#endif
497#if PROTOCOL_VERSION < 774 /* < 1.21.11 */
498 return std::make_shared<DataComponentTypeResourceLocation>();
499#else
500 return std::make_shared<DataComponentTypeIdentifier>();
501#endif
503 return std::make_shared<DataComponentTypeSuspiciousStewEffects>();
505 return std::make_shared<DataComponentTypeTool>();
506#if PROTOCOL_VERSION < 770 /* < 1.21.5 */
508 return std::make_shared<DataComponentTypeUnbreakable>();
509#else
510 // From custom Unbreakable to Unit in 1.21.5
512#endif
513#if PROTOCOL_VERSION < 770 /* < 1.21.5 */
514 case DataComponentTypes::HideAdditionalTooltip:
515 case DataComponentTypes::HideTooltip:
516#endif
518#if PROTOCOL_VERSION < 768 /* < 1.21.2 */
519 case DataComponentTypes::FireResistant:
520#endif
521 return std::make_shared<DataComponentTypeUnit>();
523 return std::make_shared<DataComponentTypeWritableBookContent>();
525 return std::make_shared<DataComponentTypeWrittenBookContent>();
526#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
528 return std::make_shared<DataComponentTypeConsumable>();
530 return std::make_shared<DataComponentTypeDeathProtection>();
532 return std::make_shared<DataComponentTypeEquippable>();
534 return std::make_shared<DataComponentTypeRepairable>();
536 return std::make_shared<DataComponentTypeUseCooldown>();
538 return std::make_shared<DataComponentTypeUseRemainder>();
539#endif
540#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
542 return std::make_shared<DataComponentTypeBlocksAttacks>();
544 return std::make_shared<DataComponentTypeBreakSound>();
546 return std::make_shared<DataComponentTypePaintingVariant>();
548 return std::make_shared<DataComponentTypeFloat>();
550 return std::make_shared<DataComponentTypeProvidesBannerPattern>();
552 return std::make_shared<DataComponentTypeProvidesTrimMaterial>();
554 return std::make_shared<DataComponentTypeTooltipDisplay>();
556 return std::make_shared<DataComponentTypeWeapon>();
557#if PROTOCOL_VERSION < 775 /* < 1.21.11 */
559 return std::make_shared<DataComponentTypeEitherRegistryVarint>();
560#endif
576 return std::make_shared<DataComponentTypeVariantEnum>();
583 return std::make_shared<DataComponentTypeDyeColor>();
584#endif
585#if PROTOCOL_VERSION > 772 /* > 1.21.8 */
588 return std::make_shared<DataComponentTypeTypedEntityData>();
589#endif
590#if PROTOCOL_VERSION > 773 /* > 1.21.10 */
592 return std::make_shared<DataComponentTypeUseEffects>();
594 return std::make_shared<DataComponentTypeFloat>();
596 return std::make_shared<DataComponentTypeAttackRange>();
597#if PROTOCOL_VERSION < 775 /* < 1.21.11 */
600 return std::make_shared<DataComponentTypeEitherRegistryVarint>();
601#endif
603 return std::make_shared<DataComponentTypePiercingWeapon>();
605 return std::make_shared<DataComponentTypeKineticWeapon>();
607 return std::make_shared<DataComponentTypeSwingAnimation>();
608#endif
609#if PROTOCOL_VERSION > 774 /* > 1.21.11 */
611 return std::make_shared<DataComponentTypeDyeColor>();
619 return std::make_shared<DataComponentTypeVariantEnum>();
621 return std::make_shared<DataComponentTypeInteger>();
622#endif
623#if PROTOCOL_VERSION > 775 /* > 26.1.2 */
625 return std::make_shared<DataComponentTypeSulfurCubeContent>();
626#endif
627 default:
628 // Should never happen but will make the compilers happy
629 throw std::runtime_error("Unable to create data component with id: " + std::to_string(static_cast<int>(type)) + ".");
630 }
631 }
632
637
638 const std::map<DataComponentTypes, std::shared_ptr<DataComponentType>>& DataComponentPredicate::GetMap() const
639 {
640 return map;
641 }
642
643 DataComponentPredicate& DataComponentPredicate::SetMap(const std::map<DataComponentTypes, std::shared_ptr<DataComponentType>>& map_)
644 {
645 map = map_;
646 return *this;
647 }
648
650 {
651 // special case, dynamic factory
652 const int map_size = ReadData<VarInt>(iter, length);
653 map.clear();
654 for (int i = 0; i < map_size; ++i)
655 {
656 const DataComponentTypes k = ReadData<DataComponentTypes, VarInt>(iter, length);
657 std::shared_ptr<DataComponentType> v = CreateComponentType(k);
658 if (v != nullptr)
659 {
660 v->Read(iter, length);
661 }
662 map[k] = v;
663 }
664 }
665
667 {
668 // special case, dynamic factory
669 WriteData<VarInt>(static_cast<int>(map.size()), container);
670 for (const auto& [k, v] : map)
671 {
672 WriteData<DataComponentTypes, VarInt>(k, container);
673 if (v != nullptr)
674 {
675 v->Write(container);
676 }
677 }
678 }
679
681 {
682 Json::Value output;
683
684 output["map"] = Json::Array();
685 for (const auto& p : map)
686 {
687 output["map"].push_back({
688 { "name", DataComponentTypesToString(p.first) },
689 { "data", p.second == nullptr ? nullptr : p.second->Serialize() }
690 });
691 }
692
693 return output;
694 }
695
696
701
702 const std::map<DataComponentTypes, std::shared_ptr<DataComponentType>>& DataComponentPatch::GetMap() const
703 {
704 return map;
705 }
706
707 DataComponentPatch& DataComponentPatch::SetMap(const std::map<DataComponentTypes, std::shared_ptr<DataComponentType>>& map_)
708 {
709 map = map_;
710 return *this;
711 }
712
713 void DataComponentPatch::ReadImpl(ReadIterator& iter, size_t& length)
714 {
715 const int num_data = ReadData<VarInt>(iter, length);
716 const int num_void = ReadData<VarInt>(iter, length);
717
718 map.clear();
719
720 for (int i = 0; i < num_data; ++i)
721 {
722 const DataComponentTypes type = ReadData<DataComponentTypes, VarInt>(iter, length);
723 std::shared_ptr<DataComponentType> data = CreateComponentType(type);
724
725 if (data != nullptr)
726 {
727 data->Read(iter, length);
728 }
729 map.insert({ type, data });
730 }
731
732 for (int i = 0; i < num_void; ++i)
733 {
734 const DataComponentTypes type = ReadData<DataComponentTypes, VarInt>(iter, length);
735 map.insert({ type, nullptr });
736 }
737 }
738
740 {
741 int num_data = 0;
742 for (const auto& p : map)
743 {
744 num_data += p.second != nullptr;
745 }
746 const int num_void = static_cast<int>(map.size()) - num_data;
747
748 WriteData<VarInt>(num_data, container);
749 WriteData<VarInt>(num_void, container);
750
751 for (const auto& p : map)
752 {
753 if (p.second == nullptr)
754 {
755 continue;
756 }
757 WriteData<DataComponentTypes, VarInt>(p.first, container);
758 p.second->Write(container);
759 }
760
761 for (const auto& p : map)
762 {
763 if (p.second != nullptr)
764 {
765 continue;
766 }
767 WriteData<DataComponentTypes, VarInt>(p.first, container);
768 }
769 }
770
772 {
773 Json::Value output;
774
775 output["map"] = Json::Array();
776 for (const auto& p : map)
777 {
778 output["map"].push_back({
779 { "name", DataComponentTypesToString(p.first) },
780 { "data", p.second == nullptr ? nullptr : p.second->Serialize() }
781 });
782 }
783
784 return output;
785 }
786
787#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
789 {
790 for (const auto& [k, v] : patch.GetMap())
791 {
792 if (v == nullptr)
793 {
794 RemovedComponents.push_back(k);
795 }
796 else
797 {
798 // TODO: Fix this, this is *NOT* how the components are serialized to bytes
799 std::vector<unsigned char> serialized;
800 WriteData<DataComponentTypes, VarInt>(k, serialized);
801 v->Write(serialized);
802 // This however should be the right CRC32C hash calculation
803 // CRC32c polynomial, from https://en.wikipedia.org/wiki/Cyclic_redundancy_check#Polynomial_representations
804 // no idea why we need the reversed one but it works
805 constexpr unsigned int polynomial = 0x82F63B78;
806
807 unsigned int crc = 0xFFFFFFFF;
808
809 for (const auto byte : serialized)
810 {
811 crc ^= byte;
812 // TODO: replace slow loop with a faster version with lookup table and cool fancy stuff ?
813 for (int i = 0; i < 8; ++i)
814 {
815 // Trick to replace if branch
816 // if (crc & 1) crc = (crc >> 1) ^ polynomial;
817 // else crc = crc >> 1;
818 // Works because a ^ 0 == a
819 crc = (crc >> 1) ^ (crc & 1) * polynomial;
820 }
821 }
822 AddedComponents[k] = static_cast<int>(~crc);
823 }
824 }
825 }
826
828#endif
829 }
830}
831#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