Botcraft 26.1.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
84
85namespace ProtocolCraft
86{
87 namespace Components
88 {
95#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
97#endif
98#if PROTOCOL_VERSION > 765 /* > 1.20.4 */
100#endif
102#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
104#endif
105#if PROTOCOL_VERSION > 766 /* > 1.20.6 */
107#endif
108#if PROTOCOL_VERSION > 773 /* > 1.21.10 */
110#endif
111#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
114#endif
117#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
119#endif
120#if PROTOCOL_VERSION > 772 /* > 1.21.8 */
123#endif
131
163#if PROTOCOL_VERSION < 774 /* < 1.21.11 */
164 DEFINE_NETWORK_TYPE(DataComponentTypeResourceLocation);
165#endif
168#if PROTOCOL_VERSION < 770 /* < 1.21.5 */
169 DEFINE_NETWORK_TYPE(DataComponentTypeUnbreakable);
170#endif
174#if PROTOCOL_VERSION > 766 /* > 1.20.6 */
176#endif
177#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
185#endif
186#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
197#endif
198#if PROTOCOL_VERSION > 772 /* > 1.21.8 */
200#endif
201#if PROTOCOL_VERSION > 773 /* > 1.21.10 */
208#endif
209
211 {
212 static constexpr std::array<std::string_view, static_cast<size_t>(DataComponentTypes::NUM_DATA_COMPONENT_TYPES)> names = {
213 "custom_data",
214 "max_stack_size",
215 "max_damage",
216 "damage",
217 "unbreakable",
218#if PROTOCOL_VERSION > 773 /* > 1.21.10 */
219 "use_effects",
220#endif
221 "custom_name",
222#if PROTOCOL_VERSION > 773 /* > 1.21.10 */
223 "minimum_attack_charge",
224 "damage_type",
225#endif
226 "item_name",
227#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
228 "item_model",
229#endif
230 "lore",
231 "rarity",
232 "enchantments",
233 "can_place_on",
234 "can_break",
235 "attribute_modifiers",
236 "custom_model_data",
237#if PROTOCOL_VERSION < 770 /* < 1.21.5 */
238 "hide_additional_tooltip",
239 "hide_tooltip",
240#endif
241#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
242 "tooltip_display",
243#endif
244 "repair_cost",
245 "creative_slot_lock",
246 "enchantment_glint_override",
247 "intangible_projectile",
248 "food",
249#if PROTOCOL_VERSION < 768 /* < 1.21.2 */
250 "fire_resistant",
251#endif
252#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
253 "consumable",
254 "use_remainder",
255 "use_cooldown",
256 "damage_resistant",
257#endif
258 "tool",
259#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
260 "weapon",
261#endif
262#if PROTOCOL_VERSION > 773 /* > 1.21.10 */
263 "attack_range",
264#endif
265#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
266 "enchantable",
267 "equippable",
268 "repairable",
269 "glider",
270 "tooltip_style",
271 "death_protection",
272#endif
273#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
274 "blocks_attacks",
275#endif
276#if PROTOCOL_VERSION > 773 /* > 1.21.10 */
277 "piercing_weapon",
278 "kinetic_weapon",
279 "swing_animation",
280#endif
281#if PROTOCOL_VERSION > 774 /* > 1.21.11 */
282 "additional_trade_cost",
283#endif
284 "stored_enchantments",
285#if PROTOCOL_VERSION > 774 /* > 1.21.11 */
286 "dye",
287#endif
288 "dyed_color",
289 "map_color",
290 "map_id",
291 "map_decorations",
292 "map_post_processing",
293 "charged_projectiles",
294 "bundle_contents",
295 "potion_contents",
296#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
297 "potion_duration_scale",
298#endif
299 "suspicious_stew_effects",
300 "writable_book_content",
301 "written_book_content",
302 "trim",
303 "debug_stick_state",
304 "entity_data",
305 "bucket_entity_data",
306 "block_entity_data",
307 "instrument",
308#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
309 "provides_trim_material",
310#endif
311 "ominous_bottle_amplifier",
312#if PROTOCOL_VERSION > 766 /* > 1.20.6 */
313 "jukebox_playable",
314#endif
315#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
316 "provides_banner_patterns",
317#endif
318 "recipes",
319 "lodestone_tracker",
320 "firework_explosion",
321 "fireworks",
322 "profile",
323 "note_block_sound",
324 "banner_patterns",
325 "base_color",
326 "pot_decorations",
327 "container",
328 "block_state",
329 "bees",
330 "lock",
331 "container_loot",
332#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
333 "break_sound",
334 "villager/variant",
335 "wolf/variant",
336 "wolf/sound_variant",
337 "wolf/collar",
338 "fox/variant",
339 "salmon/size",
340 "parrot/variant",
341 "tropical_fish/pattern",
342 "tropical_fish/base_color",
343 "tropical_fish/pattern_color",
344 "mooshroom/variant",
345 "rabbit/variant",
346 "pig/variant",
347#if PROTOCOL_VERSION > 774 /* > 1.21.11 */
348 "pig/sound_variant",
349#endif
350 "cow/variant",
351#if PROTOCOL_VERSION > 774 /* > 1.21.11 */
352 "cow/sound_variant",
353#endif
354 "chicken/variant",
355#if PROTOCOL_VERSION > 774 /* > 1.21.11 */
356 "chicken/sound_variant",
357#endif
358#if PROTOCOL_VERSION > 773 /* > 1.21.10 */
359 "zombie_nautilus/variant",
360#endif
361 "frog/variant",
362 "horse/variant",
363 "painting/variant",
364 "llama/variant",
365 "axolotl/variant",
366 "cat/variant",
367#if PROTOCOL_VERSION > 774 /* > 1.21.11 */
368 "cat/sound_variant",
369#endif
370 "cat/collar",
371 "sheep/color",
372 "shulker/color",
373#endif
374 };
375 if (type <= DataComponentTypes::None || type >= DataComponentTypes::NUM_DATA_COMPONENT_TYPES)
376 {
377 return "";
378 }
379 return names[static_cast<size_t>(type)];
380 }
381
382 std::shared_ptr<DataComponentType> CreateComponentType(const DataComponentTypes type)
383 {
384 if (type <= DataComponentTypes::None || type >= DataComponentTypes::NUM_DATA_COMPONENT_TYPES)
385 {
386 throw std::runtime_error("Unable to create data component with id: " + std::to_string(static_cast<int>(type)) + ".");
387 }
388
389 switch (type)
390 {
393 return std::make_shared<DataComponentTypeAdventureModePredicate>();
395 return std::make_shared<DataComponentTypeArmorTrim>();
397 return std::make_shared<DataComponentTypeBannerPatternLayers>();
399 return std::make_shared<DataComponentTypeBlockItemStateProperties>();
401 return std::make_shared<DataComponentTypeBoolean>();
403 return std::make_shared<DataComponentTypeBundleContents>();
405 return std::make_shared<DataComponentTypeChargedProjectiles>();
408 return std::make_shared<DataComponentTypeComponent>();
410#if PROTOCOL_VERSION < 773 /* < 1.21.9 */
413#endif
414 return std::make_shared<DataComponentTypeCustomData>();
416 return std::make_shared<DataComponentTypeCustomModelData>();
424#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
426#endif
427 // Component with no network serializer specified fallback to NBT
428 return std::make_shared<DataComponentTypeDefault>();
430 return std::make_shared<DataComponentTypeDyeColor>();
432 return std::make_shared<DataComponentTypeDyedItemColor>();
434 return std::make_shared<DataComponentTypeFireworkExplosion>();
436 return std::make_shared<DataComponentTypeFireworks>();
438 return std::make_shared<DataComponentTypeFoodProperties>();
440 return std::make_shared<DataComponentTypeInstrument>();
446#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
448#endif
449 return std::make_shared<DataComponentTypeInteger>();
451 return std::make_shared<DataComponentTypeItemAttributeModifiers>();
453 return std::make_shared<DataComponentTypeItemContainerContents>();
456 return std::make_shared<DataComponentTypeItemEnchantments>();
458 return std::make_shared<DataComponentTypeItemLore>();
459#if PROTOCOL_VERSION > 766 /* > 1.20.6 */
461 return std::make_shared<DataComponentTypeJukeboxPlayable>();
462#endif
464 return std::make_shared<DataComponentTypeListBeehiveBlockEntityOccupant>();
466 return std::make_shared<DataComponentTypeLodestoneTracker>();
468 return std::make_shared<DataComponentTypeMapId>();
470 return std::make_shared<DataComponentTypeMapItemColor>();
472 return std::make_shared<DataComponentTypeMapPostProcessing>();
474 return std::make_shared<DataComponentTypePotDecorations>();
476 return std::make_shared<DataComponentTypePotionContents>();
478 return std::make_shared<DataComponentTypeRarity>();
480 return std::make_shared<DataComponentTypeResolvableProfile>();
482#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
484 return std::make_shared<DataComponentTypeDamageResistant>();
487#endif
488#if PROTOCOL_VERSION < 774 /* < 1.21.11 */
489 return std::make_shared<DataComponentTypeResourceLocation>();
490#else
491 return std::make_shared<DataComponentTypeIdentifier>();
492#endif
494 return std::make_shared<DataComponentTypeSuspiciousStewEffects>();
496 return std::make_shared<DataComponentTypeTool>();
497#if PROTOCOL_VERSION < 770 /* < 1.21.5 */
499 return std::make_shared<DataComponentTypeUnbreakable>();
500#else
501 // From custom Unbreakable to Unit in 1.21.5
503#endif
504#if PROTOCOL_VERSION < 770 /* < 1.21.5 */
505 case DataComponentTypes::HideAdditionalTooltip:
506 case DataComponentTypes::HideTooltip:
507#endif
509#if PROTOCOL_VERSION < 768 /* < 1.21.2 */
510 case DataComponentTypes::FireResistant:
511#endif
512 return std::make_shared<DataComponentTypeUnit>();
514 return std::make_shared<DataComponentTypeWritableBookContent>();
516 return std::make_shared<DataComponentTypeWrittenBookContent>();
517#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
519 return std::make_shared<DataComponentTypeConsumable>();
521 return std::make_shared<DataComponentTypeDeathProtection>();
523 return std::make_shared<DataComponentTypeEquippable>();
525 return std::make_shared<DataComponentTypeRepairable>();
527 return std::make_shared<DataComponentTypeUseCooldown>();
529 return std::make_shared<DataComponentTypeUseRemainder>();
530#endif
531#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
533 return std::make_shared<DataComponentTypeBlocksAttacks>();
535 return std::make_shared<DataComponentTypeBreakSound>();
537 return std::make_shared<DataComponentTypePaintingVariant>();
539 return std::make_shared<DataComponentTypeFloat>();
541 return std::make_shared<DataComponentTypeProvidesBannerPattern>();
543 return std::make_shared<DataComponentTypeProvidesTrimMaterial>();
545 return std::make_shared<DataComponentTypeTooltipDisplay>();
547 return std::make_shared<DataComponentTypeWeapon>();
548#if PROTOCOL_VERSION < 775 /* < 1.21.11 */
550 return std::make_shared<DataComponentTypeEitherRegistryVarint>();
551#endif
567 return std::make_shared<DataComponentTypeVariantEnum>();
574 return std::make_shared<DataComponentTypeDyeColor>();
575#endif
576#if PROTOCOL_VERSION > 772 /* > 1.21.8 */
579 return std::make_shared<DataComponentTypeTypedEntityData>();
580#endif
581#if PROTOCOL_VERSION > 773 /* > 1.21.10 */
583 return std::make_shared<DataComponentTypeUseEffects>();
585 return std::make_shared<DataComponentTypeFloat>();
587 return std::make_shared<DataComponentTypeAttackRange>();
588#if PROTOCOL_VERSION < 775 /* < 1.21.11 */
591 return std::make_shared<DataComponentTypeEitherRegistryVarint>();
592#endif
594 return std::make_shared<DataComponentTypePiercingWeapon>();
596 return std::make_shared<DataComponentTypeKineticWeapon>();
598 return std::make_shared<DataComponentTypeSwingAnimation>();
599#endif
600#if PROTOCOL_VERSION > 774 /* > 1.21.11 */
602 return std::make_shared<DataComponentTypeDyeColor>();
610 return std::make_shared<DataComponentTypeVariantEnum>();
612 return std::make_shared<DataComponentTypeInteger>();
613#endif
614 default:
615 // Should never happen but will make the compilers happy
616 throw std::runtime_error("Unable to create data component with id: " + std::to_string(static_cast<int>(type)) + ".");
617 }
618 }
619
624
625 const std::map<DataComponentTypes, std::shared_ptr<DataComponentType>>& DataComponentPredicate::GetMap() const
626 {
627 return map;
628 }
629
630 DataComponentPredicate& DataComponentPredicate::SetMap(const std::map<DataComponentTypes, std::shared_ptr<DataComponentType>>& map_)
631 {
632 map = map_;
633 return *this;
634 }
635
637 {
638 // special case, dynamic factory
639 const int map_size = ReadData<VarInt>(iter, length);
640 map.clear();
641 for (int i = 0; i < map_size; ++i)
642 {
643 const DataComponentTypes k = ReadData<DataComponentTypes, VarInt>(iter, length);
644 std::shared_ptr<DataComponentType> v = CreateComponentType(k);
645 if (v != nullptr)
646 {
647 v->Read(iter, length);
648 }
649 map[k] = v;
650 }
651 }
652
654 {
655 // special case, dynamic factory
656 WriteData<VarInt>(static_cast<int>(map.size()), container);
657 for (const auto& [k, v] : map)
658 {
659 WriteData<DataComponentTypes, VarInt>(k, container);
660 if (v != nullptr)
661 {
662 v->Write(container);
663 }
664 }
665 }
666
668 {
669 Json::Value output;
670
671 output["map"] = Json::Array();
672 for (const auto& p : map)
673 {
674 output["map"].push_back({
675 { "name", DataComponentTypesToString(p.first) },
676 { "data", p.second == nullptr ? nullptr : p.second->Serialize() }
677 });
678 }
679
680 return output;
681 }
682
683
688
689 const std::map<DataComponentTypes, std::shared_ptr<DataComponentType>>& DataComponentPatch::GetMap() const
690 {
691 return map;
692 }
693
694 DataComponentPatch& DataComponentPatch::SetMap(const std::map<DataComponentTypes, std::shared_ptr<DataComponentType>>& map_)
695 {
696 map = map_;
697 return *this;
698 }
699
700 void DataComponentPatch::ReadImpl(ReadIterator& iter, size_t& length)
701 {
702 const int num_data = ReadData<VarInt>(iter, length);
703 const int num_void = ReadData<VarInt>(iter, length);
704
705 map.clear();
706
707 for (int i = 0; i < num_data; ++i)
708 {
709 const DataComponentTypes type = ReadData<DataComponentTypes, VarInt>(iter, length);
710 std::shared_ptr<DataComponentType> data = CreateComponentType(type);
711
712 if (data != nullptr)
713 {
714 data->Read(iter, length);
715 }
716 map.insert({ type, data });
717 }
718
719 for (int i = 0; i < num_void; ++i)
720 {
721 const DataComponentTypes type = ReadData<DataComponentTypes, VarInt>(iter, length);
722 map.insert({ type, nullptr });
723 }
724 }
725
727 {
728 int num_data = 0;
729 for (const auto& p : map)
730 {
731 num_data += p.second != nullptr;
732 }
733 const int num_void = static_cast<int>(map.size()) - num_data;
734
735 WriteData<VarInt>(num_data, container);
736 WriteData<VarInt>(num_void, container);
737
738 for (const auto& p : map)
739 {
740 if (p.second == nullptr)
741 {
742 continue;
743 }
744 WriteData<DataComponentTypes, VarInt>(p.first, container);
745 p.second->Write(container);
746 }
747
748 for (const auto& p : map)
749 {
750 if (p.second != nullptr)
751 {
752 continue;
753 }
754 WriteData<DataComponentTypes, VarInt>(p.first, container);
755 }
756 }
757
759 {
760 Json::Value output;
761
762 output["map"] = Json::Array();
763 for (const auto& p : map)
764 {
765 output["map"].push_back({
766 { "name", DataComponentTypesToString(p.first) },
767 { "data", p.second == nullptr ? nullptr : p.second->Serialize() }
768 });
769 }
770
771 return output;
772 }
773
774#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
776 {
777 for (const auto& [k, v] : patch.GetMap())
778 {
779 if (v == nullptr)
780 {
781 RemovedComponents.push_back(k);
782 }
783 else
784 {
785 // TODO: Fix this, this is *NOT* how the components are serialized to bytes
786 std::vector<unsigned char> serialized;
787 WriteData<DataComponentTypes, VarInt>(k, serialized);
788 v->Write(serialized);
789 // This however should be the right CRC32C hash calculation
790 // CRC32c polynomial, from https://en.wikipedia.org/wiki/Cyclic_redundancy_check#Polynomial_representations
791 // no idea why we need the reversed one but it works
792 constexpr unsigned int polynomial = 0x82F63B78;
793
794 unsigned int crc = 0xFFFFFFFF;
795
796 for (const auto byte : serialized)
797 {
798 crc ^= byte;
799 // TODO: replace slow loop with a faster version with lookup table and cool fancy stuff ?
800 for (int i = 0; i < 8; ++i)
801 {
802 // Trick to replace if branch
803 // if (crc & 1) crc = (crc >> 1) ^ polynomial;
804 // else crc = crc >> 1;
805 // Works because a ^ 0 == a
806 crc = (crc >> 1) ^ (crc & 1) * polynomial;
807 }
808 }
809 AddedComponents[k] = static_cast<int>(~crc);
810 }
811 }
812 }
813
815#endif
816 }
817}
818#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