diff --git a/api/src/main/java/net/momirealms/customcrops/api/action/AbstractActionManager.java b/api/src/main/java/net/momirealms/customcrops/api/action/AbstractActionManager.java index da5f84c..3301e73 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/action/AbstractActionManager.java +++ b/api/src/main/java/net/momirealms/customcrops/api/action/AbstractActionManager.java @@ -24,12 +24,14 @@ import net.momirealms.customcrops.api.BukkitCustomCropsPlugin; import net.momirealms.customcrops.api.context.Context; import net.momirealms.customcrops.api.context.ContextKeys; import net.momirealms.customcrops.api.core.*; -import net.momirealms.customcrops.api.core.block.*; +import net.momirealms.customcrops.api.core.block.BreakReason; +import net.momirealms.customcrops.api.core.block.CropBlock; +import net.momirealms.customcrops.api.core.block.PotBlock; +import net.momirealms.customcrops.api.core.mechanic.crop.CropConfig; +import net.momirealms.customcrops.api.core.mechanic.crop.CropStageConfig; import net.momirealms.customcrops.api.core.mechanic.fertilizer.Fertilizer; import net.momirealms.customcrops.api.core.mechanic.fertilizer.FertilizerConfig; import net.momirealms.customcrops.api.core.mechanic.pot.PotConfig; -import net.momirealms.customcrops.api.core.mechanic.crop.CropConfig; -import net.momirealms.customcrops.api.core.mechanic.crop.CropStageConfig; import net.momirealms.customcrops.api.core.world.CustomCropsBlockState; import net.momirealms.customcrops.api.core.world.CustomCropsChunk; import net.momirealms.customcrops.api.core.world.CustomCropsWorld; diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/AbstractCustomEventListener.java b/api/src/main/java/net/momirealms/customcrops/api/core/AbstractCustomEventListener.java index b42624e..c215d9e 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/AbstractCustomEventListener.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/AbstractCustomEventListener.java @@ -21,11 +21,11 @@ import net.momirealms.customcrops.api.BukkitCustomCropsPlugin; import net.momirealms.customcrops.api.action.ActionManager; import net.momirealms.customcrops.api.context.Context; import net.momirealms.customcrops.api.context.ContextKeys; -import net.momirealms.customcrops.api.core.block.*; -import net.momirealms.customcrops.api.core.mechanic.pot.PotConfig; +import net.momirealms.customcrops.api.core.block.CropBlock; import net.momirealms.customcrops.api.core.mechanic.crop.BoneMeal; import net.momirealms.customcrops.api.core.mechanic.crop.CropConfig; import net.momirealms.customcrops.api.core.mechanic.crop.CropStageConfig; +import net.momirealms.customcrops.api.core.mechanic.pot.PotConfig; import net.momirealms.customcrops.api.core.mechanic.sprinkler.SprinklerConfig; import net.momirealms.customcrops.api.core.world.CustomCropsBlockState; import net.momirealms.customcrops.api.core.world.CustomCropsWorld; diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/ConfigManager.java b/api/src/main/java/net/momirealms/customcrops/api/core/ConfigManager.java index 0b2e1ee..b3a36f8 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/ConfigManager.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/ConfigManager.java @@ -12,15 +12,15 @@ import dev.dejvokep.boostedyaml.settings.loader.LoaderSettings; import dev.dejvokep.boostedyaml.settings.updater.UpdaterSettings; import dev.dejvokep.boostedyaml.utils.format.NodeRole; import net.momirealms.customcrops.api.BukkitCustomCropsPlugin; -import net.momirealms.customcrops.api.core.mechanic.fertilizer.FertilizerConfig; -import net.momirealms.customcrops.api.core.mechanic.fertilizer.FertilizerType; -import net.momirealms.customcrops.api.core.mechanic.wateringcan.WateringCanConfig; -import net.momirealms.customcrops.api.core.mechanic.crop.DeathCondition; -import net.momirealms.customcrops.api.core.mechanic.crop.GrowCondition; -import net.momirealms.customcrops.api.core.mechanic.pot.PotConfig; import net.momirealms.customcrops.api.core.mechanic.crop.BoneMeal; import net.momirealms.customcrops.api.core.mechanic.crop.CropConfig; +import net.momirealms.customcrops.api.core.mechanic.crop.DeathCondition; +import net.momirealms.customcrops.api.core.mechanic.crop.GrowCondition; +import net.momirealms.customcrops.api.core.mechanic.fertilizer.FertilizerConfig; +import net.momirealms.customcrops.api.core.mechanic.fertilizer.FertilizerType; +import net.momirealms.customcrops.api.core.mechanic.pot.PotConfig; import net.momirealms.customcrops.api.core.mechanic.sprinkler.SprinklerConfig; +import net.momirealms.customcrops.api.core.mechanic.wateringcan.WateringCanConfig; import net.momirealms.customcrops.api.core.world.CustomCropsBlockState; import net.momirealms.customcrops.api.misc.water.FillMethod; import net.momirealms.customcrops.api.misc.water.WateringMethod; diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/Registries.java b/api/src/main/java/net/momirealms/customcrops/api/core/Registries.java index 4745248..ee6f0b2 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/Registries.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/Registries.java @@ -17,13 +17,13 @@ package net.momirealms.customcrops.api.core; -import net.momirealms.customcrops.api.core.mechanic.crop.CropConfig; import net.momirealms.customcrops.api.core.block.CustomCropsBlock; -import net.momirealms.customcrops.api.core.mechanic.pot.PotConfig; -import net.momirealms.customcrops.api.core.mechanic.sprinkler.SprinklerConfig; import net.momirealms.customcrops.api.core.item.CustomCropsItem; +import net.momirealms.customcrops.api.core.mechanic.crop.CropConfig; import net.momirealms.customcrops.api.core.mechanic.fertilizer.FertilizerConfig; import net.momirealms.customcrops.api.core.mechanic.fertilizer.FertilizerType; +import net.momirealms.customcrops.api.core.mechanic.pot.PotConfig; +import net.momirealms.customcrops.api.core.mechanic.sprinkler.SprinklerConfig; import net.momirealms.customcrops.api.core.mechanic.wateringcan.WateringCanConfig; import net.momirealms.customcrops.common.annotation.DoNotUse; import net.momirealms.customcrops.common.util.Key; diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/block/AbstractCustomCropsBlock.java b/api/src/main/java/net/momirealms/customcrops/api/core/block/AbstractCustomCropsBlock.java index 0f8ad3a..cef84aa 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/block/AbstractCustomCropsBlock.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/block/AbstractCustomCropsBlock.java @@ -78,11 +78,11 @@ public abstract class AbstractCustomCropsBlock implements CustomCropsBlock { } @Override - public void scheduledTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location) { + public void scheduledTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location, boolean offlineTick) { } @Override - public void randomTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location) { + public void randomTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location, boolean offlineTick) { } @Override diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/block/CropBlock.java b/api/src/main/java/net/momirealms/customcrops/api/core/block/CropBlock.java index 0f2852f..30e1ebd 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/block/CropBlock.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/block/CropBlock.java @@ -23,9 +23,9 @@ import net.momirealms.customcrops.api.action.ActionManager; import net.momirealms.customcrops.api.context.Context; import net.momirealms.customcrops.api.context.ContextKeys; import net.momirealms.customcrops.api.core.*; +import net.momirealms.customcrops.api.core.mechanic.crop.*; import net.momirealms.customcrops.api.core.mechanic.fertilizer.Fertilizer; import net.momirealms.customcrops.api.core.mechanic.fertilizer.FertilizerConfig; -import net.momirealms.customcrops.api.core.mechanic.crop.*; import net.momirealms.customcrops.api.core.mechanic.pot.PotConfig; import net.momirealms.customcrops.api.core.world.CustomCropsBlockState; import net.momirealms.customcrops.api.core.world.CustomCropsWorld; @@ -58,16 +58,16 @@ public class CropBlock extends AbstractCustomCropsBlock { } @Override - public void scheduledTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location) { + public void scheduledTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location, boolean offlineTick) { if (!world.setting().randomTickCrop() && canTick(state, world.setting().tickCropInterval())) { - tickCrop(state, world, location); + tickCrop(state, world, location, offlineTick); } } @Override - public void randomTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location) { + public void randomTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location, boolean offlineTick) { if (world.setting().randomTickCrop() && canTick(state, world.setting().tickCropInterval())) { - tickCrop(state, world, location); + tickCrop(state, world, location, offlineTick); } } @@ -273,20 +273,20 @@ public class CropBlock extends AbstractCustomCropsBlock { } CropConfig cropConfig = configList.get(0); CropStageConfig stageConfig = cropConfig.stageByID(stageID); + assert stageConfig != null; int point = stageConfig.point(); CustomCropsBlockState state = BuiltInBlockMechanics.CROP.createBlockState(); point(state, point); id(state, cropConfig.id()); world.addBlockState(pos3, state).ifPresent(previous -> { - BukkitCustomCropsPlugin.getInstance().debug( - "Overwrite old data with " + state + - " at location[" + world.worldName() + "," + pos3 + "] which used to be " + previous + BukkitCustomCropsPlugin.getInstance().debug(() -> "Overwrite old data with " + state + + " at location[" + world.worldName() + "," + pos3 + "] which used to be " + previous ); }); return state; } - private void tickCrop(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location) { + private void tickCrop(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location, boolean offline) { CropConfig config = config(state); if (config == null) { BukkitCustomCropsPlugin.getInstance().getPluginLogger().warn("Crop data is removed at location[" + world.worldName() + "," + location + "] because the crop config[" + id(state) + "] has been removed."); @@ -306,7 +306,7 @@ public class CropBlock extends AbstractCustomCropsBlock { } } - Context context = Context.block(state); + Context context = Context.block(state).arg(ContextKeys.OFFLINE, offline); Location bukkitLocation = location.toLocation(bukkitWorld); context.arg(ContextKeys.LOCATION, bukkitLocation); for (DeathCondition deathCondition : config.deathConditions()) { diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/block/CustomCropsBlock.java b/api/src/main/java/net/momirealms/customcrops/api/core/block/CustomCropsBlock.java index efcf9fb..a7a9c25 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/block/CustomCropsBlock.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/block/CustomCropsBlock.java @@ -34,9 +34,9 @@ public interface CustomCropsBlock { CustomCropsBlockState createBlockState(CompoundMap data); - void scheduledTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location); + void scheduledTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location, boolean offlineTick); - void randomTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location); + void randomTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location, boolean offlineTick); void onInteract(WrappedInteractEvent event); diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/block/GreenhouseBlock.java b/api/src/main/java/net/momirealms/customcrops/api/core/block/GreenhouseBlock.java index 4728083..3bb3d8b 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/block/GreenhouseBlock.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/block/GreenhouseBlock.java @@ -40,12 +40,13 @@ public class GreenhouseBlock extends AbstractCustomCropsBlock { } @Override - public void randomTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location) { + public void randomTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location, boolean offlineTick) { //tickGreenhouse(world, location); } @Override - public void scheduledTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location) { + public void scheduledTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location, boolean offlineTick) { + if (offlineTick) return; tickGreenhouse(world, location); } @@ -89,9 +90,8 @@ public class GreenhouseBlock extends AbstractCustomCropsBlock { Pos3 pos3 = Pos3.from(event.location()); CustomCropsWorld world = event.world(); world.addBlockState(pos3, state).ifPresent(previous -> { - BukkitCustomCropsPlugin.getInstance().debug( - "Overwrite old data with " + state + - " at location[" + world.worldName() + "," + pos3 + "] which used to be " + previous + BukkitCustomCropsPlugin.getInstance().debug(() -> "Overwrite old data with " + state + + " at location[" + world.worldName() + "," + pos3 + "] which used to be " + previous ); }); } @@ -108,7 +108,7 @@ public class GreenhouseBlock extends AbstractCustomCropsBlock { } CustomCropsBlockState state = createBlockState(); world.addBlockState(pos3, state).ifPresent(previous -> { - BukkitCustomCropsPlugin.getInstance().debug( + BukkitCustomCropsPlugin.getInstance().debug(() -> "Overwrite old data with " + state + " at pos3[" + world.worldName() + "," + pos3 + "] which used to be " + previous ); diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/block/PotBlock.java b/api/src/main/java/net/momirealms/customcrops/api/core/block/PotBlock.java index 362b22c..0e6652d 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/block/PotBlock.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/block/PotBlock.java @@ -23,11 +23,11 @@ import net.momirealms.customcrops.api.action.ActionManager; import net.momirealms.customcrops.api.context.Context; import net.momirealms.customcrops.api.context.ContextKeys; import net.momirealms.customcrops.api.core.*; +import net.momirealms.customcrops.api.core.mechanic.crop.CropConfig; +import net.momirealms.customcrops.api.core.mechanic.crop.CropStageConfig; import net.momirealms.customcrops.api.core.mechanic.fertilizer.Fertilizer; import net.momirealms.customcrops.api.core.mechanic.fertilizer.FertilizerConfig; import net.momirealms.customcrops.api.core.mechanic.pot.PotConfig; -import net.momirealms.customcrops.api.core.mechanic.crop.CropConfig; -import net.momirealms.customcrops.api.core.mechanic.crop.CropStageConfig; import net.momirealms.customcrops.api.core.world.CustomCropsBlockState; import net.momirealms.customcrops.api.core.world.CustomCropsWorld; import net.momirealms.customcrops.api.core.world.Pos3; @@ -67,16 +67,16 @@ public class PotBlock extends AbstractCustomCropsBlock { } @Override - public void scheduledTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location) { + public void scheduledTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location, boolean offlineTick) { if (!world.setting().randomTickPot() && canTick(state, world.setting().tickPotInterval())) { - tickPot(state, world, location); + tickPot(state, world, location, offlineTick); } } @Override - public void randomTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location) { + public void randomTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location, boolean offlineTick) { if (world.setting().randomTickPot() && canTick(state, world.setting().tickPotInterval())) { - tickPot(state, world, location); + tickPot(state, world, location, offlineTick); } } @@ -211,9 +211,8 @@ public class PotBlock extends AbstractCustomCropsBlock { } world.addBlockState(pos3, state).ifPresent(previous -> { - BukkitCustomCropsPlugin.getInstance().debug( - "Overwrite old data with " + state + - " at location[" + world.worldName() + "," + pos3 + "] which used to be " + previous + BukkitCustomCropsPlugin.getInstance().debug(() -> "Overwrite old data with " + state + + " at location[" + world.worldName() + "," + pos3 + "] which used to be " + previous ); }); ActionManager.trigger(context, config.placeActions()); @@ -324,15 +323,14 @@ public class PotBlock extends AbstractCustomCropsBlock { id(state, potConfig.id()); water(state, potConfig.isWet(blockID) ? 1 : 0); world.addBlockState(pos3, state).ifPresent(previous -> { - BukkitCustomCropsPlugin.getInstance().debug( - "Overwrite old data with " + state + - " at location[" + world.worldName() + "," + pos3 + "] which used to be " + previous + BukkitCustomCropsPlugin.getInstance().debug(() -> "Overwrite old data with " + state + + " at location[" + world.worldName() + "," + pos3 + "] which used to be " + previous ); }); return state; } - private void tickPot(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location) { + private void tickPot(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location, boolean offline) { PotConfig config = config(state); if (config == null) { BukkitCustomCropsPlugin.getInstance().getPluginLogger().warn("Pot data is removed at location[" + world.worldName() + "," + location + "] because the pot config[" + id(state) + "] has been removed."); @@ -411,7 +409,10 @@ public class PotBlock extends AbstractCustomCropsBlock { } ActionManager.trigger(Context.block(state) - .arg(ContextKeys.LOCATION, location.toLocation(bukkitWorld)), config.tickActions()); + .arg(ContextKeys.OFFLINE, offline) + .arg(ContextKeys.LOCATION, location.toLocation(bukkitWorld)), + config.tickActions() + ); } public int water(CustomCropsBlockState state) { diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/block/ScarecrowBlock.java b/api/src/main/java/net/momirealms/customcrops/api/core/block/ScarecrowBlock.java index 1aad9b2..80aea7a 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/block/ScarecrowBlock.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/block/ScarecrowBlock.java @@ -40,12 +40,13 @@ public class ScarecrowBlock extends AbstractCustomCropsBlock { } @Override - public void randomTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location) { + public void randomTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location, boolean offlineTick) { //tickScarecrow(world, location); } @Override - public void scheduledTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location) { + public void scheduledTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location, boolean offlineTick) { + if (offlineTick) return; tickScarecrow(world, location); } @@ -89,9 +90,8 @@ public class ScarecrowBlock extends AbstractCustomCropsBlock { Pos3 pos3 = Pos3.from(event.location()); CustomCropsWorld world = event.world(); world.addBlockState(pos3, state).ifPresent(previous -> { - BukkitCustomCropsPlugin.getInstance().debug( - "Overwrite old data with " + state + - " at location[" + world.worldName() + "," + pos3 + "] which used to be " + previous + BukkitCustomCropsPlugin.getInstance().debug(() -> "Overwrite old data with " + state + + " at location[" + world.worldName() + "," + pos3 + "] which used to be " + previous ); }); } @@ -108,7 +108,7 @@ public class ScarecrowBlock extends AbstractCustomCropsBlock { } CustomCropsBlockState state = createBlockState(); world.addBlockState(pos3, state).ifPresent(previous -> { - BukkitCustomCropsPlugin.getInstance().debug( + BukkitCustomCropsPlugin.getInstance().debug(() -> "Overwrite old data with " + state + " at pos3[" + world.worldName() + "," + pos3 + "] which used to be " + previous ); diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/block/SprinklerBlock.java b/api/src/main/java/net/momirealms/customcrops/api/core/block/SprinklerBlock.java index 29d62d9..86c3989 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/block/SprinklerBlock.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/block/SprinklerBlock.java @@ -57,16 +57,16 @@ public class SprinklerBlock extends AbstractCustomCropsBlock { } @Override - public void randomTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location) { + public void randomTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location, boolean offlineTick) { if (!world.setting().randomTickSprinkler() && canTick(state, world.setting().tickSprinklerInterval())) { - tickSprinkler(state, world, location); + tickSprinkler(state, world, location, offlineTick); } } @Override - public void scheduledTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location) { + public void scheduledTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location, boolean offlineTick) { if (world.setting().randomTickSprinkler() && canTick(state, world.setting().tickSprinklerInterval())) { - tickSprinkler(state, world, location); + tickSprinkler(state, world, location, offlineTick); } } @@ -231,15 +231,14 @@ public class SprinklerBlock extends AbstractCustomCropsBlock { id(state, sprinklerConfig.id()); water(state, blockID.equals(sprinklerConfig.threeDItemWithWater()) ? 1 : 0); world.addBlockState(pos3, state).ifPresent(previous -> { - BukkitCustomCropsPlugin.getInstance().debug( - "Overwrite old data with " + state + - " at location[" + world.worldName() + "," + pos3 + "] which used to be " + previous + BukkitCustomCropsPlugin.getInstance().debug(() -> "Overwrite old data with " + state + + " at location[" + world.worldName() + "," + pos3 + "] which used to be " + previous ); }); return state; } - private void tickSprinkler(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location) { + private void tickSprinkler(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location, boolean offline) { SprinklerConfig config = config(state); if (config == null) { BukkitCustomCropsPlugin.getInstance().getPluginLogger().warn("Sprinkler data is removed at location[" + world.worldName() + "," + location + "] because the sprinkler config[" + id(state) + "] has been removed."); @@ -257,7 +256,7 @@ public class SprinklerBlock extends AbstractCustomCropsBlock { updateState = false; } - Context context = Context.block(state); + Context context = Context.block(state).arg(ContextKeys.OFFLINE, offline); World bukkitWorld = world.bukkitWorld(); Location bukkitLocation = location.toLocation(bukkitWorld); context.arg(ContextKeys.LOCATION, bukkitLocation); diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/item/FertilizerItem.java b/api/src/main/java/net/momirealms/customcrops/api/core/item/FertilizerItem.java index cfd90bb..d267945 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/item/FertilizerItem.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/item/FertilizerItem.java @@ -26,11 +26,11 @@ import net.momirealms.customcrops.api.core.BuiltInItemMechanics; import net.momirealms.customcrops.api.core.InteractionResult; import net.momirealms.customcrops.api.core.Registries; import net.momirealms.customcrops.api.core.block.CropBlock; -import net.momirealms.customcrops.api.core.mechanic.crop.CropConfig; import net.momirealms.customcrops.api.core.block.PotBlock; -import net.momirealms.customcrops.api.core.mechanic.pot.PotConfig; +import net.momirealms.customcrops.api.core.mechanic.crop.CropConfig; import net.momirealms.customcrops.api.core.mechanic.fertilizer.Fertilizer; import net.momirealms.customcrops.api.core.mechanic.fertilizer.FertilizerConfig; +import net.momirealms.customcrops.api.core.mechanic.pot.PotConfig; import net.momirealms.customcrops.api.core.world.CustomCropsBlockState; import net.momirealms.customcrops.api.core.world.CustomCropsWorld; import net.momirealms.customcrops.api.core.world.Pos3; diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/item/SeedItem.java b/api/src/main/java/net/momirealms/customcrops/api/core/item/SeedItem.java index a4dc569..4d780b0 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/item/SeedItem.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/item/SeedItem.java @@ -117,9 +117,8 @@ public class SeedItem extends AbstractCustomCropsItem { BukkitCustomCropsPlugin.getInstance().getItemManager().place(LocationUtils.toSurfaceCenterLocation(seedLocation), form, stageID, cropConfig.rotation() ? FurnitureRotation.random() : FurnitureRotation.NONE); cropBlock.point(state, point); world.addBlockState(pos3, state).ifPresent(previous -> { - BukkitCustomCropsPlugin.getInstance().debug( - "Overwrite old data with " + state + - " at location[" + world.worldName() + "," + pos3 + "] which used to be " + previous + BukkitCustomCropsPlugin.getInstance().debug(() -> "Overwrite old data with " + state + + " at location[" + world.worldName() + "," + pos3 + "] which used to be " + previous ); }); diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/item/SprinklerItem.java b/api/src/main/java/net/momirealms/customcrops/api/core/item/SprinklerItem.java index 8ed8fac..c78c334 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/item/SprinklerItem.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/item/SprinklerItem.java @@ -110,9 +110,8 @@ public class SprinklerItem extends AbstractCustomCropsItem { // place the sprinkler BukkitCustomCropsPlugin.getInstance().getItemManager().place(LocationUtils.toSurfaceCenterLocation(targetLocation), config.existenceForm(), config.threeDItem(), FurnitureRotation.NONE); world.addBlockState(pos3, state).ifPresent(previous -> { - BukkitCustomCropsPlugin.getInstance().debug( - "Overwrite old data with " + state + - " at location[" + world.worldName() + "," + pos3 + "] which used to be " + previous + BukkitCustomCropsPlugin.getInstance().debug(() -> "Overwrite old data with " + state + + " at location[" + world.worldName() + "," + pos3 + "] which used to be " + previous ); }); ActionManager.trigger(context, config.placeActions()); diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/item/WateringCanItem.java b/api/src/main/java/net/momirealms/customcrops/api/core/item/WateringCanItem.java index 08c1a21..be7f5fe 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/item/WateringCanItem.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/item/WateringCanItem.java @@ -24,9 +24,10 @@ import net.momirealms.customcrops.api.action.ActionManager; import net.momirealms.customcrops.api.context.Context; import net.momirealms.customcrops.api.context.ContextKeys; import net.momirealms.customcrops.api.core.*; -import net.momirealms.customcrops.api.core.block.*; -import net.momirealms.customcrops.api.core.mechanic.pot.PotConfig; +import net.momirealms.customcrops.api.core.block.PotBlock; +import net.momirealms.customcrops.api.core.block.SprinklerBlock; import net.momirealms.customcrops.api.core.mechanic.crop.CropConfig; +import net.momirealms.customcrops.api.core.mechanic.pot.PotConfig; import net.momirealms.customcrops.api.core.mechanic.sprinkler.SprinklerConfig; import net.momirealms.customcrops.api.core.mechanic.wateringcan.WateringCanConfig; import net.momirealms.customcrops.api.core.world.CustomCropsBlockState; diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/world/CustomCropsChunk.java b/api/src/main/java/net/momirealms/customcrops/api/core/world/CustomCropsChunk.java index a84c7f4..ca1f44c 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/world/CustomCropsChunk.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/world/CustomCropsChunk.java @@ -107,14 +107,14 @@ public interface CustomCropsChunk { * * @return The unloaded time in seconds. */ - int unloadedSeconds(); + int lazySeconds(); /** * Sets the time in seconds since the chunk was unloaded. * - * @param unloadedSeconds The unloaded time to set. + * @param lazySeconds The unloaded time to set. */ - void unloadedSeconds(int unloadedSeconds); + void lazySeconds(int lazySeconds); /** * Gets the last time the chunk was loaded. @@ -126,7 +126,7 @@ public interface CustomCropsChunk { /** * Updates the last loaded time to the current time. */ - void updateLastLoadedTime(); + void updateLastUnloadTime(); /** * Gets the time in milliseconds since the chunk was loaded. @@ -203,11 +203,6 @@ public interface CustomCropsChunk { */ Optional removeSection(int sectionID); - /** - * Resets the unloaded time counter to zero. - */ - void resetUnloadedSeconds(); - /** * Checks if the chunk can be pruned (removed from memory or storage). * @@ -222,6 +217,11 @@ public interface CustomCropsChunk { */ boolean isOfflineTaskNotified(); + /** + * notify offline tasks + */ + void notifyOfflineTask(); + /** * Gets the queue of delayed tick tasks for this chunk. * diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/world/CustomCropsChunkImpl.java b/api/src/main/java/net/momirealms/customcrops/api/core/world/CustomCropsChunkImpl.java index c0d79ae..d7326df 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/world/CustomCropsChunkImpl.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/world/CustomCropsChunkImpl.java @@ -32,30 +32,31 @@ public class CustomCropsChunkImpl implements CustomCropsChunk { private final ConcurrentHashMap loadedSections; private final PriorityQueue queue; private final Set tickedBlocks; - private long lastLoadedTime; + private long lastUnloadTime; private int loadedSeconds; - private int unloadedSeconds; + private int lazySeconds; private boolean notified; private boolean isLoaded; private boolean forceLoad; + // new chunk protected CustomCropsChunkImpl(CustomCropsWorld world, ChunkPos chunkPos) { this.world = world; this.chunkPos = chunkPos; this.loadedSections = new ConcurrentHashMap<>(16); this.queue = new PriorityQueue<>(); - this.unloadedSeconds = 0; + this.lazySeconds = 0; this.tickedBlocks = Collections.synchronizedSet(new HashSet<>()); - this.updateLastLoadedTime(); this.notified = true; this.isLoaded = false; + this.updateLastUnloadTime(); } protected CustomCropsChunkImpl( CustomCropsWorld world, ChunkPos chunkPos, int loadedSeconds, - long lastLoadedTime, + long lastUnloadTime, ConcurrentHashMap loadedSections, PriorityQueue queue, HashSet tickedBlocks @@ -63,11 +64,13 @@ public class CustomCropsChunkImpl implements CustomCropsChunk { this.world = world; this.chunkPos = chunkPos; this.loadedSections = loadedSections; - this.lastLoadedTime = lastLoadedTime; + this.lastUnloadTime = lastUnloadTime; this.loadedSeconds = loadedSeconds; this.queue = queue; - this.unloadedSeconds = 0; + this.lazySeconds = 0; this.tickedBlocks = Collections.synchronizedSet(tickedBlocks); + this.notified = false; + this.isLoaded = false; } @Override @@ -85,6 +88,7 @@ public class CustomCropsChunkImpl implements CustomCropsChunk { if (!isLoaded()) { if (((CustomCropsWorldImpl) world).loadChunk(this)) { this.isLoaded = true; + this.lazySeconds = 0; } if (loadBukkitChunk && !this.world.bukkitWorld().isChunkLoaded(chunkPos.x(), chunkPos.z())) { this.world.bukkitWorld().getChunkAt(chunkPos.x(), chunkPos.z()); @@ -97,6 +101,8 @@ public class CustomCropsChunkImpl implements CustomCropsChunk { if (isLoaded() && !isForceLoaded()) { if (((CustomCropsWorldImpl) world).unloadChunk(this, lazy)) { this.isLoaded = false; + this.notified = false; + this.lazySeconds = 0; } } } @@ -140,8 +146,8 @@ public class CustomCropsChunkImpl implements CustomCropsChunk { this.queue.clear(); this.arrangeTasks(interval); } - scheduledTick(); - randomTick(setting.randomTickSpeed()); + scheduledTick(false); + randomTick(setting.randomTickSpeed(), false); } private void arrangeTasks(int unit) { @@ -157,7 +163,7 @@ public class CustomCropsChunkImpl implements CustomCropsChunk { } } - private void scheduledTick() { + private void scheduledTick(boolean offline) { while (!queue.isEmpty() && queue.peek().getTime() <= loadedSeconds) { DelayedTickTask task = queue.poll(); if (task != null) { @@ -165,13 +171,13 @@ public class CustomCropsChunkImpl implements CustomCropsChunk { CustomCropsSection section = loadedSections.get(pos.sectionID()); if (section != null) { Optional block = section.getBlockState(pos); - block.ifPresent(state -> state.type().scheduledTick(state, world, pos.toPos3(chunkPos))); + block.ifPresent(state -> state.type().scheduledTick(state, world, pos.toPos3(chunkPos), offline)); } } } } - private void randomTick(int randomTickSpeed) { + private void randomTick(int randomTickSpeed, boolean offline) { ThreadLocalRandom random = ThreadLocalRandom.current(); for (CustomCropsSection section : loadedSections.values()) { int sectionID = section.getSectionID(); @@ -182,34 +188,34 @@ public class CustomCropsChunkImpl implements CustomCropsChunk { int z = random.nextInt(16); BlockPos pos = new BlockPos(x,y,z); Optional block = section.getBlockState(pos); - block.ifPresent(state -> state.type().randomTick(state, world, pos.toPos3(chunkPos))); + block.ifPresent(state -> state.type().randomTick(state, world, pos.toPos3(chunkPos), offline)); } } } @Override - public int unloadedSeconds() { - return unloadedSeconds; + public int lazySeconds() { + return lazySeconds; } @Override - public void unloadedSeconds(int unloadedSeconds) { - this.unloadedSeconds = unloadedSeconds; + public void lazySeconds(int lazySeconds) { + this.lazySeconds = lazySeconds; } @Override public long lastLoadedTime() { - return lastLoadedTime; + return lastUnloadTime; } @Override - public void updateLastLoadedTime() { - this.lastLoadedTime = System.currentTimeMillis(); + public void updateLastUnloadTime() { + this.lastUnloadTime = System.currentTimeMillis(); } @Override public int loadedMilliSeconds() { - return (int) (System.currentTimeMillis() - lastLoadedTime); + return (int) (System.currentTimeMillis() - lastUnloadTime); } @NotNull @@ -266,12 +272,6 @@ public class CustomCropsChunkImpl implements CustomCropsChunk { return Optional.ofNullable(loadedSections.remove(sectionID)); } - @Override - public void resetUnloadedSeconds() { - this.unloadedSeconds = 0; - this.notified = false; - } - @Override public boolean canPrune() { return loadedSections.isEmpty(); @@ -282,6 +282,36 @@ public class CustomCropsChunkImpl implements CustomCropsChunk { return notified; } + @Override + public void notifyOfflineTask() { + if (isOfflineTaskNotified()) return; + this.notified = true; + long current = System.currentTimeMillis(); + int offlineTimeInSeconds = (int) (current - lastLoadedTime()) / 1000; + WorldSetting setting = world.setting(); + offlineTimeInSeconds = Math.min(offlineTimeInSeconds, setting.maxOfflineTime()); + int minTickUnit = setting.minTickUnit(); + int randomTickSpeed = setting.randomTickSpeed(); + int threshold = setting.maxLoadingTime(); + int i = 0; + long time1 = System.currentTimeMillis(); + while (i < offlineTimeInSeconds) { + this.loadedSeconds++; + if (this.loadedSeconds >= minTickUnit) { + this.loadedSeconds = 0; + this.tickedBlocks.clear(); + this.queue.clear(); + this.arrangeTasks(minTickUnit); + } + scheduledTick(true); + randomTick(randomTickSpeed, true); + i++; + if (System.currentTimeMillis() - time1 > threshold) { + break; + } + } + } + @Override public PriorityQueue tickTaskQueue() { return queue; diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/world/CustomCropsWorldImpl.java b/api/src/main/java/net/momirealms/customcrops/api/core/world/CustomCropsWorldImpl.java index ca65d0e..16d7859 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/world/CustomCropsWorldImpl.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/world/CustomCropsWorldImpl.java @@ -272,11 +272,11 @@ public class CustomCropsWorldImpl implements CustomCropsWorld { ArrayList chunksToSave = new ArrayList<>(); for (Map.Entry lazyEntry : this.lazyChunks.entrySet()) { CustomCropsChunk chunk = lazyEntry.getValue(); - int sec = chunk.unloadedSeconds() + 1; + int sec = chunk.lazySeconds() + 1; if (sec >= 30) { chunksToSave.add(chunk); } else { - chunk.unloadedSeconds(sec); + chunk.lazySeconds(sec); } } for (CustomCropsChunk chunk : chunksToSave) { @@ -309,9 +309,6 @@ public class CustomCropsWorldImpl implements CustomCropsWorld { this.setting = setting; } - /* - * Chunks - */ @Nullable public CustomCropsChunk removeLazyChunk(ChunkPos chunkPos) { return this.lazyChunks.remove(chunkPos); @@ -355,7 +352,7 @@ public class CustomCropsWorldImpl implements CustomCropsWorld { return false; } this.loadedChunks.remove(chunk.chunkPos()); - chunk.updateLastLoadedTime(); + chunk.updateLastUnloadTime(); if (lazy) { this.lazyChunks.put(pos, chunk); } else { @@ -368,7 +365,7 @@ public class CustomCropsWorldImpl implements CustomCropsWorld { public boolean unloadChunk(ChunkPos pos, boolean lazy) { CustomCropsChunk removed = this.loadedChunks.remove(pos); if (removed != null) { - removed.updateLastLoadedTime(); + removed.updateLastUnloadTime(); if (lazy) { this.lazyChunks.put(pos, removed); } else { diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/world/WorldManager.java b/api/src/main/java/net/momirealms/customcrops/api/core/world/WorldManager.java index 8085cd9..f3ab9d0 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/world/WorldManager.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/world/WorldManager.java @@ -23,7 +23,6 @@ import net.momirealms.customcrops.common.plugin.feature.Reloadable; import org.bukkit.World; import java.util.Optional; -import java.util.Set; import java.util.TreeSet; /** diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/world/WorldSetting.java b/api/src/main/java/net/momirealms/customcrops/api/core/world/WorldSetting.java index cf87fd1..96e337b 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/world/WorldSetting.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/world/WorldSetting.java @@ -37,6 +37,7 @@ public class WorldSetting implements Cloneable { private final int sprinklerPerChunk; private final int randomTickSpeed; private final int maxOfflineTime; + private final int maxLoadingTime; private final boolean tickCropRandomly; private final boolean tickPotRandomly; private final boolean tickSprinklerRandomly; @@ -54,6 +55,7 @@ public class WorldSetting implements Cloneable { * @param tickSprinklerInterval The interval for ticking sprinklers. * @param offlineTick Whether offline ticking is enabled. * @param maxOfflineTime The maximum offline time allowed. + * @param maxLoadingTime The maximum time allowed to load. * @param enableSeason Whether seasons are enabled. * @param autoSeasonChange Whether season change is automatic. * @param seasonDuration The duration of each season. @@ -73,6 +75,7 @@ public class WorldSetting implements Cloneable { int tickSprinklerInterval, boolean offlineTick, int maxOfflineTime, + int maxLoadingTime, boolean enableSeason, boolean autoSeasonChange, int seasonDuration, @@ -88,6 +91,7 @@ public class WorldSetting implements Cloneable { this.tickSprinklerInterval = tickSprinklerInterval; this.offlineTick = offlineTick; this.maxOfflineTime = maxOfflineTime; + this.maxLoadingTime = maxLoadingTime; this.enableSeason = enableSeason; this.autoSeasonChange = autoSeasonChange; this.seasonDuration = seasonDuration; @@ -133,6 +137,7 @@ public class WorldSetting implements Cloneable { int tickSprinklerInterval, boolean offlineGrow, int maxOfflineTime, + int maxLoadingTime, boolean enableSeason, boolean autoSeasonChange, int seasonDuration, @@ -152,6 +157,7 @@ public class WorldSetting implements Cloneable { tickSprinklerInterval, offlineGrow, maxOfflineTime, + maxLoadingTime, enableSeason, autoSeasonChange, seasonDuration, @@ -216,6 +222,15 @@ public class WorldSetting implements Cloneable { return offlineTick; } + /** + * Gets the max time allowed to load a chunk + * + * @return The max loading time + */ + public int maxLoadingTime() { + return maxLoadingTime; + } + /** * Checks if seasons are enabled. * diff --git a/api/src/main/java/net/momirealms/customcrops/api/event/FertilizerUseEvent.java b/api/src/main/java/net/momirealms/customcrops/api/event/FertilizerUseEvent.java index 32212e0..98a70c2 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/event/FertilizerUseEvent.java +++ b/api/src/main/java/net/momirealms/customcrops/api/event/FertilizerUseEvent.java @@ -17,8 +17,8 @@ package net.momirealms.customcrops.api.event; -import net.momirealms.customcrops.api.core.mechanic.pot.PotConfig; import net.momirealms.customcrops.api.core.mechanic.fertilizer.Fertilizer; +import net.momirealms.customcrops.api.core.mechanic.pot.PotConfig; import net.momirealms.customcrops.api.core.world.CustomCropsBlockState; import org.bukkit.Location; import org.bukkit.entity.Player; diff --git a/api/src/main/java/net/momirealms/customcrops/api/requirement/AbstractRequirementManager.java b/api/src/main/java/net/momirealms/customcrops/api/requirement/AbstractRequirementManager.java index d52a8d3..1c19b18 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/requirement/AbstractRequirementManager.java +++ b/api/src/main/java/net/momirealms/customcrops/api/requirement/AbstractRequirementManager.java @@ -23,10 +23,10 @@ import net.momirealms.customcrops.api.action.Action; import net.momirealms.customcrops.api.action.ActionManager; import net.momirealms.customcrops.api.context.ContextKeys; import net.momirealms.customcrops.api.core.ConfigManager; -import net.momirealms.customcrops.api.core.mechanic.crop.CrowAttack; import net.momirealms.customcrops.api.core.block.GreenhouseBlock; import net.momirealms.customcrops.api.core.block.PotBlock; import net.momirealms.customcrops.api.core.block.ScarecrowBlock; +import net.momirealms.customcrops.api.core.mechanic.crop.CrowAttack; import net.momirealms.customcrops.api.core.mechanic.fertilizer.Fertilizer; import net.momirealms.customcrops.api.core.mechanic.fertilizer.FertilizerConfig; import net.momirealms.customcrops.api.core.world.CustomCropsBlockState; diff --git a/compatibility-asp-r1/src/main/java/net/momirealms/customcrops/bukkit/integration/adaptor/asp_r1/SlimeWorldAdaptorR1.java b/compatibility-asp-r1/src/main/java/net/momirealms/customcrops/bukkit/integration/adaptor/asp_r1/SlimeWorldAdaptorR1.java index 13b348c..e329a76 100644 --- a/compatibility-asp-r1/src/main/java/net/momirealms/customcrops/bukkit/integration/adaptor/asp_r1/SlimeWorldAdaptorR1.java +++ b/compatibility-asp-r1/src/main/java/net/momirealms/customcrops/bukkit/integration/adaptor/asp_r1/SlimeWorldAdaptorR1.java @@ -32,7 +32,10 @@ import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.Nullable; import java.lang.reflect.Method; -import java.util.*; +import java.util.HashSet; +import java.util.Map; +import java.util.Optional; +import java.util.PriorityQueue; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; diff --git a/gradle.properties b/gradle.properties index b2e4607..62c1f7d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,7 +15,7 @@ asm_commons_version=9.7 jar_relocator_version=1.7 adventure_bundle_version=4.17.0 adventure_platform_version=4.3.4 -sparrow_heart_version=0.40 +sparrow_heart_version=0.42 cloud_core_version=2.0.0-rc.2 cloud_services_version=2.0.0-rc.2 cloud_brigadier_version=2.0.0-beta.9 diff --git a/plugin/src/main/java/net/momirealms/customcrops/bukkit/BukkitCustomCropsPluginImpl.java b/plugin/src/main/java/net/momirealms/customcrops/bukkit/BukkitCustomCropsPluginImpl.java index 01f08e2..549af95 100644 --- a/plugin/src/main/java/net/momirealms/customcrops/bukkit/BukkitCustomCropsPluginImpl.java +++ b/plugin/src/main/java/net/momirealms/customcrops/bukkit/BukkitCustomCropsPluginImpl.java @@ -21,7 +21,10 @@ import net.momirealms.customcrops.api.BukkitCustomCropsPlugin; import net.momirealms.customcrops.api.core.ConfigManager; import net.momirealms.customcrops.api.core.SimpleRegistryAccess; import net.momirealms.customcrops.api.core.block.*; -import net.momirealms.customcrops.api.core.item.*; +import net.momirealms.customcrops.api.core.item.FertilizerItem; +import net.momirealms.customcrops.api.core.item.SeedItem; +import net.momirealms.customcrops.api.core.item.SprinklerItem; +import net.momirealms.customcrops.api.core.item.WateringCanItem; import net.momirealms.customcrops.api.core.mechanic.fertilizer.FertilizerType; import net.momirealms.customcrops.api.core.world.CustomCropsBlockState; import net.momirealms.customcrops.api.event.CustomCropsReloadEvent; diff --git a/plugin/src/main/java/net/momirealms/customcrops/bukkit/action/PlayerActionManager.java b/plugin/src/main/java/net/momirealms/customcrops/bukkit/action/PlayerActionManager.java index dfb2865..1e39247 100644 --- a/plugin/src/main/java/net/momirealms/customcrops/bukkit/action/PlayerActionManager.java +++ b/plugin/src/main/java/net/momirealms/customcrops/bukkit/action/PlayerActionManager.java @@ -472,8 +472,8 @@ public class PlayerActionManager extends AbstractActionManager { Optional> optionalWorld = plugin.getWorldManager().getWorld(location.getWorld()); optionalWorld.ifPresent(world -> world.getChunk(pos3.toChunkPos()).flatMap(chunk -> chunk.getBlockState(pos3)).ifPresent(state -> { CustomCropsBlock customCropsBlock = state.type(); - customCropsBlock.randomTick(state, world, pos3); - customCropsBlock.scheduledTick(state, world, pos3); + customCropsBlock.randomTick(state, world, pos3, false); + customCropsBlock.scheduledTick(state, world, pos3, false); if (customCropsBlock instanceof SprinklerBlock sprinklerBlock) { int water = sprinklerBlock.water(state); SprinklerConfig config = sprinklerBlock.config(state); @@ -490,8 +490,8 @@ public class PlayerActionManager extends AbstractActionManager { Optional> optionalWorld = plugin.getWorldManager().getWorld(location.getWorld()); optionalWorld.ifPresent(world -> world.getChunk(pos3.toChunkPos()).flatMap(chunk -> chunk.getBlockState(pos3)).ifPresent(state -> { CustomCropsBlock customCropsBlock = state.type(); - customCropsBlock.randomTick(state, world, pos3); - customCropsBlock.scheduledTick(state, world, pos3); + customCropsBlock.randomTick(state, world, pos3, false); + customCropsBlock.scheduledTick(state, world, pos3, false); })); }, "tick"); } diff --git a/plugin/src/main/java/net/momirealms/customcrops/bukkit/command/feature/ForceTickCommand.java b/plugin/src/main/java/net/momirealms/customcrops/bukkit/command/feature/ForceTickCommand.java index 0355b92..6e43ac5 100644 --- a/plugin/src/main/java/net/momirealms/customcrops/bukkit/command/feature/ForceTickCommand.java +++ b/plugin/src/main/java/net/momirealms/customcrops/bukkit/command/feature/ForceTickCommand.java @@ -109,11 +109,11 @@ public class ForceTickCommand extends BukkitCommandFeature { private enum Mode { - RANDOM_TICK(CustomCropsBlock::randomTick), - SCHEDULED_TICK(CustomCropsBlock::scheduledTick), + RANDOM_TICK((customCropsBlock, state, world, location) -> customCropsBlock.randomTick(state, world, location, false)), + SCHEDULED_TICK((customCropsBlock, state, world, location) -> customCropsBlock.scheduledTick(state, world, location, false)), ALL((b, s, w, p) -> { - b.randomTick(s, w, p); - b.scheduledTick(s, w, p); + b.randomTick(s, w, p, false); + b.scheduledTick(s, w, p, false); }); private final QuadConsumer, Pos3> consumer; diff --git a/plugin/src/main/java/net/momirealms/customcrops/bukkit/config/BukkitConfigManager.java b/plugin/src/main/java/net/momirealms/customcrops/bukkit/config/BukkitConfigManager.java index e77a248..461eadc 100644 --- a/plugin/src/main/java/net/momirealms/customcrops/bukkit/config/BukkitConfigManager.java +++ b/plugin/src/main/java/net/momirealms/customcrops/bukkit/config/BukkitConfigManager.java @@ -30,13 +30,13 @@ import dev.dejvokep.boostedyaml.settings.updater.UpdaterSettings; import dev.dejvokep.boostedyaml.utils.format.NodeRole; import net.momirealms.customcrops.api.BukkitCustomCropsPlugin; import net.momirealms.customcrops.api.core.*; -import net.momirealms.customcrops.api.core.mechanic.fertilizer.FertilizerConfig; -import net.momirealms.customcrops.api.core.mechanic.wateringcan.WateringCanConfig; -import net.momirealms.customcrops.api.core.mechanic.crop.DeathCondition; -import net.momirealms.customcrops.api.core.mechanic.pot.PotConfig; import net.momirealms.customcrops.api.core.mechanic.crop.CropConfig; import net.momirealms.customcrops.api.core.mechanic.crop.CropStageConfig; +import net.momirealms.customcrops.api.core.mechanic.crop.DeathCondition; +import net.momirealms.customcrops.api.core.mechanic.fertilizer.FertilizerConfig; +import net.momirealms.customcrops.api.core.mechanic.pot.PotConfig; import net.momirealms.customcrops.api.core.mechanic.sprinkler.SprinklerConfig; +import net.momirealms.customcrops.api.core.mechanic.wateringcan.WateringCanConfig; import net.momirealms.customcrops.common.helper.AdventureHelper; import net.momirealms.customcrops.common.locale.TranslationManager; import net.momirealms.customcrops.common.plugin.CustomCropsProperties; diff --git a/plugin/src/main/java/net/momirealms/customcrops/bukkit/config/ConfigType.java b/plugin/src/main/java/net/momirealms/customcrops/bukkit/config/ConfigType.java index baa974e..7cb6144 100644 --- a/plugin/src/main/java/net/momirealms/customcrops/bukkit/config/ConfigType.java +++ b/plugin/src/main/java/net/momirealms/customcrops/bukkit/config/ConfigType.java @@ -27,10 +27,10 @@ import net.momirealms.customcrops.api.core.ExistenceForm; import net.momirealms.customcrops.api.core.Registries; import net.momirealms.customcrops.api.core.mechanic.crop.CropConfig; import net.momirealms.customcrops.api.core.mechanic.crop.CropStageConfig; -import net.momirealms.customcrops.api.core.mechanic.pot.PotConfig; -import net.momirealms.customcrops.api.core.mechanic.sprinkler.SprinklerConfig; import net.momirealms.customcrops.api.core.mechanic.fertilizer.FertilizerConfig; import net.momirealms.customcrops.api.core.mechanic.fertilizer.FertilizerType; +import net.momirealms.customcrops.api.core.mechanic.pot.PotConfig; +import net.momirealms.customcrops.api.core.mechanic.sprinkler.SprinklerConfig; import net.momirealms.customcrops.api.core.mechanic.wateringcan.WateringCanConfig; import net.momirealms.customcrops.api.core.world.CustomCropsBlockState; import net.momirealms.customcrops.api.misc.value.TextValue; diff --git a/plugin/src/main/java/net/momirealms/customcrops/bukkit/item/BukkitItemManager.java b/plugin/src/main/java/net/momirealms/customcrops/bukkit/item/BukkitItemManager.java index 385b171..995e5d9 100644 --- a/plugin/src/main/java/net/momirealms/customcrops/bukkit/item/BukkitItemManager.java +++ b/plugin/src/main/java/net/momirealms/customcrops/bukkit/item/BukkitItemManager.java @@ -512,7 +512,7 @@ public class BukkitItemManager extends AbstractItemManager { if (anyFurnitureID != null) { if (!customCropsBlockState.type().isBlockInstance(anyFurnitureID)) { world.removeBlockState(pos3); - plugin.debug("[" + location.getWorld().getName() + "] Removed inconsistent block data at " + pos3 + " which used to be " + customCropsBlockState); + plugin.debug(() -> "[" + location.getWorld().getName() + "] Removed inconsistent block data at " + pos3 + " which used to be " + customCropsBlockState); } else { event.setCancelled(true); return; @@ -521,7 +521,7 @@ public class BukkitItemManager extends AbstractItemManager { String anyBlockID = blockID(location); if (!customCropsBlockState.type().isBlockInstance(anyBlockID)) { world.removeBlockState(pos3); - plugin.debug("[" + location.getWorld().getName() + "] Removed inconsistent block data at " + pos3 + " which used to be " + customCropsBlockState); + plugin.debug(() -> "[" + location.getWorld().getName() + "] Removed inconsistent block data at " + pos3 + " which used to be " + customCropsBlockState); } else { event.setCancelled(true); return; diff --git a/plugin/src/main/java/net/momirealms/customcrops/bukkit/world/BukkitWorldManager.java b/plugin/src/main/java/net/momirealms/customcrops/bukkit/world/BukkitWorldManager.java index df7364a..0290501 100644 --- a/plugin/src/main/java/net/momirealms/customcrops/bukkit/world/BukkitWorldManager.java +++ b/plugin/src/main/java/net/momirealms/customcrops/bukkit/world/BukkitWorldManager.java @@ -194,7 +194,9 @@ public class BukkitWorldManager implements WorldManager, Listener { adaptedWorld.setTicking(true); this.worlds.put(world.getName(), adaptedWorld); for (Chunk chunk : world.getLoadedChunks()) { - loadLoadedChunk(adaptedWorld, ChunkPos.fromBukkitChunk(chunk)); + ChunkPos pos = ChunkPos.fromBukkitChunk(chunk); + loadLoadedChunk(adaptedWorld, pos); + notifyOfflineUpdates(adaptedWorld, pos); } return adaptedWorld; } @@ -204,7 +206,13 @@ public class BukkitWorldManager implements WorldManager, Listener { if (world.isChunkLoaded(pos)) return; Optional customChunk = world.getChunk(pos); // don't load bukkit chunk again since it has been loaded - customChunk.ifPresent(customCropsChunk -> customCropsChunk.load(false)); + customChunk.ifPresent(customCropsChunk -> { + customCropsChunk.load(false); + }); + } + + public void notifyOfflineUpdates(CustomCropsWorld world, ChunkPos pos) { + world.getChunk(pos).ifPresent(CustomCropsChunk::notifyOfflineTask); } @Override @@ -251,12 +259,24 @@ public class BukkitWorldManager implements WorldManager, Listener { public void onChunkLoad(ChunkLoadEvent event) { final Chunk chunk = event.getChunk(); final World world = event.getWorld(); - this.getWorld(world).ifPresent(customWorld -> loadLoadedChunk(customWorld, ChunkPos.fromBukkitChunk(chunk))); + this.getWorld(world).ifPresent(customWorld -> { + ChunkPos pos = ChunkPos.fromBukkitChunk(chunk); + loadLoadedChunk(customWorld, pos); + if (chunk.isEntitiesLoaded() && customWorld.setting().offlineTick()) { + notifyOfflineUpdates(customWorld, pos); + } + }); } @EventHandler public void onEntitiesLoad(EntitiesLoadEvent event) { - + final Chunk chunk = event.getChunk(); + final World world = event.getWorld(); + this.getWorld(world).ifPresent(customWorld -> { + if (customWorld.setting().offlineTick()) { + notifyOfflineUpdates(customWorld, ChunkPos.fromBukkitChunk(chunk)); + } + }); } public boolean isMechanicEnabled(World world) { @@ -329,6 +349,7 @@ public class BukkitWorldManager implements WorldManager, Listener { section.getInt("sprinkler.tick-interval", 2), section.getBoolean("offline-tick.enable", false), section.getInt("offline-tick.max-offline-seconds", 1200), + section.getInt("offline-tick.max-loading-time", 100), section.getBoolean("season.enable", false), section.getBoolean("season.auto-alternation", false), section.getInt("season.duration", 28), diff --git a/plugin/src/main/resources/config.yml b/plugin/src/main/resources/config.yml index 8e412eb..71601ee 100644 --- a/plugin/src/main/resources/config.yml +++ b/plugin/src/main/resources/config.yml @@ -52,6 +52,11 @@ worlds: # as it may cause chunks that have been unloaded for a long time # taking long to load max-offline-seconds: 1200 + # The max time used in loading this chunk + # Sometimes a chunk might contain a lot of data and has not been loaded for a long time, + # thus taking a long time loading and causing unexpected issues + # This setting allows the plugin to forcefully interrupt the tick process if the time consumed has exceeded a certain value + max-loading-time: 100 #ms # Settings for crops crop: # [RANDOM_TICK]