Skip to content

API Integration

shmitzas edited this page Feb 11, 2026 · 5 revisions

MixScrims provides a comprehensive API for other Swiftly plugins to integrate with and control match functionality. The API allows external plugins to monitor match states, manage teams, control match flow, and interact with the player system.

Key Capabilities:

  • Monitor and control match states and flow
  • Manage team composition and captains
  • Control timeouts and surrenders
  • Handle player assignments and punishment queues
  • Integrate custom matchmaking or tournament systems

Setup

1. Reference the contract DLL in your plugin:

csgo/addons/swiftlys2/plugins/MixScrims/resources/exports/MixScrims.Contract.dll

2. Get the API instance:

using MixScrims.Contract;

public class MyPlugin : BasePlugin
{
    private IMixScrims? _mixScrims;
    
    public MyPlugin(ISwiftlyCore core) : base(core)
    {
    }
    
    public override void UseSharedInterface(IInterfaceManager interfaceManager)
    {
        if (interfaceManager.HasSharedInterface("MixScrims.API"))
        {
            try
            {
                _mixScrims = interfaceManager.GetSharedInterface<IMixScrims>("MixScrims.API");
            }
            catch (Exception ex)
            {
                Logger.LogError($"Failed to get MixScrims API: {ex.Message}");
            }
        }
    }
    
    public override void Unload()
    {
        // API implements IDisposable - managed by Swiftly
        _mixScrims = null;
    }
}

Note: The API interface implements IDisposable, but disposal is automatically managed by the Swiftly framework. You only need to set your reference to null when your plugin unloads.


Available Methods

State Management

Get Current Match State

MatchState currentState = _mixScrims.GetCurrentMatchState();

Returns the current match phase:

State Description
Warmup Players readying up
MapVoting Voting for map
MapLoading Map is loading
MapChosen Map loaded, players readying
PickingTeam Captains picking teams
KnifeRound Knife round active
PickingStartingSide Choosing sides after knife
Match Competitive match in progress
Timeout Team timeout active
Ended Match finished
Reset Match resetting

Set Match State

_mixScrims.SetMatchState(MatchState.Warmup);

Manually sets the match to a specific state. Use with caution as this bypasses normal state transition logic.

Get Current Plugin State

PluginState pluginState = _mixScrims.GetCurrentPluginState();

Returns the plugin mode:

State Description Config
Production Normal mode TestMode: false
Staging Test mode with bots TestMode: true

Set Plugin State

_mixScrims.SetPluginState(PluginState.Production);

Changes the plugin operational mode between Production and Staging.


Team Configuration

Set Team Names

_mixScrims.SetCounterTerroristsTeamName("Team Alpha");
_mixScrims.SetTerroristsTeamName("Team Bravo");

Sets custom display names for CT and T teams. Useful for tournaments or custom team identifiers.

Set Team Captains

_mixScrims.SetCtCaptain(76561198012345678);
_mixScrims.SetTCaptain(76561198087654321);

Assigns specific players as team captains using their Steam ID64.


Match Flow Control

Start Warmup

_mixScrims.StartWarmup();

Initiates the warmup phase where players ready up before match start.

Start Map Voting

_mixScrims.StartMapVoting();

Begins the map voting process, presenting the configured map pool to players.

Start Team Picking

_mixScrims.StartTeamPicking();

Initiates the team selection phase where captains pick players for their teams.

Start Knife Round

_mixScrims.StartKnifeRound();

Begins the knife round to determine which team chooses starting sides.

Start Match

_mixScrims.StartMatch();

Starts the competitive match with live rounds and scoring enabled.

Cancel Match

_mixScrims.CancelMatch();

Immediately cancels the current match and resets all match state.

Change Map

// Official map
_mixScrims.ChangeMap("de_mirage");

// Workshop map
_mixScrims.ChangeMap(workshopId: "123456789");

Changes to a specified map. Provide workshop ID for workshop maps, leave empty for official maps.


Timeout & Surrender

Team Timeouts

_mixScrims.StartTimeoutCt();  // Start CT timeout
_mixScrims.StartTimeoutT();   // Start T timeout
_mixScrims.StopTimeout();     // Stop active timeout

Controls team tactical timeouts during matches.

Team Surrender

