Botcraft 1.21.8
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
68
69namespace ProtocolCraft
70{
71 namespace Components
72 {
79#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
81#endif
82#if PROTOCOL_VERSION > 765 /* > 1.20.4 */
84#endif
86#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
88#endif
89#if PROTOCOL_VERSION > 766 /* > 1.20.6 */
91#endif
92#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
95#endif
98#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
100#endif
108
143#if PROTOCOL_VERSION < 770 /* < 1.21.5 */
144 DEFINE_NETWORK_TYPE(DataComponentTypeUnbreakable);
145#endif
149#if PROTOCOL_VERSION > 766 /* > 1.20.6 */
151#endif
152#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
159#endif
160#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
169#endif
170
172 {
173 static constexpr std::array<std::string_view, static_cast<size_t>(DataComponentTypes::NUM_DATA_COMPONENT_TYPES)> names = {
174 "custom_data",
175 "max_stack_size",
176 "max_damage",
177 "damage",
178 "unbreakable",
179 "custom_name",
180 "item_name",
181#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
182 "item_model",
183#endif
184 "lore",
185 "rarity",
186 "enchantments",
187 "can_place_on",
188 "can_break",
189 "attribute_modifiers",
190 "custom_model_data",
191#if PROTOCOL_VERSION < 770 /* < 1.21.5 */
192 "hide_additional_tooltip",
193 "hide_tooltip",
194#endif
195#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
196 "tooltip_display",
197#endif
198 "repair_cost",
199 "creative_slot_lock",
200 "enchantment_glint_override",
201 "intangible_projectile",
202 "food",
203#if PROTOCOL_VERSION < 768 /* < 1.21.2 */
204 "fire_resistant",
205#endif
206#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
207 "consumable",
208 "use_remainder",
209 "use_cooldown",
210 "damage_resistant",
211#endif
212 "tool",
213#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
214 "weapon",
215#endif
216#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
217 "enchantable",
218 "equippable",
219 "repairable",
220 "glider",
221 "tooltip_style",
222 "death_protection",
223#endif
224#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
225 "blocks_attacks",
226#endif
227 "stored_enchantments",
228 "dyed_color",
229 "map_color",
230 "map_id",
231 "map_decorations",
232 "map_post_processing",
233 "charged_projectiles",
234 "bundle_contents",
235 "potion_contents",
236#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
237 "potion_duration_scale",
238#endif
239 "suspicious_stew_effects",
240 "writable_book_content",
241 "written_book_content",
242 "trim",
243 "debug_stick_state",
244 "entity_data",
245 "bucket_entity_data",
246 "block_entity_data",
247 "instrument",
248#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
249 "provides_trim_material",
250#endif
251 "ominous_bottle_amplifier",
252#if PROTOCOL_VERSION > 766 /* > 1.20.6 */
253 "jukebox_playable",
254#endif
255#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
256 "provides_banner_patterns",
257#endif
258 "recipes",
259 "lodestone_tracker",
260 "firework_explosion",
261 "fireworks",
262 "profile",
263 "note_block_sound",
264 "banner_patterns",
265 "base_color",
266 "pot_decorations",
267 "container",
268 "block_state",
269 "bees",
270 "lock",
271 "container_loot",
272#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
273 "break_sound",
274 "villager/variant",
275 "wolf/variant",
276 "wolf/sound_variant",
277 "wolf/collar",
278 "fox/variant",
279 "salmon/size",
280 "parrot/variant",
281 "tropical_fish/pattern",
282 "tropical_fish/base_color",
283 "tropical_fish/pattern_color",
284 "mooshroom/variant",
285 "rabbit/variant",
286 "pig/variant",
287 "cow/variant",
288 "chicken/variant",
289 "frog/variant",
290 "horse/variant",
291 "painting/variant",
292 "llama/variant",
293 "axolotl/variant",
294 "cat/variant",
295 "cat/collar",
296 "sheep/color",
297 "shulker/color",
298#endif
299 };
300 if (type <= DataComponentTypes::None || type >= DataComponentTypes::NUM_DATA_COMPONENT_TYPES)
301 {
302 return "";
303 }
304 return names[static_cast<size_t>(type)];
305 }
306
307 std::shared_ptr<DataComponentType> CreateComponentType(const DataComponentTypes type)
308 {
309 if (type <= DataComponentTypes::None || type >= DataComponentTypes::NUM_DATA_COMPONENT_TYPES)
310 {
311 throw std::runtime_error("Unable to create data component with id: " + std::to_string(static_cast<int>(type)) + ".");
312 }
313
314 switch (type)
315 {
318 return std::make_shared<DataComponentTypeAdventureModePredicate>();
320 return std::make_shared<DataComponentTypeArmorTrim>();
322 return std::make_shared<DataComponentTypeBannerPatternLayers>();
324 return std::make_shared<DataComponentTypeBlockItemStateProperties>();
326 return std::make_shared<DataComponentTypeBoolean>();
328 return std::make_shared<DataComponentTypeBundleContents>();
330 return std::make_shared<DataComponentTypeChargedProjectiles>();
333 return std::make_shared<DataComponentTypeComponent>();
337 return std::make_shared<DataComponentTypeCustomData>();
339 return std::make_shared<DataComponentTypeCustomModelData>();
347#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
349#endif
350 // Component with no network serializer specified fallback to NBT
351 return std::make_shared<DataComponentTypeDefault>();
353 return std::make_shared<DataComponentTypeDyeColor>();
355 return std::make_shared<DataComponentTypeDyedItemColor>();
357 return std::make_shared<DataComponentTypeFireworkExplosion>();
359 return std::make_shared<DataComponentTypeFireworks>();
361 return std::make_shared<DataComponentTypeFoodProperties>();
363 return std::make_shared<DataComponentTypeInstrument>();
369#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
371#endif
372 return std::make_shared<DataComponentTypeInteger>();
374 return std::make_shared<DataComponentTypeItemAttributeModifiers>();
376 return std::make_shared<DataComponentTypeItemContainerContents>();
379 return std::make_shared<DataComponentTypeItemEnchantments>();
381 return std::make_shared<DataComponentTypeItemLore>();
382#if PROTOCOL_VERSION > 766 /* > 1.20.6 */
384 return std::make_shared<DataComponentTypeJukeboxPlayable>();
385#endif
387 return std::make_shared<DataComponentTypeListBeehiveBlockEntityOccupant>();
389 return std::make_shared<DataComponentTypeLodestoneTracker>();
391 return std::make_shared<DataComponentTypeMapId>();
393 return std::make_shared<DataComponentTypeMapItemColor>();
395 return std::make_shared<DataComponentTypeMapPostProcessing>();
397 return std::make_shared<DataComponentTypePotDecorations>();
399 return std::make_shared<DataComponentTypePotionContents>();
401 return std::make_shared<DataComponentTypeRarity>();
403 return std::make_shared<DataComponentTypeResolvableProfile>();
405#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
409#endif
410 return std::make_shared<DataComponentTypeResourceLocation>();
412 return std::make_shared<DataComponentTypeSuspiciousStewEffects>();
414 return std::make_shared<DataComponentTypeTool>();
415#if PROTOCOL_VERSION < 770 /* < 1.21.5 */
417 return std::make_shared<DataComponentTypeUnbreakable>();
418#else
419 // From custom Unbreakable to Unit in 1.21.5
421#endif
422#if PROTOCOL_VERSION < 770 /* < 1.21.5 */
423 case DataComponentTypes::HideAdditionalTooltip:
424 case DataComponentTypes::HideTooltip:
425#endif
427#if PROTOCOL_VERSION < 768 /* < 1.21.2 */
428 case DataComponentTypes::FireResistant:
429#endif
430 return std::make_shared<DataComponentTypeUnit>();
432 return std::make_shared<DataComponentTypeWritableBookContent>();
434 return std::make_shared<DataComponentTypeWrittenBookContent>();
435#if PROTOCOL_VERSION > 767 /* > 1.21.1 */
437 return std::make_shared<DataComponentTypeConsumable>();
439 return std::make_shared<DataComponentTypeDeathProtection>();
441 return std::make_shared<DataComponentTypeEquippable>();
443 return std::make_shared<DataComponentTypeRepairable>();
445 return std::make_shared<DataComponentTypeUseCooldown>();
447 return std::make_shared<DataComponentTypeUseRemainder>();
448#endif
449#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
451 return std::make_shared<DataComponentTypeBlocksAttacks>();
453 return std::make_shared<DataComponentTypeBreakSound>();
455 return std::make_shared<DataComponentTypePaintingVariant>();
457 return std::make_shared<DataComponentTypePotionDurationScale>();
459 return std::make_shared<DataComponentTypeProvidesTrimMaterial>();
461 return std::make_shared<DataComponentTypeTooltipDisplay>();
463 return std::make_shared<DataComponentTypeWeapon>();
466 case DataComponentTypes::Chicken_Variant: // TODO: understand why there is an Either thing in MC code for this one?
480 return std::make_shared<DataComponentTypeVariantEnum>();
487 return std::make_shared<DataComponentTypeDyeColor>();
488#endif
489 default:
490 // Should never happen but will make the compilers happy
491 throw std::runtime_error("Unable to create data component with id: " + std::to_string(static_cast<int>(type)) + ".");
492 }
493 }
494
499
500 const std::map<DataComponentTypes, std::shared_ptr<DataComponentType>>& DataComponentPredicate::GetMap() const
501 {
502 return map;
503 }
504
505 DataComponentPredicate& DataComponentPredicate::SetMap(const std::map<DataComponentTypes, std::shared_ptr<DataComponentType>>& map_)
506 {
507 map = map_;
508 return *this;
509 }
510
512 {
513 // special case, dynamic factory
514 const int map_size = ReadData<VarInt>(iter, length);
515 map.clear();
516 for (int i = 0; i < map_size; ++i)
517 {
518 const DataComponentTypes k = ReadData<DataComponentTypes, VarInt>(iter, length);
519 std::shared_ptr<DataComponentType> v = CreateComponentType(k);
520 if (v != nullptr)
521 {
522 v->Read(iter, length);
523 }
524 map[k] = v;
525 }
526 }
527
529 {
530 // special case, dynamic factory
531 WriteData<VarInt>(static_cast<int>(map.size()), container);
532 for (const auto& [k, v] : map)
533 {
534 WriteData<DataComponentTypes, VarInt>(k, container);
535 if (v != nullptr)
536 {
537 v->Write(container);
538 }
539 }
540 }
541
543 {
544 Json::Value output;
545
546 output["map"] = Json::Array();
547 for (const auto& p : map)
548 {
549 output["map"].push_back({
550 { "name", DataComponentTypesToString(p.first) },
551 { "data", p.second == nullptr ? nullptr : p.second->Serialize() }
552 });
553 }
554
555 return output;
556 }
557
558
563
564 const std::map<DataComponentTypes, std::shared_ptr<DataComponentType>>& DataComponentPatch::GetMap() const
565 {
566 return map;
567 }
568
569 DataComponentPatch& DataComponentPatch::SetMap(const std::map<DataComponentTypes, std::shared_ptr<DataComponentType>>& map_)
570 {
571 map = map_;
572 return *this;
573 }
574
575 void DataComponentPatch::ReadImpl(ReadIterator& iter, size_t& length)
576 {
577 const int num_data = ReadData<VarInt>(iter, length);
578 const int num_void = ReadData<VarInt>(iter, length);
579
580 map.clear();
581
582 for (int i = 0; i < num_data; ++i)
583 {
584 const DataComponentTypes type = ReadData<DataComponentTypes, VarInt>(iter, length);
585 std::shared_ptr<DataComponentType> data = CreateComponentType(type);
586
587 if (data != nullptr)
588 {
589 data->Read(iter, length);
590 }
591 map.insert({ type, data });
592 }
593
594 for (int i = 0; i < num_void; ++i)
595 {
596 const DataComponentTypes type = ReadData<DataComponentTypes, VarInt>(iter, length);
597 map.insert({ type, nullptr });
598 }
599 }
600
602 {
603 int num_data = 0;
604 for (const auto& p : map)
605 {
606 num_data += p.second != nullptr;
607 }
608 const int num_void = static_cast<int>(map.size()) - num_data;
609
610 WriteData<VarInt>(num_data, container);
611 WriteData<VarInt>(num_void, container);
612
613 for (const auto& p : map)
614 {
615 if (p.second == nullptr)
616 {
617 continue;
618 }
619 WriteData<DataComponentTypes, VarInt>(p.first, container);
620 p.second->Write(container);
621 }
622
623 for (const auto& p : map)
624 {
625 if (p.second != nullptr)
626 {
627 continue;
628 }
629 WriteData<DataComponentTypes, VarInt>(p.first, container);
630 }
631 }
632
634 {
635 Json::Value output;
636
637 output["map"] = Json::Array();
638 for (const auto& p : map)
639 {
640 output["map"].push_back({
641 { "name", DataComponentTypesToString(p.first) },
642 { "data", p.second == nullptr ? nullptr : p.second->Serialize() }
643 });
644 }
645
646 return output;
647 }
648
649#if PROTOCOL_VERSION > 769 /* > 1.21.4 */
651 {
652 for (const auto& [k, v] : patch.GetMap())
653 {
654 if (v == nullptr)
655 {
656 RemovedComponents.push_back(k);
657 }
658 else
659 {
660 std::vector<unsigned char> serialized;
661 WriteData<DataComponentTypes, VarInt>(k, serialized);
662 v->Write(serialized);
663 // CRC32c polynomial, from https://en.wikipedia.org/wiki/Cyclic_redundancy_check#Polynomial_representations
664 // no idea why we need the reversed one but it works
665 constexpr unsigned int polynomial = 0x82F63B78;
666
667 unsigned int crc = 0xFFFFFFFF;
668
669 for (const auto byte : serialized)
670 {
671 crc ^= byte;
672 // TODO: replace slow loop with a faster version with lookup table and cool fancy stuff ?
673 for (int i = 0; i < 8; ++i)
674 {
675 // Trick to replace if branch
676 // if (crc & 1) crc = (crc >> 1) ^ polynomial;
677 // else crc = crc >> 1;
678 // Works because a ^ 0 == a
679 crc = (crc >> 1) ^ (crc & 1) * polynomial;
680 }
681 }
682 AddedComponents[k] = static_cast<int>(~crc);
683 }
684 }
685 }
686
688#endif
689 }
690}
691#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