combatant_delivery_auth.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. #pragma once
  2. #include <array>
  3. #include <cstdint>
  4. #include <span>
  5. #include "../../encoding/bit_reader.h"
  6. #include "../../encoding/bit_writer.h"
  7. namespace sunrise::middleware::bap::activity_message::combatant_delivery {
  8. inline constexpr std::uint32_t kSchema = 0x80807DA1;
  9. inline constexpr std::size_t kBits = 132, kBytes = 17;
  10. struct Request {
  11. std::uint32_t generation{}, revision{}, registryKey{};
  12. std::uint16_t squadIndex{};
  13. };
  14. // AB6600 dispatches Auth .7 to the actor's 80807DB4 interface. Harvester component
  15. // 8080670A implements it at 1029330: create passengers in seats, finish after detach.
  16. // The reference MUST be a squad (type 1); its counts must be reserved beforehand.
  17. // Auth .6 remains absent so delivery cannot replace the movement program.
  18. struct SquadReference { std::uint32_t registryKey{}; std::uint16_t squadIndex{}; };
  19. inline constexpr std::size_t kMaxSquads = 8;
  20. inline constexpr std::size_t kMaxBytes = (kBits + 55 * (kMaxSquads - 1) + 7) / 8;
  21. [[nodiscard]] inline bool encode_many(std::uint32_t generation, std::uint32_t revision,
  22. std::span<const SquadReference> squads, std::span<std::byte> output,
  23. std::size_t& written, std::size_t& bits) noexcept {
  24. written = bits = 0;
  25. if (!generation || generation > 0x7fffffff || !revision || revision > 0x7fffffff
  26. || squads.empty() || squads.size() > kMaxSquads) return false;
  27. for (std::size_t i = 0; i < squads.size(); ++i) {
  28. if (!squads[i].registryKey || squads[i].squadIndex > 32767) return false;
  29. for (std::size_t j = 0; j < i; ++j)
  30. if (squads[i].registryKey == squads[j].registryKey && squads[i].squadIndex == squads[j].squadIndex)
  31. return false;
  32. }
  33. std::array<std::byte, kMaxBytes> b{};
  34. encoding::bits::Writer w(b);
  35. if (!(w.write(1,1) && w.write(generation,31)
  36. && w.write(1,2) && w.write(1,3) && w.write(1,1)
  37. && w.write(0,3) && w.write(1,1) && w.write(squads.size(),4))) return false;
  38. for (const auto& squad : squads)
  39. if (!(w.write(squad.registryKey,32) && w.write(2,7) && w.write(squad.squadIndex + 32768U,16))) return false;
  40. if (!w.write(revision,31)) return false;
  41. const auto usedBits = w.bit_count(); std::size_t used{};
  42. if (!w.finish(used) || output.size() < used) return false;
  43. for (std::size_t i = 0; i < used; ++i) output[i] = b[i];
  44. written = used; bits = usedBits; return true;
  45. }
  46. [[nodiscard]] inline bool encode(const Request& q, std::span<std::byte> output) noexcept {
  47. const std::array<SquadReference,1> squads{{{q.registryKey,q.squadIndex}}};
  48. std::size_t written{}, bits{};
  49. return output.size() == kBytes && encode_many(q.generation,q.revision,squads,output,written,bits);
  50. }
  51. [[nodiscard]] inline bool validate(std::span<const std::byte> b, std::size_t bits) noexcept {
  52. if (bits < kBits || b.size() != (bits+7)/8 || b.size() > kMaxBytes) return false;
  53. encoding::bits::Reader r(b); std::uint64_t v{}, count{};
  54. if (!(r.read(1,v)&&v==1 && r.read(31,v)&&v>0
  55. && r.read(2,v)&&v==1 && r.read(3,v)&&v==1 && r.read(1,v)&&v==1
  56. && r.read(3,v)&&v==0 && r.read(1,v)&&v==1 && r.read(4,count)&&count>0&&count<=kMaxSquads
  57. && bits == kBits + 55*(count-1))) return false;
  58. std::array<SquadReference,kMaxSquads> seen{};
  59. for (std::size_t i=0; i<count; ++i) {
  60. if (!r.read(32,v) || !v) return false;
  61. seen[i].registryKey=static_cast<std::uint32_t>(v);
  62. if (!(r.read(7,v)&&v==2 && r.read(16,v)&&v>=32768)) return false;
  63. seen[i].squadIndex=static_cast<std::uint16_t>(v-32768);
  64. for (std::size_t j=0;j<i;++j)
  65. if (seen[i].registryKey==seen[j].registryKey && seen[i].squadIndex==seen[j].squadIndex) return false;
  66. }
  67. return r.read(31,v)&&v>0 && r.read(static_cast<std::uint8_t>(b.size()*8-bits),v)&&v==0;
  68. }
  69. }