_mixScrims.SurrenderCt();  // CT team surrenders
_mixScrims.SurrenderT();   // T team surrenders

Forces immediate surrender for the specified team, ending the match.


Player Management

Ready Status Control

_mixScrims.ForceAllPlayersToReady();
_mixScrims.ForceAllPlayersToUnready();

Overrides all player ready states. Useful for admin control or testing.

Player Removal

// Kick players not in the active match
_mixScrims.KickNotPlayingPlayers("Not in active match");

// Kick players not picked during team selection
_mixScrims.KickNotPickedPlayers("Not selected for teams");

Removes players based on their match participation status. Optional reason parameter included in kick message.

Join Prevention

_mixScrims.PreventNewPlayersJoining(true);  // Block new joins
_mixScrims.PreventNewPlayersJoining(false); // Allow new joins

Controls whether new players can join during an active match. Automatically disabled when match ends.


Picked Players (Team Selection Phase)

Counter-Terrorists Picked Players

// Get list of picked CT players
List<ulong> ctPicked = _mixScrims.GetPickedCtPlayers();

// Add player to CT picked list
_mixScrims.AddPlayerToPickedCtPlayers(76561198012345678);

// Remove player from CT picked list
_mixScrims.RemovePlayerFromPickedCtPlayers(76561198012345678);

Manages the list of players selected for CT team during the picking phase.

Terrorists Picked Players

// Get list of picked T players
List<ulong> tPicked = _mixScrims.GetPickedTPlayers();

// Add player to T picked list
_mixScrims.AddPlayerToPickedTPlayers(76561198087654321);

// Remove player from T picked list
_mixScrims.RemovePlayerFromPickedTPlayers(76561198087654321);

Manages the list of players selected for T team during the picking phase.


Playing Players (Active Match)

Counter-Terrorists Playing Players

// Get list of active CT players in match
List<ulong> ctPlaying = _mixScrims.GetPlayingCtPlayers();

// Add player to active CT roster
_mixScrims.AddPlayerToPlayingCtPlayers(76561198012345678);

// Remove player from active CT roster
_mixScrims.RemovePlayerFromPlayingCtPlayers(76561198012345678);

Manages the roster of players actively participating for CT team during the match.

Terrorists Playing Players

// Get list of active T players in match
List<ulong> tPlaying = _mixScrims.GetPlayingTPlayers();

// Add player to active T roster
_mixScrims.AddPlayerToPlayingTPlayers(76561198087654321);

// Remove player from active T roster
_mixScrims.RemovePlayerFromPlayingTPlayers(76561198087654321);

Manages the roster of players actively participating for T team during the match.


Punishment System

Punishment Queue Management

// Get players awaiting punishment
List<ulong> awaitingPunishment = _mixScrims.GetPlayersWaitingForPunishment(76561198012345678);

// Add player to punishment queue
_mixScrims.AddPlayerToWaitingForPunishmentList(76561198012345678);

// Remove player from punishment queue
_mixScrims.RemovePlayerFromWaitingForPunishmentList(76561198012345678);

Manages the queue of players who disconnected during a match and are awaiting punishment based on configured leave punishment settings.


Usage Examples

Basic: Block Commands During Active Match

public class MyPlugin : BasePlugin
{
    private IMixScrims? _mixScrims;
    
    public MyPlugin(ISwiftlyCore core) : base(core)
    {
    }
    
    public override void UseSharedInterface(IInterfaceManager interfaceManager)
    {
        if (interfaceManager.HasSharedInterface("MixScrims.API"))
        {
            try
            {
                _mixScrims = interfaceManager.GetSharedInterface<IMixScrims>("MixScrims.API");
            }
            catch (Exception ex)
            {
                Logger.LogError($"Failed to get MixScrims API: {ex.Message}");
            }
        }
    }
    
    public void OnPlayerCommand(CCSPlayerController player, string command)
    {
        if (_mixScrims == null) return;
        
        var matchState = _mixScrims.GetCurrentMatchState();
        
        // Block certain commands during active match
        if (matchState == MatchState.Match)
        {
            player.PrintToChat("This command is disabled during matches");
            return;
        }
        
        // Your command logic here
    }
}

Advanced: Custom Team Assignment

