combatant_path_auth.h 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  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_path {
  8. inline constexpr std::uint32_t kSchema = 0x80807DA1;
  9. inline constexpr std::size_t kBits = 156, kBytes = 20;
  10. struct Request {
  11. std::uint32_t generation{}, revision{}, registryKey{};
  12. std::uint16_t pathIndex{};
  13. };
  14. // AB6340 creates the authored member. Auth .6 runs one kind-3 movement command:
  15. // A97BB0 -> 4FFEC0 resolves a type-58 authored path; native AI follows its curve.
  16. // Auth .7 is a squad-reference delivery request, NOT a movement path list.
  17. // Preserve spawn generation while advancing the action-program revision. The authored
  18. // entry/exit curves have two markers: marker 0 is the START, marker 1 the destination.
  19. // AB0C30 resolves the marker index, not an action index or a duration in seconds.
  20. [[nodiscard]] inline bool encode(const Request& request, std::span<std::byte> output) noexcept {
  21. if (output.size() != kBytes || request.generation == 0 || request.generation > 0x7fffffff
  22. || request.revision == 0 || request.revision > 0x7fffffff || request.registryKey == 0
  23. || request.pathIndex > 32767) return false;
  24. std::array<std::byte, kBytes> bytes{};
  25. encoding::bits::Writer w(bytes);
  26. std::size_t written{};
  27. const bool ok = w.write(1, 1) && w.write(request.generation, 31)
  28. && w.write(1, 2) && w.write(1, 3) && w.write(1, 1)
  29. && w.write(0, 2) && w.write(1, 1) // .4/.5 absent; .6 present
  30. && w.write(request.revision, 31) && w.write(0, 6) && w.write(1, 6)
  31. && w.write(1, 1) && w.write(4, 4) && w.write(1, 2) // kind 3, completion 0
  32. && w.write(request.registryKey, 32) && w.write(59, 7)
  33. && w.write(request.pathIndex + 32768U, 16)
  34. && w.write(1, 8) && w.write(1, 1) // destination marker; follow curve
  35. && w.write(0, 1) && w.bit_count() == kBits // .7 absent
  36. && w.finish(written) && written == kBytes;
  37. if (!ok) return false;
  38. for (std::size_t i = 0; i < bytes.size(); ++i) output[i] = bytes[i];
  39. return true;
  40. }
  41. [[nodiscard]] inline bool validate(std::span<const std::byte> input, std::size_t bits) noexcept {
  42. if (bits != kBits || input.size() != kBytes) return false;
  43. encoding::bits::Reader r(input);
  44. std::uint64_t v{}, generation{}, registry{}, index{}, revision{};
  45. return r.read(1, v) && v == 1 && r.read(31, generation) && generation > 0
  46. && r.read(2, v) && v == 1 && r.read(3, v) && v == 1
  47. && r.read(1, v) && v == 1 && r.read(2, v) && v == 0
  48. && r.read(1, v) && v == 1 && r.read(31, revision) && revision > 0
  49. && r.read(6, v) && v == 0 && r.read(6, v) && v == 1
  50. && r.read(1, v) && v == 1 && r.read(4, v) && v == 4
  51. && r.read(2, v) && v == 1 && r.read(32, registry) && registry != 0
  52. && r.read(7, v) && v == 59 && r.read(16, index) && index >= 32768
  53. && r.read(8, v) && v == 1 && r.read(1, v) && v == 1
  54. && r.read(1, v) && v == 0 && r.read(4, v) && v == 0;
  55. }
  56. }