Welcome!

By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!

Documentation DonutTeams plugin Docs

Official documentation maintained by Shyam Studio.
teams-thumbnail-png.919807

DonutTeams
Team management plugin for Minecraft
Paper/Spigot 1.21+ • Java 21



Installation​


Requirements:
  • Paper/Spigot 1.21+
  • Java 21 or higher
  • License key from Discord

Setup:
1. Download DonutTeams.jar
2. Place in plugins/ folder
3. Start server (generates config.yml)
4. Get license from discord.gg/r6XJyfzhdT
5. Edit plugins/DonutTeams/config.yml:
Code:
License: "your-key-here"
6. Restart server (license requires restart)



Commands​


Player Commands​

CommandDescription
/team create <name>Create a team
/team disbandDisband your team
/team invite <player>Invite a player
/team join <team>Accept invitation
/team leaveLeave your team
/team kick <player>Kick a member
/team infoOpen team GUI
/team homeTeleport to team home
/team sethomeSet team home
/team delhomeDelete team home
/team chatToggle team chat
/team cTeam chat alias
/team pvpToggle friendly fire
/team rename <name>Rename team

Admin Commands​

CommandDescription
/dteam reloadReload configuration
/dteam delete <team>Delete any team
/dteam list [all]List teams
/dteam info <team>View team details
/dteam forcejoin <player> <team>Force player to team
/dteam tphome <team>TP to team home
/dteam blacklist add <name>Blacklist team name
/dteam blacklist remove <name>Remove from blacklist
/dteam blacklist listList blacklisted names
/dteam migrate <source-dest>Migrate databases
/dteam switchstorage <type>Switch storage type



Permissions​


Player:
  • donutteams.* - All player commands
  • donutteams.create
  • donutteams.disband
  • donutteams.invite
  • donutteams.join
  • donutteams.leave
  • donutteams.kick
  • donutteams.info
  • donutteams.home
  • donutteams.sethome
  • donutteams.chat
  • donutteams.rename

Admin:
  • donutteams.admin.* - All admin commands
  • donutteams.admin.reload
  • donutteams.admin.delete
  • donutteams.admin.list
  • donutteams.admin.info
  • donutteams.admin.forcejoin
  • donutteams.admin.blacklist
  • donutteams.admin.migrate



Configuration​


Database​

Code:
database:
  type: SQLITE  # or MYSQL
  mysql:
    host: localhost
    port: 3306
    database: donutteams
    username: root
    password: password
    pool-size: 10

Teams​

Code:
settings:
  invite-expiry-seconds: 30
  team-limit: 50  # Max members per team
 
  features:
    home:
      enabled: true
    pvp:
      enabled: true
    
  teleport:
    delay-seconds: 5
    sound:
      enabled: true
    
  rename:
    cooldown-minutes: 30
    enabled: true

Performance​

Code:
settings:
  performance:
    refresh-cooldown-seconds: 3
    tab-complete-cooldown-ms: 500
    skull-cache:
      max-size: 500
      expire-after-minutes: 15



Developer API​


DonutTeams provides a complete API for plugin developers.

Setup​


Step 1: Add JAR to project
Create libs/ folder, add DonutTeams.jar

Step 2: build.gradle
Code:
dependencies {
    compileOnly files('libs/DonutTeams.jar')
}

Step 3: plugin.yml
YAML:
depend: [DonutTeams]

Step 4: Get API instance
Java:
import og.shyamstudio.donutteams.api.DonutTeamsAPI;

// In onEnable()
if (!Bukkit.getPluginManager().isPluginEnabled("DonutTeams")) {
    getLogger().severe("DonutTeams not found!");
    getServer().getPluginManager().disablePlugin(this);
    return;
}

DonutTeamsAPI api = DonutTeamsAPI.getInstance();
getLogger().info("DonutTeams API ready!");



Basic Usage​


Check if player is in a team:
Java:
DonutTeamsAPI api = DonutTeamsAPI.getInstance();

if (api.isInTeam(player.getUniqueId())) {
    player.sendMessage("You're in a team!");
  
    // Get team name
    String teamName = api.getPlayerTeamName(player.getUniqueId());
    player.sendMessage("Team: " + teamName);
}

Check if two players are teammates:
Java:
UUID player1 = ...;
UUID player2 = ...;