public class CustomTeamPlugin : BasePlugin
{
    private IMixScrims? _mixScrims;
    
    // Custom logic to assign teams based on rank/skill
    public void AssignBalancedTeams(List<ulong> players)
    {
        if (_mixScrims == null) return;
        
        // Sort players by skill (your custom logic)
        var sortedPlayers = SortPlayersBySkill(players);
        
        // Assign teams in alternating fashion
        for (int i = 0; i < sortedPlayers.Count; i++)
        {
            if (i % 2 == 0)
                _mixScrims.AddPlayerToPickedCtPlayers(sortedPlayers[i]);
            else
                _mixScrims.AddPlayerToPickedTPlayers(sortedPlayers[i]);
        }
        
        // Set custom team names
        _mixScrims.SetCounterTerroristsTeamName("High Skill");
        _mixScrims.SetTerroristsTeamName("Medium Skill");
        
        // Skip picking phase and start match
        _mixScrims.StartKnifeRound();
    }
}

Advanced: Match Automation

public class MatchAutomationPlugin : BasePlugin
{
    private IMixScrims? _mixScrims;
    private Timer? _autoStartTimer;
    
    // Automatically start match when 10 players ready
    public void CheckAutoStart()
    {
        if (_mixScrims == null) return;
        
        var state = _mixScrims.GetCurrentMatchState();
        
        if (state == MatchState.Warmup)
        {
            // Get all connected players
            var players = Utilities.GetPlayers();
            
            if (players.Count >= 10)
            {
                // Force everyone ready and start voting
                _mixScrims.ForceAllPlayersToReady();
                _mixScrims.StartMapVoting();
            }
        }
    }
    
    // Handle player disconnections during match
    public void OnPlayerDisconnect(CCSPlayerController player)
    {
        if (_mixScrims == null) return;
        
        var state = _mixScrims.GetCurrentMatchState();
        var steamId = player.SteamID;
        
        // If player was in active match, add to punishment queue
        if (state == MatchState.Match)
        {
            var ctPlayers = _mixScrims.GetPlayingCtPlayers();
            var tPlayers = _mixScrims.GetPlayingTPlayers();
            
            if (ctPlayers.Contains(steamId) || tPlayers.Contains(steamId))
            {
                _mixScrims.AddPlayerToWaitingForPunishmentList(steamId);
                Logger.LogInfo($"Player {steamId} added to punishment queue");
            }
        }
    }
}

Advanced: Tournament Mode

public class TournamentPlugin : BasePlugin
{
    private IMixScrims? _mixScrims;
    
    // Setup tournament match with predefined teams
    public void SetupTournamentMatch(string ctTeamName, List<ulong> ctPlayers, 
                                      string tTeamName, List<ulong> tPlayers,
                                      string mapName)
    {
        if (_mixScrims == null) return;
        
        // Set team names
        _mixScrims.SetCounterTerroristsTeamName(ctTeamName);
        _mixScrims.SetTerroristsTeamName(tTeamName);
        
        // Assign players to teams
        foreach (var player in ctPlayers)
            _mixScrims.AddPlayerToPickedCtPlayers(player);
        
        foreach (var player in tPlayers)
            _mixScrims.AddPlayerToPickedTPlayers(player);
        
        // Set captains (first player in each team)
        if (ctPlayers.Count > 0)
            _mixScrims.SetCtCaptain(ctPlayers[0]);
        if (tPlayers.Count > 0)
            _mixScrims.SetTCaptain(tPlayers[0]);
        
        // Prevent random joins during tournament
        _mixScrims.PreventNewPlayersJoining(true);
        
        // Change to tournament map
        _mixScrims.ChangeMap(mapName);
        
        // Start knife round
        _mixScrims.StartKnifeRound();
    }
    
    // Admin force end match
    public void EndTournamentMatch(string reason)
    {
        if (_mixScrims == null) return;
        
        Server.PrintToChatAll($"[Tournament] Match ended: {reason}");
        _mixScrims.CancelMatch();
        _mixScrims.PreventNewPlayersJoining(false);
    }
}

Best Practices & Tips

Null Checking

Always verify the API instance is available before using it:

if (_mixScrims == null)
{
    Logger.LogWarning("MixScrims API not available");
    return;
}

State Validation

Check the current match state before performing operations:

