feat(Core): Add clustering support (#16832)

Co-authored-by: 3kynox <thierry.prost@gmail.com>
Co-authored-by: nox <nox@noxen.net>
Co-authored-by: Ludwig <sudlud@users.noreply.github.com>
This commit is contained in:
Anton Popovichenko
2026-07-27 18:51:04 +02:00
committed by GitHub
parent f23ac046ab
commit 6f0ba8e896
80 changed files with 3675 additions and 297 deletions
+77
View File
@@ -0,0 +1,77 @@
#ifndef __BATTLEGROUND_API__
#define __BATTLEGROUND_API__
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum BattlegroundErrorCode {
BattlegroundErrorCodeNoError = 0,
BattlegroundErrorCodeNoHandler = 1,
BattlegroundErrorFailedToCreateBG = 2,
BattlegroundErrorBattlegroundNotFound = 3,
} BattlegroundErrorCode;
typedef struct {
uint8_t battlegroundTypeID;
uint32_t arenaType;
bool isRated;
uint32_t mapID;
uint8_t bracketLvl;
uint64_t *hordePlayersToAdd;
int hordePlayersToAddSize;
uint64_t *alliancePlayersToAdd;
int alliancePlayersToAddSize;
uint64_t *randomBGPlayers;
int randomBGPlayersSize;
} BattlegroundStartRequest;
typedef struct {
int errorCode;
uint64_t instanceID;
uint64_t instanceClientID;
} BattlegroundStartResponse;
typedef BattlegroundStartResponse (*BattlegroundStartHandler) (BattlegroundStartRequest* request);
void SetBattlegroundStartHandler(BattlegroundStartHandler h);
BattlegroundStartResponse CallBattlegroundStartHandler(BattlegroundStartRequest* request);
typedef struct {
uint8_t battlegroundTypeID;
uint64_t instanceID;
uint64_t *hordePlayersToAdd;
int hordePlayersToAddSize;
uint64_t *alliancePlayersToAdd;
int alliancePlayersToAddSize;
uint64_t *randomBGPlayers;
int randomBGPlayersSize;
} BattlegroundAddPlayersRequest;
typedef BattlegroundErrorCode (*BattlegroundAddPlayersHandler) (BattlegroundAddPlayersRequest* request);
void SetBattlegroundAddPlayersHandler(BattlegroundAddPlayersHandler h);
BattlegroundErrorCode CallBattlegroundAddPlayersHandler(BattlegroundAddPlayersRequest* request);
typedef enum BattlegroundJoinCheckErrorCode {
BattlegroundJoinCheckErrorCodeOK = 0,
BattlegroundJoinCheckErrorCodeNoHook = 1,
BattlegroundJoinCheckErrorCodeResponseIsFalse = 2,
BattlegroundJoinCheckErrorCodePlayerNotFound = 3,
} BattlegroundJoinCheckErrorCode;
typedef BattlegroundJoinCheckErrorCode (*CanPlayerJoinBattlegroundQueueHandler)(uint64_t playerGuid);
void SetCanPlayerJoinBattlegroundQueueHandler(CanPlayerJoinBattlegroundQueueHandler h);
BattlegroundJoinCheckErrorCode CallCanPlayerJoinBattlegroundQueueHandler(uint64_t playerGuid);
typedef BattlegroundJoinCheckErrorCode (*CanPlayerTeleportToBattlegroundHandler)(uint64_t playerGuid);
void SetCanPlayerTeleportToBattlegroundHandler(CanPlayerTeleportToBattlegroundHandler h);
BattlegroundJoinCheckErrorCode CallCanPlayerTeleportToBattlegroundHandler(uint64_t playerGuid);
#ifdef __cplusplus
}
#endif
#endif
+66
View File
@@ -0,0 +1,66 @@
#ifndef __EVENT_GROUP__
#define __EVENT_GROUP__
#include <stdint.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
enum GroupStatus {
GroupHookStatusOK = 0,
GroupHookStatusNoHook = 1
};
typedef struct {
uint32_t guid;
uint64_t leader;
uint8_t lootMethod;
uint64_t looterGuid;
uint8_t lootThreshold;
uint8_t groupType;
uint8_t difficulty;
uint8_t raidDifficulty;
uint64_t masterLooterGuid;
uint64_t *members;
uint8_t membersSize;
} EventObjectGroup;
typedef void (*OnGroupCreatedHook) (EventObjectGroup *group);
void SetOnGroupCreatedHook(OnGroupCreatedHook h);
int CallOnGroupCreatedHook(EventObjectGroup *group);
typedef void (*OnGroupMemberAddedHook) (uint32_t guid, uint64_t newMemberGuid);
void SetOnGroupMemberAddedHook(OnGroupMemberAddedHook h);
int CallOnGroupMemberAddedHook(uint32_t guid, uint64_t newMemberGuid);
typedef void (*OnGroupMemberRemovedHook) (uint32_t guid, uint64_t removedMemberGuid, uint64_t newLeaderGuid);
void SetOnGroupMemberRemovedHook(OnGroupMemberRemovedHook h);
int CallOnGroupMemberRemovedHook(uint32_t guid, uint64_t removedMemberGuid, uint64_t newLeaderGuid);
typedef void (*OnGroupDisbandedHook) (uint32_t guid);
void SetOnGroupDisbandedHook(OnGroupDisbandedHook h);
int CallOnGroupDisbandedHook(uint32_t guid);
typedef void (*OnGroupLootTypeChangedHook) (uint32_t guid, uint8_t lootMethod, uint64_t looter, uint8_t lootThreshold);
void SetOnGroupLootTypeChangedHook(OnGroupLootTypeChangedHook h);
int CallOnGroupLootTypeChangedHook(uint32_t guid, uint8_t lootMethod, uint64_t looter, uint8_t lootThreshold);
typedef void (*OnGroupDungeonDifficultyChangedHook) (uint32_t guid, uint8_t difficulty);
void SetOnGroupDungeonDifficultyChangedHook(OnGroupDungeonDifficultyChangedHook h);
int CallOnGroupDungeonDifficultyChangedHook(uint32_t guid, uint8_t difficulty);
typedef void (*OnGroupRaidDifficultyChangedHook) (uint32_t guid, uint8_t difficulty);
void SetOnGroupRaidDifficultyChangedHook(OnGroupRaidDifficultyChangedHook h);
int CallOnGroupRaidDifficultyChangedHook(uint32_t guid, uint8_t difficulty);
typedef void (*OnGroupConvertedToRaidHook) (uint32_t guid);
void SetOnGroupConvertedToRaidHook(OnGroupConvertedToRaidHook h);
int CallOnGroupConvertedToRaidHook(uint32_t guid);
#ifdef __cplusplus
}
#endif
#endif
+31
View File
@@ -0,0 +1,31 @@
#ifndef __EVENT_GUILD__
#define __EVENT_GUILD__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
enum GuildHookStatus {
GuildHookStatusOK = 0,
GuildHookStatusNoHook = 1
};
typedef void (*OnGuildMemberAddedHook) (uint64_t /*guild_id*/, uint64_t /*player_guid*/);
void SetOnGuildMemberAddedHook(OnGuildMemberAddedHook h);
int CallOnGuildMemberAddedHook(uint64_t guild_id, uint64_t player_guid);
typedef void (*OnGuildMemberLeftHook) (uint64_t /*guild_id*/, uint64_t /*player_guid*/);
void SetOnGuildMemberLeftHook(OnGuildMemberLeftHook h);
int CallOnGuildMemberLeftHook(uint64_t guild_id, uint64_t player_guid);
typedef void (*OnGuildMemberRemovedHook) (uint64_t /*guild_id*/, uint64_t /*player_guid*/);
void SetOnGuildMemberRemovedHook(OnGuildMemberRemovedHook h);
int CallOnGuildMemberRemovedHook(uint64_t guild_id, uint64_t player_guid);
#ifdef __cplusplus
}
#endif
#endif
+23
View File
@@ -0,0 +1,23 @@
#ifndef __EVENT_SERVERS_REGISTRY__
#define __EVENT_SERVERS_REGISTRY__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
enum ServersRegistryStatus {
ServersRegistryHookStatusOK = 0,
ServersRegistryHookStatusNoHook = 1
};
typedef void (*OnMapsReassignedHook) (uint32_t* /*maps_added*/, int /*maps_added_size*/, uint32_t* /*maps_removed*/, int /*maps_removed_size*/);
void SetOnMapsReassignedHook(OnMapsReassignedHook h);
int CallOnMapsReassignedHook(uint32_t* maps_added, int maps_added_size, uint32_t* maps_removed, int maps_removed_size);
#ifdef __cplusplus
}
#endif
#endif
+116
View File
@@ -0,0 +1,116 @@
#ifndef __LIBSIDECAR_H__
#define __LIBSIDECAR_H__
#include <stdint.h>
#include <stdbool.h>
/* Export/import decoration for Windows DLL */
#ifdef _WIN32
#ifdef TC9_BUILDING_DLL
#define TC9_API __declspec(dllexport)
#else
#define TC9_API __declspec(dllimport)
#endif
#else
#ifdef TC9_BUILDING_DLL
#define TC9_API __attribute__((visibility("default")))
#else
#define TC9_API
#endif
#endif
/* Include all API headers */
#include "battleground-api.h"
#include "events-group.h"
#include "events-guild.h"
#include "events-servers-registry.h"
#include "monitoring.h"
#include "player-interactions-api.h"
#include "player-items-api.h"
#include "player-money-api.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Main library functions */
TC9_API void TC9InitLib(uint16_t port, uint32_t realmID, uint8_t isCrossRealm, char* availableMaps, uint32_t** assignedMaps, int* assignedMapsSize);
TC9_API void TC9GracefulShutdown();
TC9_API void TC9ProcessGRPCOrHTTPRequests();
TC9_API void TC9ProcessEventsHooks();
/* GUID generation */
TC9_API uint64_t TC9GetNextAvailableCharacterGuid(int realmID);
TC9_API uint64_t TC9GetNextAvailableItemGuid(int realmID);
TC9_API uint64_t TC9GetNextAvailableInstanceGuid(int realmID);
/* Map loading notification */
TC9_API void TC9ReadyToAcceptPlayersFromMaps(uint32_t* maps, int mapsLen);
/* Generic NATS pub/sub. Payloads are opaque bytes, subjects are arbitrary.
* Subscription callbacks run on the thread draining TC9ProcessEventsHooks
* (the world update thread), not on the NATS delivery thread. Both return
* 0 on success, -1 on failure.
*
* Example — a mod broadcasting and consuming its own events:
*
* // Publish (any thread):
* const char msg[] = "{\"zone\":1519,\"boss\":466}";
* TC9NatsPublish("mymod.boss.spawned", msg, sizeof(msg) - 1);
*
* // Subscribe once at startup; the handler runs on the world update
* // thread, so it is safe to touch game state from it:
* void OnBossSpawned(const char* subject, const char* payload, int payloadLen)
* {
* std::string data(payload, payloadLen); // payload is not NUL-terminated
* // ... react to the event ...
* }
* TC9NatsSubscribe("mymod.boss.spawned", &OnBossSpawned);
*/
typedef void (*TC9NatsMessageHandler)(const char* subject, const char* payload, int payloadLen);
TC9_API int TC9NatsPublish(const char* subject, const char* payload, int payloadLen);
TC9_API int TC9NatsSubscribe(const char* subject, TC9NatsMessageHandler handler);
/* Matchmaking notifications */
TC9_API void TC9PlayerLeftBattleground(uint64_t playerGUID, uint32_t realmID, uint32_t instanceID);
TC9_API void TC9BattlegroundStatusChanged(uint32_t instanceID, uint8_t status);
/* Event hooks registration */
TC9_API void TC9SetOnGroupCreatedHook(OnGroupCreatedHook h);
TC9_API void TC9SetOnGroupMemberAddedHook(OnGroupMemberAddedHook h);
TC9_API void TC9SetOnGroupMemberRemovedHook(OnGroupMemberRemovedHook h);
TC9_API void TC9SetOnGroupDisbandedHook(OnGroupDisbandedHook h);
TC9_API void TC9SetOnGroupLootTypeChangedHook(OnGroupLootTypeChangedHook h);
TC9_API void TC9SetOnGroupDungeonDifficultyChangedHook(OnGroupDungeonDifficultyChangedHook h);
TC9_API void TC9SetOnGroupRaidDifficultyChangedHook(OnGroupRaidDifficultyChangedHook h);
TC9_API void TC9SetOnGroupConvertedToRaidHook(OnGroupConvertedToRaidHook h);
TC9_API void TC9SetOnGuildMemberAddedHook(OnGuildMemberAddedHook h);
TC9_API void TC9SetOnGuildMemberRemovedHook(OnGuildMemberRemovedHook h);
TC9_API void TC9SetOnGuildMemberLeftHook(OnGuildMemberLeftHook h);
TC9_API void TC9SetOnMapsReassignedHook(OnMapsReassignedHook h);
/* Handler registration for gRPC requests */
TC9_API void TC9SetBattlegroundStartHandler(BattlegroundStartHandler h);
TC9_API void TC9SetBattlegroundAddPlayersHandler(BattlegroundAddPlayersHandler h);
TC9_API void TC9SetCanPlayerJoinBattlegroundQueueHandler(CanPlayerJoinBattlegroundQueueHandler h);
TC9_API void TC9SetCanPlayerTeleportToBattlegroundHandler(CanPlayerTeleportToBattlegroundHandler h);
TC9_API void TC9SetMonitoringDataCollectorHandler(MonitoringDataCollectorHandler h);
TC9_API void TC9SetCanPlayerInteractWithNPCAndFlagsHandler(CanPlayerInteractWithNPCAndFlagsHandler h);
TC9_API void TC9SetCanPlayerInteractWithGOAndTypeHandler(CanPlayerInteractWithGOAndTypeHandler h);
TC9_API void TC9SetGetPlayerItemsByGuidsHandler(GetPlayerItemsByGuidsHandler h);
TC9_API void TC9SetRemoveItemsWithGuidsFromPlayerHandler(RemoveItemsWithGuidsFromPlayerHandler h);
TC9_API void TC9SetAddExistingItemToPlayerHandler(AddExistingItemToPlayerHandler h);
TC9_API void TC9SetGetMoneyForPlayerHandler(GetMoneyForPlayerHandler h);
TC9_API void TC9SetModifyMoneyForPlayerHandler(ModifyMoneyForPlayerHandler h);
#ifdef __cplusplus
}
#endif
#endif /* __LIBSIDECAR_H__ */
+36
View File
@@ -0,0 +1,36 @@
#ifndef __MONITORING__
#define __MONITORING__
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum MonitoringErrorCode {
MonitoringErrorCodeNoError = 0,
MonitoringErrorCodeNoHandler = 1,
} MonitoringErrorCode;
// MonitoringDataCollectorResponse request.
typedef struct {
int errorCode;
uint32_t connectedPlayers;
uint32_t diffMean;
uint32_t diffMedian;
uint32_t diff95Percentile;
uint32_t diff99Percentile;
uint32_t diffMaxPercentile;
} MonitoringDataCollectorResponse;
typedef MonitoringDataCollectorResponse (*MonitoringDataCollectorHandler)();
void SetMonitoringDataCollectorHandler(MonitoringDataCollectorHandler h);
MonitoringDataCollectorResponse CallMonitoringDataCollectorHandler();
#ifdef __cplusplus
}
#endif
#endif
+42
View File
@@ -0,0 +1,42 @@
#ifndef __PLAYER_INTERACTIONS_API__
#define __PLAYER_INTERACTIONS_API__
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum PlayerInteractionErrorCode {
PlayerInteractionErrorCodeNoError = 0,
PlayerInteractionErrorCodeNoHandler = 1,
PlayerInteractionErrorCodeCodePlayerNotFound = 2,
} PlayerInteractionErrorCode;
// CanPlayerInteractWithNPCAndFlags request.
typedef struct {
int errorCode;
bool canInteract;
} CanPlayerInteractWithNPCAndFlagsResponse;
typedef CanPlayerInteractWithNPCAndFlagsResponse (*CanPlayerInteractWithNPCAndFlagsHandler) (uint64_t /*playerGUID*/, uint64_t /*npcGUID*/, uint32_t /*npcFlags*/);
void SetCanPlayerInteractWithNPCAndFlagsHandler(CanPlayerInteractWithNPCAndFlagsHandler h);
CanPlayerInteractWithNPCAndFlagsResponse CallCanPlayerInteractWithNPCAndFlagsHandler(uint64_t player_guid, uint64_t npc_guid, uint32_t npc_flags);
// CanPlayerInteractWithGOAndType request.
typedef struct {
int errorCode;
bool canInteract;
} CanPlayerInteractWithGOAndTypeResponse;
typedef CanPlayerInteractWithGOAndTypeResponse (*CanPlayerInteractWithGOAndTypeHandler) (uint64_t /*playerGUID*/, uint64_t /*goGUID*/, uint8_t /*goType*/);
void SetCanPlayerInteractWithGOAndTypeHandler(CanPlayerInteractWithGOAndTypeHandler h);
CanPlayerInteractWithGOAndTypeResponse CallCanPlayerInteractWithGOAndTypeHandler(uint64_t player_guid, uint64_t go_guid, uint8_t go_type);
#ifdef __cplusplus
}
#endif
#endif
+76
View File
@@ -0,0 +1,76 @@
#ifndef __PLAYER_ITEMS_API__
#define __PLAYER_ITEMS_API__
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum PlayerItemErrorCode {
PlayerItemErrorCodeNoError = 0,
PlayerItemErrorCodeNoHandler = 1,
PlayerItemErrorCodePlayerNotFound = 2,
PlayerItemErrorNoInventorySpace = 3,
PlayerItemErrorUnknownTemplate = 4,
PlayerItemErrorFailedToCreateItem = 5
} PlayerItemErrorCode;
// GetPlayerItemsByGuids request.
typedef struct {
uint64_t guid;
uint32_t entry;
uint64_t owner;
uint8_t bagSlot;
uint8_t slot;
bool isTradable;
uint32_t count;
uint16_t flags;
uint8_t durability;
int8_t randomPropertyID;
const char* text;
} PlayerItem;
typedef struct {
int errorCode;
PlayerItem* items;
int itemsSize;
} GetPlayerItemsByGuidsResponse;
typedef GetPlayerItemsByGuidsResponse (*GetPlayerItemsByGuidsHandler) (uint64_t /*player_guid*/, uint64_t* /*items_guids*/, int /*items_guids_size*/);
void SetGetPlayerItemsByGuidsHandler(GetPlayerItemsByGuidsHandler h);
GetPlayerItemsByGuidsResponse CallGetPlayerItemsByGuidsHandler(uint64_t player_guid, uint64_t* items_guids, int items_guids_size);
// RemoveItemsWithGuidsFromPlayer request.
typedef struct {
int errorCode;
uint64_t* updatedItems;
int updatedItemsSize;
} RemoveItemsWithGuidsFromPlayerResponse;
typedef RemoveItemsWithGuidsFromPlayerResponse (*RemoveItemsWithGuidsFromPlayerHandler) (uint64_t /*player_guid*/, uint64_t* /*items_guids*/, int /*items_guids_size*/, uint64_t /*assign_player_guid*/);
void SetRemoveItemsWithGuidsFromPlayerHandler(RemoveItemsWithGuidsFromPlayerHandler h);
RemoveItemsWithGuidsFromPlayerResponse CallRemoveItemsWithGuidsFromPlayerHandler(uint64_t player_guid, uint64_t* items_guids, int items_guids_size, uint64_t assign_player_guid);
// AddExistingItemToPlayer request.
typedef struct {
uint64_t playerGuid;
uint64_t itemGuid;
uint32_t itemEntry;
uint32_t itemCount;
uint16_t itemFlags;
uint8_t itemDurability;
int8_t itemRandomPropertyID;
} AddExistingItemToPlayerRequest;
typedef PlayerItemErrorCode (*AddExistingItemToPlayerHandler) (AddExistingItemToPlayerRequest*);
void SetAddExistingItemToPlayerHandler(AddExistingItemToPlayerHandler h);
PlayerItemErrorCode CallAddExistingItemToPlayerHandler(AddExistingItemToPlayerRequest*);
#ifdef __cplusplus
}
#endif
#endif
+43
View File
@@ -0,0 +1,43 @@
#ifndef __PLAYER_MONEY_API__
#define __PLAYER_MONEY_API__
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum PlayerMoneyErrorCode {
PlayerMoneyErrorCodeNoError = 0,
PlayerMoneyErrorCodeNoHandler = 1,
PlayerMoneyErrorCodePlayerNotFound = 2,
PlayerMoneyErrorCodeTooMuchMoney = 3,
} PlayerMoneyErrorCode;
// GetMoneyForPlayer request.
typedef struct {
int errorCode;
uint32_t money;
} GetMoneyForPlayerResponse;
typedef GetMoneyForPlayerResponse (*GetMoneyForPlayerHandler) (uint64_t /*player_guid*/);
void SetGetMoneyForPlayerHandler(GetMoneyForPlayerHandler h);
GetMoneyForPlayerResponse CallGetMoneyForPlayerHandler(uint64_t player_guid);
// ModifyMoneyForPlayer request.
typedef struct {
int errorCode;
uint32_t newMoneyValue;
} ModifyMoneyForPlayerResponse;
typedef ModifyMoneyForPlayerResponse (*ModifyMoneyForPlayerHandler) (uint64_t /*player_guid*/, int32_t /*amount*/);
void SetModifyMoneyForPlayerHandler(ModifyMoneyForPlayerHandler h);
ModifyMoneyForPlayerResponse CallModifyMoneyForPlayerHandler(uint64_t player_guid, int32_t amount);
#ifdef __cplusplus
}
#endif
#endif