Welcome!

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

SignUp Now!

DonutTeams plugin Docs

𝐀𝐝𝐦𝐢𝐧𝐢𝐬𝐭𝐫𝐚𝐭𝐨𝐫𝐬
Jan
26
3
𝐃𝐄𝐕𝐄𝐋𝐎𝐏𝐄𝐑 & 𝐀𝐃𝐌𝐈𝐍
𝐅𝐨𝐮𝐧𝐝𝐞𝐫
𝐌𝐞𝐦𝐛𝐞𝐫
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
 
Last edited:
Top