mirror of
https://github.com/mcMMO-Dev/mcMMO.git
synced 2024-11-24 14:16:45 +01:00
Fixes, Cleanup, and Comments for actions that need further investigation
This commit is contained in:
parent
1f20e6344b
commit
23dede6b97
@ -49,6 +49,7 @@ public class PtpAcceptCommand implements CommandExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mcMMO.p.getGeneralConfig().getPTPCommandWorldPermissions()) {
|
if (mcMMO.p.getGeneralConfig().getPTPCommandWorldPermissions()) {
|
||||||
|
// TODO TECH CHECK - running operations on teleporting player and target player without the proper thread
|
||||||
World targetWorld = target.getWorld();
|
World targetWorld = target.getWorld();
|
||||||
World playerWorld = player.getWorld();
|
World playerWorld = player.getWorld();
|
||||||
|
|
||||||
@ -64,6 +65,7 @@ public class PtpAcceptCommand implements CommandExecutor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO TECH CHECK - running operations on teleporting player and target player without the proper thread
|
||||||
PtpCommand.handleTeleportWarmup(target, player);
|
PtpCommand.handleTeleportWarmup(target, player);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -228,6 +228,7 @@ public class PtpCommand implements TabExecutor {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO TECH CHECK - running operations on teleporting player and target player without the proper thread
|
||||||
protected static void handleTeleportWarmup(Player teleportingPlayer, Player targetPlayer) {
|
protected static void handleTeleportWarmup(Player teleportingPlayer, Player targetPlayer) {
|
||||||
if(UserManager.getPlayer(targetPlayer) == null)
|
if(UserManager.getPlayer(targetPlayer) == null)
|
||||||
{
|
{
|
||||||
@ -250,9 +251,11 @@ public class PtpCommand implements TabExecutor {
|
|||||||
|
|
||||||
if (warmup > 0) {
|
if (warmup > 0) {
|
||||||
teleportingPlayer.sendMessage(LocaleLoader.getString("Teleport.Commencing", warmup));
|
teleportingPlayer.sendMessage(LocaleLoader.getString("Teleport.Commencing", warmup));
|
||||||
|
// TODO TECH CHECK - running operations on teleporting player and target player without the proper thread
|
||||||
mcMMO.p.getFoliaLib().getImpl().runAtEntityLater(teleportingPlayer, new TeleportationWarmup(mcMMOPlayer, mcMMOTarget), 20 * warmup);
|
mcMMO.p.getFoliaLib().getImpl().runAtEntityLater(teleportingPlayer, new TeleportationWarmup(mcMMOPlayer, mcMMOTarget), 20 * warmup);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// TODO TECH CHECK - running operations on teleporting player and target player without the proper thread
|
||||||
EventUtils.handlePartyTeleportEvent(teleportingPlayer, targetPlayer);
|
EventUtils.handlePartyTeleportEvent(teleportingPlayer, targetPlayer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,14 +106,15 @@ public class McrankCommand implements TabExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mcMMOPlayer.actualizeDatabaseATS();
|
mcMMOPlayer.actualizeDatabaseATS();
|
||||||
}
|
|
||||||
|
|
||||||
|
// Assumes sender is player
|
||||||
boolean useBoard = mcMMO.p.getGeneralConfig().getScoreboardsEnabled() && (sender instanceof Player) && (mcMMO.p.getGeneralConfig().getRankUseBoard());
|
boolean useBoard = mcMMO.p.getGeneralConfig().getScoreboardsEnabled() && (sender instanceof Player) && (mcMMO.p.getGeneralConfig().getRankUseBoard());
|
||||||
boolean useChat = !useBoard || mcMMO.p.getGeneralConfig().getRankUseChat();
|
boolean useChat = !useBoard || mcMMO.p.getGeneralConfig().getRankUseChat();
|
||||||
|
|
||||||
mcMMO.p.getFoliaLib().getImpl().runAsync(new McrankCommandAsyncTask(playerName, sender, useBoard, useChat));
|
mcMMO.p.getFoliaLib().getImpl().runAsync(new McrankCommandAsyncTask(playerName, sender, useBoard, useChat));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private long getCDSeconds(McMMOPlayer mcMMOPlayer, long cooldownMillis) {
|
private long getCDSeconds(McMMOPlayer mcMMOPlayer, long cooldownMillis) {
|
||||||
return ((mcMMOPlayer.getDatabaseATS() + cooldownMillis) - System.currentTimeMillis());
|
return ((mcMMOPlayer.getDatabaseATS() + cooldownMillis) - System.currentTimeMillis());
|
||||||
}
|
}
|
||||||
|
@ -242,7 +242,7 @@ public class EntityListener implements Listener {
|
|||||||
|
|
||||||
entity.setMetadata(MetadataConstants.METADATA_KEY_TRAVELING_BLOCK, MetadataConstants.MCMMO_METADATA_VALUE);
|
entity.setMetadata(MetadataConstants.METADATA_KEY_TRAVELING_BLOCK, MetadataConstants.MCMMO_METADATA_VALUE);
|
||||||
TravelingBlockMetaCleanup metaCleanupTask = new TravelingBlockMetaCleanup(entity, pluginRef);
|
TravelingBlockMetaCleanup metaCleanupTask = new TravelingBlockMetaCleanup(entity, pluginRef);
|
||||||
mcMMO.p.getFoliaLib().getImpl().runAtEntityTimer(entity, metaCleanupTask, 20, 20*60); //6000 ticks is 5 minutes
|
mcMMO.p.getFoliaLib().getImpl().runAtEntityTimer(entity, metaCleanupTask, 20, 20*60); // 20*60 ticks is 1 minute
|
||||||
}
|
}
|
||||||
else if (isTracked) {
|
else if (isTracked) {
|
||||||
BlockUtils.setUnnaturalBlock(block);
|
BlockUtils.setUnnaturalBlock(block);
|
||||||
|
@ -589,7 +589,7 @@ public class PlayerListener implements Listener {
|
|||||||
Player player = event.getPlayer();
|
Player player = event.getPlayer();
|
||||||
|
|
||||||
//Delay loading for 3 seconds in case the player has a save task running, its hacky but it should do the trick
|
//Delay loading for 3 seconds in case the player has a save task running, its hacky but it should do the trick
|
||||||
mcMMO.p.getFoliaLib().getImpl().runLaterAsync(new PlayerProfileLoadingTask(player), 60);
|
mcMMO.p.getFoliaLib().getImpl().runLaterAsync(new PlayerProfileLoadingTask(player), 3*20);
|
||||||
|
|
||||||
if (mcMMO.p.getGeneralConfig().getMOTDEnabled() && Permissions.motd(player)) {
|
if (mcMMO.p.getGeneralConfig().getMOTDEnabled() && Permissions.motd(player)) {
|
||||||
Motd.displayAll(player);
|
Motd.displayAll(player);
|
||||||
|
@ -11,6 +11,8 @@ import org.bukkit.event.world.ChunkUnloadEvent;
|
|||||||
import org.bukkit.event.world.StructureGrowEvent;
|
import org.bukkit.event.world.StructureGrowEvent;
|
||||||
import org.bukkit.event.world.WorldUnloadEvent;
|
import org.bukkit.event.world.WorldUnloadEvent;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class WorldListener implements Listener {
|
public class WorldListener implements Listener {
|
||||||
private final mcMMO plugin;
|
private final mcMMO plugin;
|
||||||
|
|
||||||
@ -29,9 +31,16 @@ public class WorldListener implements Listener {
|
|||||||
if(WorldBlacklist.isWorldBlacklisted(event.getWorld()))
|
if(WorldBlacklist.isWorldBlacklisted(event.getWorld()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Using 50 ms later as I do not know of a way to run one tick later (safely)
|
// Under Folia, any two loaded and adjacent chunks will be in the same ticking region. To avoid scheduling many
|
||||||
plugin.getFoliaLib().getImpl().runLater(() -> {
|
// tasks, we will use this assumption.
|
||||||
for (BlockState blockState : event.getBlocks()) {
|
// Therefore, we will schedule the task such that all blocks in the event are handled from the ticking region of
|
||||||
|
// the first block in the event.
|
||||||
|
// Without folia, this will run on the main tick.
|
||||||
|
List<BlockState> blocks = event.getBlocks();
|
||||||
|
BlockState referenceBlock = blocks.get(0);
|
||||||
|
plugin.getFoliaLib().getImpl().runAtLocationLater(referenceBlock.getLocation(), () -> {
|
||||||
|
for (BlockState blockState : blocks) {
|
||||||
|
// The HashChunkManager is thread-safe, we can safely call it from a non-single-threaded environment
|
||||||
mcMMO.getPlaceStore().setFalse(blockState);
|
mcMMO.getPlaceStore().setFalse(blockState);
|
||||||
}
|
}
|
||||||
}, 1);
|
}, 1);
|
||||||
|
@ -32,7 +32,18 @@ public class McrankCommandAsyncTask extends CancellableRunnable {
|
|||||||
public void run() {
|
public void run() {
|
||||||
Map<PrimarySkillType, Integer> skills = mcMMO.getDatabaseManager().readRank(playerName);
|
Map<PrimarySkillType, Integer> skills = mcMMO.getDatabaseManager().readRank(playerName);
|
||||||
|
|
||||||
mcMMO.p.getFoliaLib().getImpl().runNextTick(new McrankCommandDisplayTask(skills, sender, playerName, useBoard, useChat));
|
// If the sender is a player, actions on the player will be taken. Under folia, this needs to run on the
|
||||||
|
// entity's scheduler.
|
||||||
|
if (sender instanceof Player player) {
|
||||||
|
mcMMO.p.getFoliaLib().getImpl().runAtEntityLater(
|
||||||
|
player,
|
||||||
|
new McrankCommandDisplayTask(skills, player, playerName, useBoard, useChat),
|
||||||
|
1
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
McrankCommandDisplayTask task = new McrankCommandDisplayTask(skills, sender, playerName, useBoard, useChat);
|
||||||
|
mcMMO.p.getFoliaLib().getImpl().runNextTick(task);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,6 @@ public class DatabaseConversionTask extends CancellableRunnable {
|
|||||||
public void run() {
|
public void run() {
|
||||||
sourceDatabase.convertUsers(mcMMO.getDatabaseManager());
|
sourceDatabase.convertUsers(mcMMO.getDatabaseManager());
|
||||||
|
|
||||||
mcMMO.p.getFoliaLib().getImpl().runNextTick(t -> sender.sendMessage(message));
|
mcMMO.p.getFoliaLib().getImpl().runLaterAsync(t -> sender.sendMessage(message), 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ public class PlayerProfileLoadingTask extends CancellableRunnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Quit if they logged out
|
// Quit if they logged out
|
||||||
if (!player.isOnline()) {
|
if (!player.isOnline()) { // TODO TECH CHECK - is thread safe? We are running this async
|
||||||
LogUtils.debug(mcMMO.p.getLogger(), "Aborting profile loading recovery for " + player.getName() + " - player logged out");
|
LogUtils.debug(mcMMO.p.getLogger(), "Aborting profile loading recovery for " + player.getName() + " - player logged out");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,10 @@ public class DelayedCropReplant extends CancellableRunnable {
|
|||||||
PlantAnchorType plantAnchorType = PlantAnchorType.NORMAL;
|
PlantAnchorType plantAnchorType = PlantAnchorType.NORMAL;
|
||||||
|
|
||||||
//Remove the metadata marking the block as recently replanted
|
//Remove the metadata marking the block as recently replanted
|
||||||
mcMMO.p.getFoliaLib().getImpl().runAtLocationLater(blockBreakEvent.getBlock().getLocation(), new markPlantAsOld(blockBreakEvent.getBlock().getLocation()), 10);
|
mcMMO.p.getFoliaLib().getImpl().runAtLocationLater(
|
||||||
|
blockBreakEvent.getBlock().getLocation(),
|
||||||
|
new markPlantAsOld(blockBreakEvent.getBlock().getLocation()),
|
||||||
|
10);
|
||||||
|
|
||||||
if(blockBreakEvent.isCancelled()) {
|
if(blockBreakEvent.isCancelled()) {
|
||||||
wasImmaturePlant = true;
|
wasImmaturePlant = true;
|
||||||
@ -101,7 +104,10 @@ public class DelayedCropReplant extends CancellableRunnable {
|
|||||||
|
|
||||||
//Play an effect
|
//Play an effect
|
||||||
ParticleEffectUtils.playGreenThumbEffect(cropLocation);
|
ParticleEffectUtils.playGreenThumbEffect(cropLocation);
|
||||||
mcMMO.p.getFoliaLib().getImpl().runAtLocationLater(newState.getLocation(), new PhysicsBlockUpdate(newState.getBlock(), cropFace, plantAnchorType), 1);
|
mcMMO.p.getFoliaLib().getImpl().runAtLocationLater(
|
||||||
|
newState.getLocation(),
|
||||||
|
new PhysicsBlockUpdate(newState.getBlock(), cropFace, plantAnchorType),
|
||||||
|
1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,6 +259,7 @@ public final class AlchemyPotionBrewer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void scheduleCheck(Player player, BrewingStand brewingStand) {
|
public static void scheduleCheck(Player player, BrewingStand brewingStand) {
|
||||||
|
// TODO TECH CHECK - should be runAtLocation? We are using block data AND player data. Must resolve correctly
|
||||||
mcMMO.p.getFoliaLib().getImpl().runAtEntity(player, new AlchemyBrewCheckTask(player, brewingStand));
|
mcMMO.p.getFoliaLib().getImpl().runAtEntity(player, new AlchemyBrewCheckTask(player, brewingStand));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +131,10 @@ public class HerbalismManager extends SkillManager {
|
|||||||
if(blockState.getBlockData() instanceof Ageable ageable) {
|
if(blockState.getBlockData() instanceof Ageable ageable) {
|
||||||
|
|
||||||
if (ageable.getAge() <= 1) {
|
if (ageable.getAge() <= 1) {
|
||||||
applyXpGain(xpReward, XPGainReason.PVE, XPGainSource.SELF);
|
// Is using Player properties, run this on the Player's Scheduler if under Folia
|
||||||
|
mcMMO.p.getFoliaLib().getImpl().runAtEntity(
|
||||||
|
mmoPlayer.getPlayer(),
|
||||||
|
(task) -> applyXpGain(xpReward, XPGainReason.PVE, XPGainSource.SELF));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -310,7 +313,8 @@ public class HerbalismManager extends SkillManager {
|
|||||||
DelayedHerbalismXPCheckTask delayedHerbalismXPCheckTask = new DelayedHerbalismXPCheckTask(mmoPlayer, delayedChorusBlocks);
|
DelayedHerbalismXPCheckTask delayedHerbalismXPCheckTask = new DelayedHerbalismXPCheckTask(mmoPlayer, delayedChorusBlocks);
|
||||||
|
|
||||||
//Large delay because the tree takes a while to break
|
//Large delay because the tree takes a while to break
|
||||||
mcMMO.p.getFoliaLib().getImpl().runAtEntity(mmoPlayer.getPlayer(), delayedHerbalismXPCheckTask); //Calculate Chorus XP + Bonus Drops 1 tick later
|
Location referenceLocation = delayedChorusBlocks.get(0).getBlockRef().getLocation();
|
||||||
|
mcMMO.p.getFoliaLib().getImpl().runAtLocationLater(referenceLocation, delayedHerbalismXPCheckTask, 1); //Calculate Chorus XP + Bonus Drops 1 tick later
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -741,7 +745,10 @@ public class HerbalismManager extends SkillManager {
|
|||||||
*/
|
*/
|
||||||
private void startReplantTask(int desiredCropAge, BlockBreakEvent blockBreakEvent, BlockState cropState, boolean isImmature) {
|
private void startReplantTask(int desiredCropAge, BlockBreakEvent blockBreakEvent, BlockState cropState, boolean isImmature) {
|
||||||
//Mark the plant as recently replanted to avoid accidental breakage
|
//Mark the plant as recently replanted to avoid accidental breakage
|
||||||
mcMMO.p.getFoliaLib().getImpl().runAtLocationLater(blockBreakEvent.getBlock().getLocation(), new DelayedCropReplant(blockBreakEvent, cropState, desiredCropAge, isImmature), 2 * Misc.TICK_CONVERSION_FACTOR);
|
mcMMO.p.getFoliaLib().getImpl().runAtLocationLater(
|
||||||
|
blockBreakEvent.getBlock().getLocation(),
|
||||||
|
new DelayedCropReplant(blockBreakEvent, cropState, desiredCropAge, isImmature),
|
||||||
|
2 * Misc.TICK_CONVERSION_FACTOR);
|
||||||
blockBreakEvent.getBlock().setMetadata(MetadataConstants.METADATA_KEY_REPLANT, new RecentlyReplantedCropMeta(mcMMO.p, true));
|
blockBreakEvent.getBlock().setMetadata(MetadataConstants.METADATA_KEY_REPLANT, new RecentlyReplantedCropMeta(mcMMO.p, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,7 +130,10 @@ public class MiningManager extends SkillManager {
|
|||||||
|
|
||||||
mmoPlayer.setAbilityDATS(SuperAbilityType.BLAST_MINING, System.currentTimeMillis());
|
mmoPlayer.setAbilityDATS(SuperAbilityType.BLAST_MINING, System.currentTimeMillis());
|
||||||
mmoPlayer.setAbilityInformed(SuperAbilityType.BLAST_MINING, false);
|
mmoPlayer.setAbilityInformed(SuperAbilityType.BLAST_MINING, false);
|
||||||
mcMMO.p.getFoliaLib().getImpl().runAtEntityLater(mmoPlayer.getPlayer(), new AbilityCooldownTask(mmoPlayer, SuperAbilityType.BLAST_MINING), (long) SuperAbilityType.BLAST_MINING.getCooldown() * Misc.TICK_CONVERSION_FACTOR);
|
mcMMO.p.getFoliaLib().getImpl().runAtEntityLater(
|
||||||
|
mmoPlayer.getPlayer(),
|
||||||
|
new AbilityCooldownTask(mmoPlayer, SuperAbilityType.BLAST_MINING),
|
||||||
|
(long) SuperAbilityType.BLAST_MINING.getCooldown() * Misc.TICK_CONVERSION_FACTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -354,12 +354,14 @@ public final class EventUtils {
|
|||||||
return !damageEvent.isCancelled() && !fakeBlockBreakEvent.isCancelled();
|
return !damageEvent.isCancelled() && !fakeBlockBreakEvent.isCancelled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO TECH CHECK - running operations on teleporting player and target player without the proper thread
|
||||||
public static void handlePartyTeleportEvent(Player teleportingPlayer, Player targetPlayer) {
|
public static void handlePartyTeleportEvent(Player teleportingPlayer, Player targetPlayer) {
|
||||||
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(teleportingPlayer);
|
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(teleportingPlayer);
|
||||||
|
|
||||||
if(mcMMOPlayer == null)
|
if(mcMMOPlayer == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// TODO TECH CHECK - running operations on teleporting player and target player without the proper thread
|
||||||
McMMOPartyTeleportEvent event = new McMMOPartyTeleportEvent(teleportingPlayer, targetPlayer, mcMMOPlayer.getParty().getName());
|
McMMOPartyTeleportEvent event = new McMMOPartyTeleportEvent(teleportingPlayer, targetPlayer, mcMMOPlayer.getParty().getName());
|
||||||
mcMMO.p.getServer().getPluginManager().callEvent(event);
|
mcMMO.p.getServer().getPluginManager().callEvent(event);
|
||||||
|
|
||||||
@ -367,7 +369,7 @@ public final class EventUtils {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// teleportingPlayer.teleport(targetPlayer);
|
// TODO TECH CHECK - getting location of target from another thread
|
||||||
mcMMO.p.getFoliaLib().getImpl().teleportAsync(teleportingPlayer, targetPlayer.getLocation());
|
mcMMO.p.getFoliaLib().getImpl().teleportAsync(teleportingPlayer, targetPlayer.getLocation());
|
||||||
|
|
||||||
teleportingPlayer.sendMessage(LocaleLoader.getString("Party.Teleport.Player", targetPlayer.getName()));
|
teleportingPlayer.sendMessage(LocaleLoader.getString("Party.Teleport.Player", targetPlayer.getName()));
|
||||||
|
@ -131,7 +131,8 @@ public class ScoreboardWrapper {
|
|||||||
if (cooldownTask == null) {
|
if (cooldownTask == null) {
|
||||||
// Repeat every 5 seconds.
|
// Repeat every 5 seconds.
|
||||||
// Cancels once all cooldowns are done, using stopCooldownUpdating().
|
// Cancels once all cooldowns are done, using stopCooldownUpdating().
|
||||||
cooldownTask = mcMMO.p.getFoliaLib().getImpl().runAtEntityTimer(player, new ScoreboardCooldownTask(), 5 * Misc.TICK_CONVERSION_FACTOR, 5 * Misc.TICK_CONVERSION_FACTOR);
|
cooldownTask = mcMMO.p.getFoliaLib().getImpl().runAtEntityTimer(player, new ScoreboardCooldownTask(),
|
||||||
|
5 * Misc.TICK_CONVERSION_FACTOR, 5 * Misc.TICK_CONVERSION_FACTOR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -981,6 +981,6 @@ public final class CombatUtils {
|
|||||||
* @param entity the projectile
|
* @param entity the projectile
|
||||||
*/
|
*/
|
||||||
public static void delayArrowMetaCleanup(@NotNull Projectile entity) {
|
public static void delayArrowMetaCleanup(@NotNull Projectile entity) {
|
||||||
mcMMO.p.getFoliaLib().getImpl().runLater(() -> cleanupArrowMetadata(entity), 20*60);
|
mcMMO.p.getFoliaLib().getImpl().runAtEntityLater(entity, () -> cleanupArrowMetadata(entity), 20*60);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,9 @@ public class RankUtils {
|
|||||||
{
|
{
|
||||||
SkillUnlockNotificationTask skillUnlockNotificationTask = new SkillUnlockNotificationTask(mcMMOPlayer, subSkillType, newLevel);
|
SkillUnlockNotificationTask skillUnlockNotificationTask = new SkillUnlockNotificationTask(mcMMOPlayer, subSkillType, newLevel);
|
||||||
|
|
||||||
mcMMO.p.getFoliaLib().getImpl().runAtEntityLater(mcMMOPlayer.getPlayer(), skillUnlockNotificationTask, (count * 100L));
|
long tickDelay = count * 100L; // Delay for this skill's notification
|
||||||
|
if (tickDelay == 0) tickDelay = 1; // Ensure delay always > 0
|
||||||
|
mcMMO.p.getFoliaLib().getImpl().runAtEntityLater(mcMMOPlayer.getPlayer(), skillUnlockNotificationTask, tickDelay);
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user