if (api.areTeammates(player1, player2)) {
    // They're in the same team
}

Get team information:
Java:
import og.shyamstudio.donutteams.entity.TeamEntity;
import og.shyamstudio.donutteams.entity.member.TeamMember;

TeamEntity team = api.getTeam("TeamName");
if (team != null) {
    // Get members
    List<TeamMember> members = team.getMembers();
  
    // Get leader
    TeamMember leader = api.getTeamLeader("TeamName");
  
    // Get home location
    Location home = api.getTeamHome("TeamName");
  
    // Check friendly fire
    boolean ff = api.isFriendlyFireEnabled("TeamName");
}



Async Operations​


Most write operations are async for performance. Always handle them properly:

Creating a team:
Java:
api.createTeam("MyTeam", leaderPlayer).thenAccept(success -> {
    if (success) {
        // Run on main thread for Bukkit operations
        Bukkit.getScheduler().runTask(plugin, () -> {
            leaderPlayer.sendMessage("§aTeam created!");
        });
    } else {
        Bukkit.getScheduler().runTask(plugin, () -> {
            leaderPlayer.sendMessage("§cFailed - you may already be in a team");
        });
    }
}).exceptionally(ex -> {
    plugin.getLogger().severe("Error: " + ex.getMessage());
    return null;
});

Adding a player to a team:
Java:
api.addPlayerToTeam("TeamName", targetPlayer).thenAccept(success -> {
    Bukkit.getScheduler().runTask(plugin, () -> {
        if (success) {
            targetPlayer.sendMessage("§aYou joined the team!");
        } else {
            targetPlayer.sendMessage("§cCouldn't join team");
        }
    });
});

Removing a player:
Java:
api.removePlayerFromTeam(playerUUID).thenAccept(success -> {
    if (success) {
        plugin.getLogger().info("Player removed from team");
    }
});

Disbanding a team:
Java:
api.disbandTeam("TeamName").thenAccept(success -> {
    if (success) {
        plugin.getLogger().info("Team disbanded");
    }
});



Permission System​


Team members have granular permissions. Available permissions:

TeamPermission enum:
  • DELETE - Disband team
  • MANAGE - Kick members, edit permissions
  • HOME - Use team home
  • SET_HOME - Set team home
  • PVP - Toggle friendly fire
  • SPEAK - Use team chat
  • INVITE - Invite players

Check permission:
Java:
import og.shyamstudio.donutteams.entity.permission.TeamPermission;

boolean canInvite = api.hasPermission(playerUUID, TeamPermission.INVITE);
boolean isLeader = api.hasPermission(playerUUID, TeamPermission.DELETE);

Grant permission:
Java:
api.grantPermission(playerUUID, TeamPermission.MANAGE).thenAccept(success -> {
    if (success) {
        plugin.getLogger().info("Permission granted");
    }
});

Revoke permission:
Java:
api.revokePermission(playerUUID, TeamPermission.INVITE).thenAccept(success -> {
    if (success) {
        plugin.getLogger().info("Permission revoked");
    }
});



Events​


Listen to team events in your plugin:

Java:
import og.shyamstudio.donutteams.api.events.*;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;

public class TeamListener implements Listener {
  
    @EventHandler
    public void onTeamCreate(TeamCreateEvent event) {
        TeamEntity team = event.getTeam();
        Player leader = event.getLeader();
      
        Bukkit.broadcastMessage(
            "§6" + leader.getName() + " §ecreated team §b" + team.getName()
        );
    }
  
    @EventHandler
    public void onPlayerJoinTeam(TeamPlayerJoinEvent event) {
        String teamName = event.getTeamName();
        Player player = event.getPlayer();
      
        player.sendMessage("§aWelcome to " + teamName + "!");
    }
  
    @EventHandler
    public void onPlayerLeaveTeam(TeamPlayerLeaveEvent event) {
        String teamName = event.getTeamName();
        Player player = event.getPlayer();
      
        player.sendMessage("§7You left " + teamName);
    }
  
    @EventHandler
    public void onTeamDisband(TeamDisbandEvent event) {
        // This event is CANCELLABLE
        if (someCondition) {
            event.setCancelled(true);
        }
      
        TeamEntity team = event.getTeam();
        String reason = event.getReason(); // Optional
    }
  