var state = _mixScrims.GetCurrentMatchState();
if (state != MatchState.Match)
{
    // Operation only valid during active match
    return;
}

Steam ID Format

All player-related methods use Steam ID64 (ulong):

ulong steamId = player.SteamID; // Correct format
_mixScrims.AddPlayerToPickedCtPlayers(steamId);

Respect Match Integrity

  • Avoid state changes during critical phases (knife round, active rounds)
  • Use SetMatchState() sparingly - prefer built-in flow methods
  • Don't interrupt timeouts or surrender votes
  • Validate player counts before team operations

Integration Safety

  • Hook into MixScrims state transitions, don't force them
  • Disable conflicting plugin features during matches
  • Log all API interactions for debugging
  • Handle exceptions gracefully to prevent plugin crashes

Common Patterns

Check if match is in progress:

bool isMatchActive = matchState == MatchState.Match 
                  || matchState == MatchState.Timeout;

Check if teams are being formed:

bool isTeamFormation = matchState == MatchState.PickingTeam 
                    || matchState == MatchState.MapChosen;

Check if match is competitive state:

bool isCompetitive = matchState == MatchState.KnifeRound 
                  || matchState == MatchState.Match 
                  || matchState == MatchState.Timeout 
                  || matchState == MatchState.PickingStartingSide;

Performance Considerations

  • Cache match state if checking frequently:

    private MatchState _cachedState;
    private DateTime _lastStateCheck;
    
    public MatchState GetCachedState()
    {
        if ((DateTime.Now - _lastStateCheck).TotalSeconds > 5)
        {
            _cachedState = _mixScrims.GetCurrentMatchState();
            _lastStateCheck = DateTime.Now;
        }
        return _cachedState;
    }
  • Batch player operations when possible:

    // Add multiple players at once
    foreach (var steamId in playerList)
        _mixScrims.AddPlayerToPickedCtPlayers(steamId);

Debugging

Enable detailed logging to monitor API interactions:

Logger.LogInfo($"Current match state: {_mixScrims.GetCurrentMatchState()}");
Logger.LogInfo($"CT Players: {string.Join(", ", _mixScrims.GetPlayingCtPlayers())}");
Logger.LogInfo($"T Players: {string.Join(", ", _mixScrims.GetPlayingTPlayers())}");

Compatibility

  • API is stable across minor MixScrims updates
  • Test with your target MixScrims version
  • Check for API interface existence before use
  • Handle API not available gracefully in your plugin

API Reference Summary

Category Methods
State Management GetCurrentMatchState(), SetMatchState(), GetCurrentPluginState(), SetPluginState()
Team Configuration SetCounterTerroristsTeamName(), SetTerroristsTeamName(), SetCtCaptain(), SetTCaptain()
Match Flow StartWarmup(), StartMapVoting(), StartTeamPicking(), StartKnifeRound(), StartMatch(), CancelMatch(), ChangeMap()
Timeout & Surrender StartTimeoutCt(), StartTimeoutT(), StopTimeout(), SurrenderCt(), SurrenderT()
Player Management ForceAllPlayersToReady(), ForceAllPlayersToUnready(), KickNotPlayingPlayers(), KickNotPickedPlayers(), PreventNewPlayersJoining()
CT Picked Players GetPickedCtPlayers(), AddPlayerToPickedCtPlayers(), RemovePlayerFromPickedCtPlayers()
T Picked Players GetPickedTPlayers(), AddPlayerToPickedTPlayers(), RemovePlayerFromPickedTPlayers()
CT Playing Players GetPlayingCtPlayers(), AddPlayerToPlayingCtPlayers(), RemovePlayerFromPlayingCtPlayers()
T Playing Players GetPlayingTPlayers(), AddPlayerToPlayingTPlayers(), RemovePlayerFromPlayingTPlayers()
Punishment System GetPlayersWaitingForPunishment(), AddPlayerToWaitingForPunishmentList(), RemovePlayerFromWaitingForPunishmentList()

Support & Resources

  • Source Code: GitHub Repository
  • Issue Tracker: Report bugs or request features on GitHub Issues
  • Documentation: Full wiki available in repository

For plugin development questions, refer to the Swiftly Plugin Development Guide.

Clone this wiki locally