Files
ReSkate/Extension/Plugins/plugin_session_feed.h
T
AyeZeeBB 5c0993afea Plugins: the wider set (phase 3), behind one Game interface the tests fake
- Skater: skater.state() and the skater_state and bail events (events.skater); noclip and boosts
  through the console's own queue, under the host's rules (skater.control); a save point of the
  plugin's own (trainer); the game's HUD hidden while any plugin asks (hud).
- World: park editor objects listed, placed, moved and removed through the editor's own edits and
  the session's object rules (world.objects); time of day, world controls and park rotation as
  the World menu sets them, refused where the host chooses (world.environment); fast travel and
  levels, refused for guests (travel); AI skaters, outside sessions only (world.ai).
- Session: other players' skaters as last heard (session.skaters, a feed the session publishes
  each frame, plugin_session_feed.h); a plugin's tag above a player's nametag (session.nametags);
  voice volume (voice.control); chat lines as events (chat.read) and sending one, one every 3 s
  (chat.send); throwdown state and events (throwdowns).
- Music from outside players (music), progress (progression.read) and game settings
  (settings.read), read only; named actions on keys or pad combos, pressed while the game has the
  input (input); full-screen screens with the input, closed by Esc (ui.screen).
- Libraries and events between plugins: expose, require_plugin, emit, on_plugin; plain data is
  copied across VMs and a plugin in a call cannot be called back into.
- net.http: HTTPS to the hosts reskate-plugin.json's new "domains" lists; no redirects, cookies
  or Windows sign-in; private and local addresses refused; 10 a minute, 4 waiting, 1 MB back.
- Left for engine work (listed in the design doc): respawn and freeze, manuals, the camera, trick
  animations, replays, starting throwdowns, the game's own soundtrack, overlay images, rebinding
  plugin keys in the Binds page, local-only chat lines.
- reskate-test has a wider module (ptest noclip, boost, hidehud, object, night, day, ai, screen,
  bind, music, chat, web by hand); reskate-hostile has chat-spam, edit-spam, travel-spam,
  web-elsewhere, bind-spam and screen-loop.

All host tests pass; not yet tried in game.
2026-10-19 13:49:29 -05:00

58 lines
2.0 KiB
C++

#pragma once
#include <array>
#include <cstdint>
#include <map>
#include <mutex>
#include <optional>
#include <string>
#include <utility>
#include <vector>
// What the session and the plugins hand each other (Extension/Multiplayer/Session/session.cpp
// and plugin_game_runtime.cpp): other players' skaters as the session last heard them, published
// each rendered frame; and the short tags plugins put beside players' nametags. Header only, so
// neither depends on the other. Any thread.
namespace dingosdk::plugin_feed {
struct Peer {
std::uint64_t id{};
std::array<float, 3> position{};
std::array<float, 4> rotation{0, 0, 0, 1}; // x, y, z, w
double age_ms{}; // since its pose arrived, when published
};
struct Tag {
std::string text;
std::uint32_t colour{0xffffffffu}; // IM_COL32 layout
};
namespace detail {
inline std::mutex mutex;
inline std::vector<Peer> peers;
inline std::map<std::pair<std::string, std::uint64_t>, Tag> tags; // (plugin, player)
}
inline void publish_peers(std::vector<Peer> peers) {
std::lock_guard lock(detail::mutex);
detail::peers = std::move(peers);
}
inline std::vector<Peer> latest_peers() {
std::lock_guard lock(detail::mutex);
return detail::peers;
}
inline void set_tag(const std::string& plugin, std::uint64_t player, std::string text, std::uint32_t colour) {
std::lock_guard lock(detail::mutex);
if (text.empty()) detail::tags.erase({plugin, player});
else if (detail::tags.size() < 1024 || detail::tags.contains({plugin, player})) detail::tags[{plugin, player}] = {std::move(text), colour};
}
inline void release_tags(const std::string& plugin) {
std::lock_guard lock(detail::mutex);
std::erase_if(detail::tags, [&](const auto& item) { return item.first.first == plugin; });
}
// The tag a plugin gave this player (the first, when several did).
inline std::optional<Tag> tag_of(std::uint64_t player) {
std::lock_guard lock(detail::mutex);
for (const auto& [key, tag] : detail::tags)
if (key.second == player) return tag;
return std::nullopt;
}
}