    @EventHandler
    public void onPermissionChange(TeamPermissionChangeEvent event) {
        TeamMember member = event.getMember();
        TeamPermission permission = event.getPermission();
        boolean granted = event.isGranted();
      
        plugin.getLogger().info(
            member.getName() + " - " +
            permission + ": " + granted
        );
    }
}

// Don't forget to register in onEnable():
getServer().getPluginManager().registerEvents(new TeamListener(), this);



Advanced: Direct Entity Access​


For advanced use cases, you can work directly with TeamEntity and TeamMember:

Java:
import og.shyamstudio.donutteams.entity.TeamEntity;
import og.shyamstudio.donutteams.entity.member.TeamMember;

// Get team entity
TeamEntity team = api.getTeam("TeamName");
if (team != null) {
    // Direct member access
    for (TeamMember member : team.getMembers()) {
        UUID uuid = member.getUniqueId();
        String name = member.getName();
        boolean online = member.isOnline();
        Player bukkitPlayer = member.getBukkitPlayer(); // may be null
      
        // Check permissions
        if (member.hasPermission(TeamPermission.DELETE)) {
            // This is the leader
        }
    }
  
    // Check if specific player is in team
    boolean hasMember = team.hasMember(playerUUID);
  
    // Get creation time
    Instant createdAt = team.getCreatedAt();
}

Async team loading:
Java:
// Recommended for better performance
api.getTeamAsync("TeamName").thenAccept(team -> {
    if (team != null) {
        // Process team data
    }
});

// Same for members
api.getTeamMemberAsync(playerUUID).thenAccept(member -> {
    if (member != null) {
        String teamName = member.getTeamName();
        // Process member data
    }
});



Real-World Examples​


Example 1: Economy integration
Java:
// Give bonus money to team members when leader earns money
@EventHandler
public void onPlayerEarn(PlayerEarnMoneyEvent event) {
    Player leader = event.getPlayer();
    double amount = event.getAmount();
  
    String teamName = api.getPlayerTeamName(leader.getUniqueId());
    if (teamName != null) {
        List<Player> onlineMembers = api.getOnlineTeamMembers(teamName);
        double bonus = amount * 0.1; // 10% bonus
      
        for (Player member : onlineMembers) {
            if (!member.equals(leader)) {
                economy.depositPlayer(member, bonus);
                member.sendMessage("§a+$" + bonus + " team bonus!");
            }
        }
    }
}

Example 2: Prevent PvP between teammates
Java:
@EventHandler
public void onPvP(EntityDamageByEntityEvent event) {
    if (!(event.getEntity() instanceof Player victim)) return;
    if (!(event.getDamager() instanceof Player attacker)) return;
  
    if (api.areTeammates(victim.getUniqueId(), attacker.getUniqueId())) {
        event.setCancelled(true);
        attacker.sendMessage("§cYou can't hurt your teammate!");
    }
}

Example 3: Team-wide teleportation
Java:
public void teleportTeamToLocation(String teamName, Location destination) {
    List<Player> onlineMembers = api.getOnlineTeamMembers(teamName);
  
    for (Player player : onlineMembers) {
        player.teleportAsync(destination).thenAccept(success -> {
            if (success) {
                player.sendMessage("§aTeam teleported!");
            }
        });
    }
}

Example 4: Team-based permissions
Java:
// Give special permission to team leaders
public boolean canUseAdmin(Player player) {
    return api.hasPermission(player.getUniqueId(), TeamPermission.DELETE);
}

// Give special permission to team managers
public boolean canManageRegion(Player player) {
    return api.hasPermission(player.getUniqueId(), TeamPermission.MANAGE);
}



Best Practices​


  • Always use async methods (getTeamAsync, createTeam, etc.) for better performance
  • Check DonutTeamsAPI.isAvailable() before getting instance
  • Use Bukkit.getScheduler().runTask() inside .thenAccept() for Bukkit API calls
  • Cache results if you need them multiple times in short period
  • Use events instead of polling for team changes
  • Handle exceptions in .exceptionally() blocks



PlaceholderAPI​


Placeholder:
  • %team_name% - Player's team name (returns "N/A" if not in team)



Support​


Discord: discord.gg/r6XJyfzhdT

When reporting issues provide:
  • Server version
  • Java version
  • Full console error



DonutTeams • by Ravi_Rai • ShyamStudio
 
Back
Top