mirror of
https://github.com/Dingo-Shenanigans/ReSkate.git
synced 2026-10-25 00:06:18 +02:00
Plugins register modes (card, replaces, order, flag, players) and publish documents through reskate.throwdowns.ui: the setup page, the waiting card, HUD slots themed on the game's HUD_<theme>_* widgets, the match panel, flags and match restrictions. SmokeyDawg58's native plumbing (throwdown_menu.cpp and its .inl files) renders them and posts throwdown_ui events back. kit::flag is the one native flag registration. General services added for it: reskate.files, reskate.ui.dialog, reskate.skater push/hold/bone_cam, reskate.camera.pad_flight, reskate.physics competition, reskate.session.world, reskate.tricks feed/gesture, and world entities. His ten modes are now Lua in his plugin: the rules, referee and wire (td/rules, referee, wire), and every page and HUD document (td/ui*.lua). Extension/Modes and reskate.modes are gone, along with every race and 1-UP branch in the SDK. The plugin test drives each mode through kit events. A native setup page is never written to while it closes into flag placement: its rows are not republished, the stock page is put back once the exit is over, and the stock Players slider is left alone while a plugin flag is out. This fixes the crashes on the Deathrace button and on 1-UP's Confirm.
51 lines
2.2 KiB
C++
51 lines
2.2 KiB
C++
#pragma once
|
|
#include <array>
|
|
#include <cstdint>
|
|
#include <cstring>
|
|
#include <span>
|
|
#include <string_view>
|
|
|
|
namespace dingosdk::multiplayer {
|
|
inline bool flag_preview_asset_name(std::string_view name) {
|
|
constexpr std::string_view stock="ecs/activities/throwdowns/spotbattlethrowdownerinteractablevalidator_ecsprefab";
|
|
if(name.size()!=stock.size())return false;
|
|
for(std::size_t i=0;i<name.size();++i) {
|
|
const auto c=name[i]>='A' && name[i]<='Z'?name[i]+('a'-'A'):name[i];
|
|
if(c!=stock[i])return false;
|
|
}
|
|
return true;
|
|
}
|
|
inline bool flag_preview_graph(std::uint32_t hash,const std::array<std::uint32_t,10>& layout) {
|
|
struct Graph {std::uint32_t hash;std::array<std::uint32_t,10> layout;};
|
|
constexpr std::array graphs{
|
|
Graph{0x73fd87ef,{80,832,1221,601,6,0,4,655395,4456459,16844800}},
|
|
Graph{0x08a3b8c5,{80,976,1466,756,6,0,4,655409,4456459,16844800}},
|
|
Graph{0x05df4a18,{80,832,1221,601,6,0,4,655395,4456459,16844800}},
|
|
Graph{0x7a9c4313,{80,720,1205,561,6,0,4,655391,4456459,16844800}},
|
|
Graph{0xbb2b2cdd,{80,832,1221,601,6,0,4,655395,4456459,16844800}},
|
|
Graph{0x67122a51,{80,856,1221,601,6,0,4,655395,4456459,16844800}},
|
|
Graph{0xdba685be,{80,720,1205,561,6,0,4,655391,4456459,16844800}}};
|
|
for(const auto& graph:graphs)if(hash==graph.hash && layout==graph.layout)return true;
|
|
return false;
|
|
}
|
|
// Own only an interpreter invocation's pointer, never the asset's shared page.
|
|
// Nested invocations and exceptional exits restore the exact previous page.
|
|
class FlagPreviewPage {
|
|
std::uintptr_t* slot_{};
|
|
std::uintptr_t original_{};
|
|
alignas(16) std::array<std::byte,1024> bytes_;
|
|
public:
|
|
void prepare(std::span<const std::byte> page,std::size_t offset,std::uintptr_t prefab) {
|
|
if(page.size()>bytes_.size() || offset+sizeof(prefab)>page.size())return;
|
|
std::memcpy(bytes_.data(),page.data(),page.size());
|
|
std::memcpy(bytes_.data()+offset,&prefab,sizeof(prefab));
|
|
}
|
|
void publish(std::uintptr_t& slot) {
|
|
slot_=&slot;original_=slot;slot=reinterpret_cast<std::uintptr_t>(bytes_.data());
|
|
}
|
|
~FlagPreviewPage() {if(slot_)*slot_=original_;}
|
|
FlagPreviewPage()=default;
|
|
FlagPreviewPage(const FlagPreviewPage&)=delete;
|
|
};
|
|
}
|