9
0
mirror of https://github.com/Xiao-MoMi/Custom-Crops.git synced 2025-12-26 10:29:10 +00:00

untested offline growth

This commit is contained in:
XiaoMoMi
2024-04-03 18:53:51 +08:00
parent 3bde4340b2
commit 024cb479d0
43 changed files with 257 additions and 153 deletions

View File

@@ -38,7 +38,7 @@ import net.momirealms.customcrops.mechanic.misc.migrator.Migration;
import net.momirealms.customcrops.mechanic.requirement.RequirementManagerImpl;
import net.momirealms.customcrops.mechanic.world.WorldManagerImpl;
import net.momirealms.customcrops.scheduler.SchedulerImpl;
import net.momirealms.customcrops.utils.EventUtils;
import net.momirealms.customcrops.util.EventUtils;
import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit;

View File

@@ -113,7 +113,7 @@ public class CommandManager implements Initable {
for (CustomCropsSection section : chunk.getSections()) {
for (CustomCropsBlock block : section.getBlocks()) {
if (block.getType() == itemType) {
block.tick(1);
block.tick(1, false);
}
}
}

View File

@@ -26,7 +26,7 @@ import dev.dejvokep.boostedyaml.settings.updater.UpdaterSettings;
import net.momirealms.customcrops.api.CustomCropsPlugin;
import net.momirealms.customcrops.api.manager.ConfigManager;
import net.momirealms.customcrops.api.util.LogUtils;
import net.momirealms.customcrops.utils.ConfigUtils;
import net.momirealms.customcrops.util.ConfigUtils;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.configuration.ConfigurationSection;

View File

@@ -23,7 +23,7 @@ import net.momirealms.customcrops.api.common.Reloadable;
import net.momirealms.customcrops.api.common.Tuple;
import net.momirealms.customcrops.api.manager.VersionManager;
import net.momirealms.customcrops.api.scheduler.CancellableTask;
import net.momirealms.customcrops.utils.FakeEntityUtils;
import net.momirealms.customcrops.util.FakeEntityUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.EntityType;

View File

@@ -22,7 +22,7 @@ import net.momirealms.customcrops.api.common.Reloadable;
import net.momirealms.customcrops.api.manager.ConfigManager;
import net.momirealms.customcrops.api.manager.MessageManager;
import net.momirealms.customcrops.api.mechanic.world.season.Season;
import net.momirealms.customcrops.utils.ConfigUtils;
import net.momirealms.customcrops.util.ConfigUtils;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;

View File

@@ -21,7 +21,7 @@ import net.momirealms.customcrops.api.CustomCropsPlugin;
import net.momirealms.customcrops.api.manager.PlaceholderManager;
import net.momirealms.customcrops.compatibility.papi.CCPapi;
import net.momirealms.customcrops.compatibility.papi.ParseUtils;
import net.momirealms.customcrops.utils.ConfigUtils;
import net.momirealms.customcrops.util.ConfigUtils;
import org.bukkit.Bukkit;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;

View File

@@ -56,10 +56,10 @@ import net.momirealms.customcrops.manager.PacketManager;
import net.momirealms.customcrops.mechanic.item.impl.VariationCrop;
import net.momirealms.customcrops.mechanic.misc.TempFakeItem;
import net.momirealms.customcrops.mechanic.world.block.MemoryCrop;
import net.momirealms.customcrops.utils.ClassUtils;
import net.momirealms.customcrops.utils.ConfigUtils;
import net.momirealms.customcrops.utils.EventUtils;
import net.momirealms.customcrops.utils.ItemUtils;
import net.momirealms.customcrops.util.ClassUtils;
import net.momirealms.customcrops.util.ConfigUtils;
import net.momirealms.customcrops.util.EventUtils;
import net.momirealms.customcrops.util.ItemUtils;
import org.bukkit.*;
import org.bukkit.block.BlockFace;
import org.bukkit.configuration.ConfigurationSection;
@@ -220,6 +220,7 @@ public class ActionManagerImpl implements ActionManager {
boolean onlyShowToOne = !section.getBoolean("visible-to-all", false);
return condition -> {
if (Math.random() > chance) return;
if (condition.getArg("{offline}") != null) return;
Location location = condition.getLocation().clone().add(x,y,z);
SimpleLocation simpleLocation = SimpleLocation.of(location);
if (applyCorrection) {
@@ -269,6 +270,7 @@ public class ActionManagerImpl implements ActionManager {
boolean onlyShowToOne = !section.getBoolean("visible-to-all", true);
return condition -> {
if (Math.random() > chance) return;
if (condition.getArg("{offline}") != null) return;
if (item.equals("")) return;
Location location = condition.getLocation().clone().add(x,y,z);
new TempFakeItem(location, item, duration, onlyShowToOne ? condition.getPlayer() : null).start();
@@ -446,7 +448,7 @@ public class ActionManagerImpl implements ActionManager {
.flatMap(world -> world.getLoadedChunkAt(ChunkPos.getByBukkitChunk(location.getChunk())))
.flatMap(chunk -> chunk.getBlockAt(SimpleLocation.of(location)))
.ifPresent(block -> {
block.tick(1);
block.tick(1, false);
if (block instanceof WorldSprinkler sprinkler) {
Sprinkler config = sprinkler.getConfig();
state.setArg("{current}", String.valueOf(sprinkler.getWater()));

View File

@@ -33,8 +33,9 @@ import net.momirealms.customcrops.api.mechanic.world.season.Season;
import net.momirealms.customcrops.api.util.LogUtils;
import net.momirealms.customcrops.compatibility.papi.ParseUtils;
import net.momirealms.customcrops.mechanic.misc.CrowAttackAnimation;
import net.momirealms.customcrops.utils.ClassUtils;
import net.momirealms.customcrops.utils.ConfigUtils;
import net.momirealms.customcrops.mechanic.world.block.MemoryCrop;
import net.momirealms.customcrops.util.ClassUtils;
import net.momirealms.customcrops.util.ConfigUtils;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.data.type.Farmland;
@@ -95,6 +96,7 @@ public class ConditionManagerImpl implements ConditionManager {
this.registerCrowAttackCondition();
this.registerPotCondition();
this.registerLightCondition();
this.registerPointCondition();
}
@Override
@@ -167,7 +169,7 @@ public class ConditionManagerImpl implements ConditionManager {
String flyModel = section.getString("fly-model");
String standModel = section.getString("stand-model");
double chance = section.getDouble("chance");
return block -> {
return (block, offline) -> {
if (Math.random() > chance) return false;
SimpleLocation location = block.getLocation();
if (ConfigManager.enableScarecrow()) {
@@ -185,7 +187,8 @@ public class ConditionManagerImpl implements ConditionManager {
}
}
}
new CrowAttackAnimation(location, flyModel, standModel).start();
if (!offline)
new CrowAttackAnimation(location, flyModel, standModel).start();
return true;
};
} else {
@@ -198,14 +201,14 @@ public class ConditionManagerImpl implements ConditionManager {
private void registerBiomeRequirement() {
registerCondition("biome", (args) -> {
HashSet<String> biomes = new HashSet<>(ConfigUtils.stringListArgs(args));
return block -> {
return (block, offline) -> {
String currentBiome = BiomeAPI.getBiomeAt(block.getLocation().getBukkitLocation());
return biomes.contains(currentBiome);
};
});
registerCondition("!biome", (args) -> {
HashSet<String> biomes = new HashSet<>(ConfigUtils.stringListArgs(args));
return block -> {
return (block, offline) -> {
String currentBiome = BiomeAPI.getBiomeAt(block.getLocation().getBukkitLocation());
return !biomes.contains(currentBiome);
};
@@ -215,21 +218,21 @@ public class ConditionManagerImpl implements ConditionManager {
private void registerRandomCondition() {
registerCondition("random", (args -> {
double value = ConfigUtils.getDoubleValue(args);
return block -> Math.random() < value;
return (block, offline) -> Math.random() < value;
}));
}
private void registerPotCondition() {
registerCondition("pot", (args -> {
HashSet<String> pots = new HashSet<>(ConfigUtils.stringListArgs(args));
return block -> {
return (block, offline) -> {
Optional<WorldPot> worldPot = plugin.getWorldManager().getPotAt(block.getLocation().copy().add(0,-1,0));
return worldPot.filter(pot -> pots.contains(pot.getKey())).isPresent();
};
}));
registerCondition("!pot", (args -> {
HashSet<String> pots = new HashSet<>(ConfigUtils.stringListArgs(args));
return block -> {
return (block, offline) -> {
Optional<WorldPot> worldPot = plugin.getWorldManager().getPotAt(block.getLocation().copy().add(0,-1,0));
return worldPot.filter(pot -> !pots.contains(pot.getKey())).isPresent();
};
@@ -239,7 +242,7 @@ public class ConditionManagerImpl implements ConditionManager {
private void registerFertilizerCondition() {
registerCondition("fertilizer", (args -> {
HashSet<String> fertilizer = new HashSet<>(ConfigUtils.stringListArgs(args));
return block -> {
return (block, offline) -> {
Optional<WorldPot> worldPot = plugin.getWorldManager().getPotAt(block.getLocation().copy().add(0,-1,0));
return worldPot.filter(pot -> {
Fertilizer fertilizerInstance = pot.getFertilizer();
@@ -250,7 +253,7 @@ public class ConditionManagerImpl implements ConditionManager {
}));
registerCondition("fertilizer_type", (args -> {
HashSet<String> fertilizer = new HashSet<>(ConfigUtils.stringListArgs(args).stream().map(str -> str.toUpperCase(Locale.ENGLISH)).toList());
return block -> {
return (block, offline) -> {
Optional<WorldPot> worldPot = plugin.getWorldManager().getPotAt(block.getLocation().copy().add(0,-1,0));
return worldPot.filter(pot -> {
Fertilizer fertilizerInstance = pot.getFertilizer();
@@ -265,7 +268,7 @@ public class ConditionManagerImpl implements ConditionManager {
registerCondition("&&", (args -> {
if (args instanceof ConfigurationSection section) {
Condition[] conditions = getConditions(section);
return block -> ConditionManager.isConditionMet(block, conditions);
return (block, offline) -> ConditionManager.isConditionMet(block, offline, conditions);
} else {
LogUtils.warn("Wrong value format found at && condition.");
return EmptyCondition.instance;
@@ -277,9 +280,9 @@ public class ConditionManagerImpl implements ConditionManager {
registerCondition("||", (args -> {
if (args instanceof ConfigurationSection section) {
Condition[] conditions = getConditions(section);
return block -> {
return (block, offline) -> {
for (Condition condition : conditions) {
if (condition.isConditionMet(block)) {
if (condition.isConditionMet(block, offline)) {
return true;
}
}
@@ -295,7 +298,7 @@ public class ConditionManagerImpl implements ConditionManager {
private void registerTemperatureCondition() {
registerCondition("temperature", (args) -> {
List<Pair<Integer, Integer>> tempPairs = ConfigUtils.stringListArgs(args).stream().map(it -> ConfigUtils.splitStringIntegerArgs(it, "~")).toList();
return block -> {
return (block, offline) -> {
SimpleLocation location = block.getLocation();
World world = location.getBukkitWorld();
if (world == null) return false;
@@ -316,7 +319,7 @@ public class ConditionManagerImpl implements ConditionManager {
if (args instanceof ConfigurationSection section) {
String v1 = section.getString("value1", "");
String v2 = section.getString("value2", "");
return block -> {
return (block, offline) -> {
String p1 = v1.startsWith("%") ? ParseUtils.setPlaceholders(null, v1) : v1;
String p2 = v2.startsWith("%") ? ParseUtils.setPlaceholders(null, v2) : v2;
return Double.parseDouble(p1) >= Double.parseDouble(p2);
@@ -330,7 +333,7 @@ public class ConditionManagerImpl implements ConditionManager {
if (args instanceof ConfigurationSection section) {
String v1 = section.getString("value1", "");
String v2 = section.getString("value2", "");
return block -> {
return (block, offline) -> {
String p1 = v1.startsWith("%") ? ParseUtils.setPlaceholders(null, v1) : v1;
String p2 = v2.startsWith("%") ? ParseUtils.setPlaceholders(null, v2) : v2;
return Double.parseDouble(p1) > Double.parseDouble(p2);
@@ -347,7 +350,7 @@ public class ConditionManagerImpl implements ConditionManager {
if (args instanceof ConfigurationSection section) {
String v1 = section.getString("papi", "");
String v2 = section.getString("regex", "");
return block -> ParseUtils.setPlaceholders(null, v1).matches(v2);
return (block, offline) -> ParseUtils.setPlaceholders(null, v1).matches(v2);
} else {
LogUtils.warn("Wrong value format found at regex requirement.");
return EmptyCondition.instance;
@@ -360,7 +363,7 @@ public class ConditionManagerImpl implements ConditionManager {
if (args instanceof ConfigurationSection section) {
String v1 = section.getString("value1", "");
String v2 = section.getString("value2", "");
return block -> {
return (block, offline) -> {
String p1 = v1.startsWith("%") ? ParseUtils.setPlaceholders(null, v1) : v1;
String p2 = v2.startsWith("%") ? ParseUtils.setPlaceholders(null, v2) : v2;
return Double.parseDouble(p1) == Double.parseDouble(p2);
@@ -374,7 +377,7 @@ public class ConditionManagerImpl implements ConditionManager {
if (args instanceof ConfigurationSection section) {
String v1 = section.getString("value1", "");
String v2 = section.getString("value2", "");
return block -> {
return (block, offline) -> {
String p1 = v1.startsWith("%") ? ParseUtils.setPlaceholders(null, v1) : v1;
String p2 = v2.startsWith("%") ? ParseUtils.setPlaceholders(null, v2) : v2;
return Double.parseDouble(p1) != Double.parseDouble(p2);
@@ -392,7 +395,7 @@ public class ConditionManagerImpl implements ConditionManager {
if (args instanceof ConfigurationSection section) {
String v1 = section.getString("value1", "");
String v2 = section.getString("value2", "");
return block -> {
return (block, offline) -> {
String p1 = v1.startsWith("%") ? ParseUtils.setPlaceholders(null, v1) : v1;
String p2 = v2.startsWith("%") ? ParseUtils.setPlaceholders(null, v2) : v2;
return Double.parseDouble(p1) < Double.parseDouble(p2);
@@ -406,7 +409,7 @@ public class ConditionManagerImpl implements ConditionManager {
if (args instanceof ConfigurationSection section) {
String v1 = section.getString("value1", "");
String v2 = section.getString("value2", "");
return block -> {
return (block, offline) -> {
String p1 = v1.startsWith("%") ? ParseUtils.setPlaceholders(null, v1) : v1;
String p2 = v2.startsWith("%") ? ParseUtils.setPlaceholders(null, v2) : v2;
return Double.parseDouble(p1) <= Double.parseDouble(p2);
@@ -423,7 +426,7 @@ public class ConditionManagerImpl implements ConditionManager {
if (args instanceof ConfigurationSection section) {
String v1 = section.getString("value1", "");
String v2 = section.getString("value2", "");
return block -> {
return (block, offline) -> {
String p1 = v1.startsWith("%") ? ParseUtils.setPlaceholders(null, v1) : v1;
String p2 = v2.startsWith("%") ? ParseUtils.setPlaceholders(null, v2) : v2;
return p1.startsWith(p2);
@@ -437,7 +440,7 @@ public class ConditionManagerImpl implements ConditionManager {
if (args instanceof ConfigurationSection section) {
String v1 = section.getString("value1", "");
String v2 = section.getString("value2", "");
return block -> {
return (block, offline) -> {
String p1 = v1.startsWith("%") ? ParseUtils.setPlaceholders(null, v1) : v1;
String p2 = v2.startsWith("%") ? ParseUtils.setPlaceholders(null, v2) : v2;
return !p1.startsWith(p2);
@@ -454,7 +457,7 @@ public class ConditionManagerImpl implements ConditionManager {
if (args instanceof ConfigurationSection section) {
String v1 = section.getString("value1", "");
String v2 = section.getString("value2", "");
return block -> {
return (block, offline) -> {
String p1 = v1.startsWith("%") ? ParseUtils.setPlaceholders(null, v1) : v1;
String p2 = v2.startsWith("%") ? ParseUtils.setPlaceholders(null, v2) : v2;
return p1.endsWith(p2);
@@ -468,7 +471,7 @@ public class ConditionManagerImpl implements ConditionManager {
if (args instanceof ConfigurationSection section) {
String v1 = section.getString("value1", "");
String v2 = section.getString("value2", "");
return block -> {
return (block, offline) -> {
String p1 = v1.startsWith("%") ? ParseUtils.setPlaceholders(null, v1) : v1;
String p2 = v2.startsWith("%") ? ParseUtils.setPlaceholders(null, v2) : v2;
return !p1.endsWith(p2);
@@ -485,7 +488,7 @@ public class ConditionManagerImpl implements ConditionManager {
if (args instanceof ConfigurationSection section) {
String v1 = section.getString("value1", "");
String v2 = section.getString("value2", "");
return block -> {
return (block, offline) -> {
String p1 = v1.startsWith("%") ? ParseUtils.setPlaceholders(null, v1) : v1;
String p2 = v2.startsWith("%") ? ParseUtils.setPlaceholders(null, v2) : v2;
return p1.contains(p2);
@@ -499,7 +502,7 @@ public class ConditionManagerImpl implements ConditionManager {
if (args instanceof ConfigurationSection section) {
String v1 = section.getString("value1", "");
String v2 = section.getString("value2", "");
return block -> {
return (block, offline) -> {
String p1 = v1.startsWith("%") ? ParseUtils.setPlaceholders(null, v1) : v1;
String p2 = v2.startsWith("%") ? ParseUtils.setPlaceholders(null, v2) : v2;
return !p1.contains(p2);
@@ -516,7 +519,7 @@ public class ConditionManagerImpl implements ConditionManager {
if (args instanceof ConfigurationSection section) {
String papi = section.getString("papi", "");
HashSet<String> values = new HashSet<>(ConfigUtils.stringListArgs(section.get("values")));
return block -> {
return (block, offline) -> {
String p1 = papi.startsWith("%") ? ParseUtils.setPlaceholders(null, papi) : papi;
return values.contains(p1);
};
@@ -529,7 +532,7 @@ public class ConditionManagerImpl implements ConditionManager {
if (args instanceof ConfigurationSection section) {
String papi = section.getString("papi", "");
HashSet<String> values = new HashSet<>(ConfigUtils.stringListArgs(section.get("values")));
return block -> {
return (block, offline) -> {
String p1 = papi.startsWith("%") ? ParseUtils.setPlaceholders(null, papi) : papi;
return !values.contains(p1);
};
@@ -545,7 +548,7 @@ public class ConditionManagerImpl implements ConditionManager {
if (args instanceof ConfigurationSection section) {
String v1 = section.getString("value1", "");
String v2 = section.getString("value2", "");
return block -> {
return (block, offline) -> {
String p1 = v1.startsWith("%") ? ParseUtils.setPlaceholders(null, v1) : v1;
String p2 = v2.startsWith("%") ? ParseUtils.setPlaceholders(null, v2) : v2;
return p1.equals(p2);
@@ -559,7 +562,7 @@ public class ConditionManagerImpl implements ConditionManager {
if (args instanceof ConfigurationSection section) {
String v1 = section.getString("value1", "");
String v2 = section.getString("value2", "");
return block -> {
return (block, offline) -> {
String p1 = v1.startsWith("%") ? ParseUtils.setPlaceholders(null, v1) : v1;
String p2 = v2.startsWith("%") ? ParseUtils.setPlaceholders(null, v2) : v2;
return !p1.equals(p2);
@@ -574,7 +577,7 @@ public class ConditionManagerImpl implements ConditionManager {
private void registerSeasonCondition() {
registerCondition("suitable_season", (args) -> {
HashSet<String> seasons = new HashSet<>(ConfigUtils.stringListArgs(args).stream().map(it -> it.toUpperCase(Locale.ENGLISH)).toList());
return block -> {
return (block, offline) -> {
Season season = plugin.getIntegrationManager().getSeason(block.getLocation().getBukkitWorld());
if (season == null) {
return true;
@@ -598,7 +601,7 @@ public class ConditionManagerImpl implements ConditionManager {
});
registerCondition("unsuitable_season", (args) -> {
HashSet<String> seasons = new HashSet<>(ConfigUtils.stringListArgs(args).stream().map(it -> it.toUpperCase(Locale.ENGLISH)).toList());
return block -> {
return (block, offline) -> {
Season season = plugin.getIntegrationManager().getSeason(block.getLocation().getBukkitWorld());
if (season == null) {
return false;
@@ -625,52 +628,73 @@ public class ConditionManagerImpl implements ConditionManager {
private void registerLightCondition() {
registerCondition("skylight_more_than", (args) -> {
int value = (int) args;
return block -> {
return (block, offline) -> {
int light = block.getLocation().getBukkitLocation().getBlock().getLightFromSky();
return value > light;
};
});
registerCondition("skylight_less_than", (args) -> {
int value = (int) args;
return block -> {
return (block, offline) -> {
int light = block.getLocation().getBukkitLocation().getBlock().getLightFromSky();
return value < light;
};
});
registerCondition("light_more_than", (args) -> {
int value = (int) args;
return block -> {
return (block, offline) -> {
int light = block.getLocation().getBukkitLocation().getBlock().getLightLevel();
return value > light;
};
});
registerCondition("light_less_than", (args) -> {
int value = (int) args;
return block -> {
return (block, offline) -> {
int light = block.getLocation().getBukkitLocation().getBlock().getLightLevel();
return value < light;
};
});
}
private void registerPointCondition() {
registerCondition("point_more_than", (args) -> {
int value = (int) args;
return (block, offline) -> {
if (block instanceof MemoryCrop crop) {
return crop.getPoint() > value;
}
return false;
};
});
registerCondition("point_less_than", (args) -> {
int value = (int) args;
return (block, offline) -> {
if (block instanceof MemoryCrop crop) {
return crop.getPoint() < value;
}
return false;
};
});
}
private void registerWaterCondition() {
registerCondition("water_more_than", (args) -> {
int value = (int) args;
return block -> {
return (block, offline) -> {
Optional<WorldPot> worldPot = plugin.getWorldManager().getPotAt(block.getLocation().copy().add(0,-1,0));
return worldPot.filter(pot -> pot.getWater() > value).isPresent();
};
});
registerCondition("water_less_than", (args) -> {
int value = (int) args;
return block -> {
return (block, offline) -> {
Optional<WorldPot> worldPot = plugin.getWorldManager().getPotAt(block.getLocation().copy().add(0,-1,0));
return worldPot.filter(pot -> pot.getWater() < value).isPresent();
};
});
registerCondition("moisture_more_than", (args) -> {
int value = (int) args;
return block -> {
return (block, offline) -> {
Block underBlock = block.getLocation().copy().add(0,-1,0).getBukkitLocation().getBlock();
if (underBlock.getBlockData() instanceof Farmland farmland) {
return farmland.getMoisture() > value;
@@ -680,7 +704,7 @@ public class ConditionManagerImpl implements ConditionManager {
});
registerCondition("moisture_less_than", (args) -> {
int value = (int) args;
return block -> {
return (block, offline) -> {
Block underBlock = block.getLocation().copy().add(0,-1,0).getBukkitLocation().getBlock();
if (underBlock.getBlockData() instanceof Farmland farmland) {
return farmland.getMoisture() < value;

View File

@@ -25,7 +25,7 @@ public class EmptyCondition implements Condition {
public static EmptyCondition instance = new EmptyCondition();
@Override
public boolean isConditionMet(CustomCropsBlock block) {
public boolean isConditionMet(CustomCropsBlock block, boolean offline) {
return true;
}
}

View File

@@ -20,9 +20,9 @@ package net.momirealms.customcrops.mechanic.item;
import net.momirealms.customcrops.api.manager.VersionManager;
import net.momirealms.customcrops.api.mechanic.misc.CRotation;
import net.momirealms.customcrops.api.util.LocationUtils;
import net.momirealms.customcrops.utils.ConfigUtils;
import net.momirealms.customcrops.utils.DisplayEntityUtils;
import net.momirealms.customcrops.utils.RotationUtils;
import net.momirealms.customcrops.util.ConfigUtils;
import net.momirealms.customcrops.util.DisplayEntityUtils;
import net.momirealms.customcrops.util.RotationUtils;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;

View File

@@ -57,10 +57,10 @@ import net.momirealms.customcrops.mechanic.item.impl.SprinklerConfig;
import net.momirealms.customcrops.mechanic.item.impl.WateringCanConfig;
import net.momirealms.customcrops.mechanic.item.impl.fertilizer.*;
import net.momirealms.customcrops.mechanic.world.block.*;
import net.momirealms.customcrops.utils.ConfigUtils;
import net.momirealms.customcrops.utils.EventUtils;
import net.momirealms.customcrops.utils.ItemUtils;
import net.momirealms.customcrops.utils.RotationUtils;
import net.momirealms.customcrops.util.ConfigUtils;
import net.momirealms.customcrops.util.EventUtils;
import net.momirealms.customcrops.util.ItemUtils;
import net.momirealms.customcrops.util.RotationUtils;
import org.bukkit.*;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
@@ -213,7 +213,7 @@ public class ItemManagerImpl implements ItemManager {
@Override
public String getItemID(ItemStack itemStack) {
if (itemStack == null)
if (itemStack == null || itemStack.getType() == Material.AIR || itemStack.getAmount() == 0)
return "AIR";
String id;
id = customProvider.getItemID(itemStack);

View File

@@ -27,7 +27,7 @@ import net.momirealms.customcrops.api.mechanic.requirement.State;
import net.momirealms.customcrops.api.mechanic.world.SimpleLocation;
import net.momirealms.customcrops.api.mechanic.world.level.WorldCrop;
import net.momirealms.customcrops.mechanic.item.ItemManagerImpl;
import net.momirealms.customcrops.utils.EventUtils;
import net.momirealms.customcrops.util.EventUtils;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;

View File

@@ -20,7 +20,6 @@ package net.momirealms.customcrops.mechanic.item.custom.itemsadder;
import dev.lone.itemsadder.api.CustomBlock;
import dev.lone.itemsadder.api.CustomFurniture;
import dev.lone.itemsadder.api.CustomStack;
import net.momirealms.customcrops.api.util.LocationUtils;
import net.momirealms.customcrops.api.util.LogUtils;
import net.momirealms.customcrops.mechanic.item.CustomProvider;
import org.bukkit.Location;

View File

@@ -41,9 +41,7 @@ public class OraxenProvider implements CustomProvider {
if (block.getType() == Material.AIR) {
return false;
}
if (!OraxenBlocks.remove(location, null, false)) {
block.setType(Material.AIR);
}
block.setType(Material.AIR);
return true;
}

View File

@@ -26,7 +26,7 @@ import net.momirealms.customcrops.api.mechanic.item.water.PassiveFillMethod;
import net.momirealms.customcrops.api.mechanic.misc.image.WaterBar;
import net.momirealms.customcrops.api.mechanic.requirement.Requirement;
import net.momirealms.customcrops.mechanic.item.AbstractEventItem;
import net.momirealms.customcrops.utils.ConfigUtils;
import net.momirealms.customcrops.util.ConfigUtils;
import java.util.HashMap;
import java.util.HashSet;

View File

@@ -22,7 +22,7 @@ import net.momirealms.customcrops.api.CustomCropsPlugin;
import net.momirealms.customcrops.api.mechanic.world.SimpleLocation;
import net.momirealms.customcrops.api.scheduler.CancellableTask;
import net.momirealms.customcrops.manager.PacketManager;
import net.momirealms.customcrops.utils.FakeEntityUtils;
import net.momirealms.customcrops.util.FakeEntityUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.EntityType;

View File

@@ -21,7 +21,7 @@ import com.comphenix.protocol.events.PacketContainer;
import net.momirealms.customcrops.api.CustomCropsPlugin;
import net.momirealms.customcrops.api.mechanic.world.SimpleLocation;
import net.momirealms.customcrops.manager.PacketManager;
import net.momirealms.customcrops.utils.FakeEntityUtils;
import net.momirealms.customcrops.util.FakeEntityUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.EntityType;

View File

@@ -11,7 +11,7 @@ import net.momirealms.customcrops.api.mechanic.world.level.WorldSetting;
import net.momirealms.customcrops.api.util.LogUtils;
import net.momirealms.customcrops.mechanic.world.CWorld;
import net.momirealms.customcrops.mechanic.world.adaptor.BukkitWorldAdaptor;
import net.momirealms.customcrops.utils.ConfigUtils;
import net.momirealms.customcrops.util.ConfigUtils;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.configuration.ConfigurationSection;
@@ -47,7 +47,7 @@ public class Migration {
if (CustomCropsPlugin.get().getWorldManager().getWorldAdaptor() instanceof BukkitWorldAdaptor adaptor) {
for (World world : Bukkit.getWorlds()) {
CWorld temp = new CWorld(CustomCropsPlugin.getInstance().getWorldManager(), world);
temp.setWorldSetting(WorldSetting.of(false,300,true, 1,true,2,true,2,false,false,false,28,-1,-1,-1, 0));
temp.setWorldSetting(WorldSetting.of(false,300,true, 1,true,2,true,2,false,1200, false,false,28,-1,-1,-1, 0));
adaptor.convertWorldFromV342toV343(temp, world);
}
}
@@ -102,7 +102,7 @@ public class Migration {
if (CustomCropsPlugin.get().getWorldManager().getWorldAdaptor() instanceof BukkitWorldAdaptor adaptor) {
for (World world : Bukkit.getWorlds()) {
CWorld temp = new CWorld(CustomCropsPlugin.getInstance().getWorldManager(), world);
temp.setWorldSetting(WorldSetting.of(false,300,true, 1,true,2,true,2,false,false,false,28,-1,-1,-1, 0));
temp.setWorldSetting(WorldSetting.of(false,300,true, 1,true,2,true,2,false, 1200, false,false,28,-1,-1,-1, 0));
adaptor.convertWorldFromV33toV34(temp, world);
}
}

View File

@@ -18,7 +18,7 @@
package net.momirealms.customcrops.mechanic.misc.value;
import net.momirealms.customcrops.api.mechanic.misc.Value;
import net.momirealms.customcrops.utils.ConfigUtils;
import net.momirealms.customcrops.util.ConfigUtils;
import org.bukkit.entity.Player;
import java.util.HashMap;

View File

@@ -37,8 +37,8 @@ import net.momirealms.customcrops.api.mechanic.world.season.Season;
import net.momirealms.customcrops.api.util.LogUtils;
import net.momirealms.customcrops.compatibility.VaultHook;
import net.momirealms.customcrops.compatibility.papi.ParseUtils;
import net.momirealms.customcrops.utils.ClassUtils;
import net.momirealms.customcrops.utils.ConfigUtils;
import net.momirealms.customcrops.util.ClassUtils;
import net.momirealms.customcrops.util.ConfigUtils;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;

View File

@@ -88,7 +88,26 @@ public class CChunk implements CustomCropsChunk {
@Override
public void notifyOfflineUpdates() {
this.lastLoadedTime = System.currentTimeMillis();
long current = System.currentTimeMillis();
int offlineTimeInSeconds = (int) (this.lastLoadedTime - current) / 1000;
offlineTimeInSeconds = Math.min(offlineTimeInSeconds, cWorld.getWorldSetting().getMaxOfflineTime());
this.lastLoadedTime = current;
var setting = cWorld.getWorldSetting();
int minTickUnit = setting.getMinTickUnit();
for (int i = 0; i < offlineTimeInSeconds; i++) {
this.loadedSeconds++;
if (this.loadedSeconds >= minTickUnit) {
this.loadedSeconds = 0;
this.tickedBlocks.clear();
this.queue.clear();
if (setting.isScheduledTick()) {
this.arrangeTasks(minTickUnit);
}
}
scheduledTick(setting, true);
randomTick(setting, true);
}
}
public void setWorld(CWorld cWorld) {
@@ -121,10 +140,15 @@ public class CChunk implements CustomCropsChunk {
this.tickedBlocks.clear();
this.queue.clear();
if (setting.isScheduledTick()) {
this.arrangeTasks(setting.getMinTickUnit());
this.arrangeTasks(interval);
}
}
scheduledTick(setting, false);
randomTick(setting, false);
}
private void scheduledTick(WorldSetting setting, boolean offline) {
// scheduled tick
while (!queue.isEmpty() && queue.peek().getTime() <= loadedSeconds) {
TickTask task = queue.poll();
@@ -138,24 +162,26 @@ public class CChunk implements CustomCropsChunk {
case SCARECROW, GREENHOUSE -> {}
case POT -> {
if (!setting.randomTickPot()) {
block.tick(setting.getTickPotInterval());
block.tick(setting.getTickPotInterval(), offline);
}
}
case CROP -> {
if (!setting.randomTickCrop()) {
block.tick(setting.getTickCropInterval());
block.tick(setting.getTickCropInterval(), offline);
}
}
case SPRINKLER -> {
if (!setting.randomTickSprinkler()) {
block.tick(setting.getTickSprinklerInterval());
block.tick(setting.getTickSprinklerInterval(), offline);
}
}
}
}
}
}
}
private void randomTick(WorldSetting setting, boolean offline) {
// random tick
ThreadLocalRandom random = ThreadLocalRandom.current();
int randomTicks = setting.getRandomTickSpeed();
@@ -171,18 +197,18 @@ public class CChunk implements CustomCropsChunk {
switch (block.getType()) {
case CROP -> {
if (setting.randomTickCrop()) {
block.tick(setting.getTickCropInterval());
block.tick(setting.getTickCropInterval(), offline);
}
}
case SPRINKLER -> {
if (setting.randomTickSprinkler()) {
block.tick(setting.getTickSprinklerInterval());
block.tick(setting.getTickSprinklerInterval(), offline);
}
}
case POT -> {
((WorldPot) block).tickWater(this);
if (setting.randomTickPot()) {
block.tick(setting.getTickPotInterval());
block.tick(setting.getTickPotInterval(), offline);
}
}
}

View File

@@ -36,7 +36,7 @@ import net.momirealms.customcrops.api.mechanic.world.season.Season;
import net.momirealms.customcrops.api.scheduler.CancellableTask;
import net.momirealms.customcrops.api.scheduler.Scheduler;
import net.momirealms.customcrops.api.util.LogUtils;
import net.momirealms.customcrops.utils.EventUtils;
import net.momirealms.customcrops.util.EventUtils;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.jetbrains.annotations.Nullable;
@@ -122,13 +122,19 @@ public class CWorld implements CustomCropsWorld {
this.updateSeasonAndDate();
}
if (setting.isSchedulerEnabled()) {
Scheduler scheduler = CustomCropsPlugin.get().getScheduler();
if (VersionManager.folia()) {
Scheduler scheduler = CustomCropsPlugin.get().getScheduler();
for (CChunk chunk : loadedChunks.values()) {
if (unloadIfNotLoaded(chunk.getChunkPos())) {
continue;
}
scheduler.runTaskSync(chunk::secondTimer, getWorld(), chunk.getChunkPos().x(), chunk.getChunkPos().z());
}
} else {
for (CChunk chunk : loadedChunks.values()) {
if (unloadIfNotLoaded(chunk.getChunkPos())) {
continue;
}
chunk.secondTimer();
}
}
@@ -302,49 +308,49 @@ public class CWorld implements CustomCropsWorld {
@Override
public Optional<WorldSprinkler> getSprinklerAt(SimpleLocation location) {
CChunk chunk = loadedChunks.get(location.getChunkCoordinate());
CChunk chunk = loadedChunks.get(location.getChunkPos());
if (chunk == null) return Optional.empty();
return chunk.getSprinklerAt(location);
}
@Override
public Optional<WorldPot> getPotAt(SimpleLocation location) {
CChunk chunk = loadedChunks.get(location.getChunkCoordinate());
CChunk chunk = loadedChunks.get(location.getChunkPos());
if (chunk == null) return Optional.empty();
return chunk.getPotAt(location);
}
@Override
public Optional<WorldCrop> getCropAt(SimpleLocation location) {
CChunk chunk = loadedChunks.get(location.getChunkCoordinate());
CChunk chunk = loadedChunks.get(location.getChunkPos());
if (chunk == null) return Optional.empty();
return chunk.getCropAt(location);
}
@Override
public Optional<WorldGlass> getGlassAt(SimpleLocation location) {
CChunk chunk = loadedChunks.get(location.getChunkCoordinate());
CChunk chunk = loadedChunks.get(location.getChunkPos());
if (chunk == null) return Optional.empty();
return chunk.getGlassAt(location);
}
@Override
public Optional<WorldScarecrow> getScarecrowAt(SimpleLocation location) {
CChunk chunk = loadedChunks.get(location.getChunkCoordinate());
CChunk chunk = loadedChunks.get(location.getChunkPos());
if (chunk == null) return Optional.empty();
return chunk.getScarecrowAt(location);
}
@Override
public Optional<CustomCropsBlock> getBlockAt(SimpleLocation location) {
CChunk chunk = loadedChunks.get(location.getChunkCoordinate());
CChunk chunk = loadedChunks.get(location.getChunkPos());
if (chunk == null) return Optional.empty();
return chunk.getBlockAt(location);
}
@Override
public void addWaterToSprinkler(Sprinkler sprinkler, SimpleLocation location, int amount) {
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkPos());
if (chunk.isPresent()) {
chunk.get().addWaterToSprinkler(sprinkler, location, amount);
} else {
@@ -354,7 +360,7 @@ public class CWorld implements CustomCropsWorld {
@Override
public void addFertilizerToPot(Pot pot, Fertilizer fertilizer, SimpleLocation location) {
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkPos());
if (chunk.isPresent()) {
chunk.get().addFertilizerToPot(pot, fertilizer, location);
} else {
@@ -364,7 +370,7 @@ public class CWorld implements CustomCropsWorld {
@Override
public void addWaterToPot(Pot pot, SimpleLocation location, int amount) {
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkPos());
if (chunk.isPresent()) {
chunk.get().addWaterToPot(pot, location, amount);
} else {
@@ -374,7 +380,7 @@ public class CWorld implements CustomCropsWorld {
@Override
public void addPotAt(WorldPot pot, SimpleLocation location) {
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkPos());
if (chunk.isPresent()) {
chunk.get().addPotAt(pot, location);
} else {
@@ -384,7 +390,7 @@ public class CWorld implements CustomCropsWorld {
@Override
public void addSprinklerAt(WorldSprinkler sprinkler, SimpleLocation location) {
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkPos());
if (chunk.isPresent()) {
chunk.get().addSprinklerAt(sprinkler, location);
} else {
@@ -394,7 +400,7 @@ public class CWorld implements CustomCropsWorld {
@Override
public void addCropAt(WorldCrop crop, SimpleLocation location) {
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkPos());
if (chunk.isPresent()) {
chunk.get().addCropAt(crop, location);
} else {
@@ -404,7 +410,7 @@ public class CWorld implements CustomCropsWorld {
@Override
public void addPointToCrop(Crop crop, SimpleLocation location, int points) {
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkPos());
if (chunk.isPresent()) {
chunk.get().addPointToCrop(crop, location, points);
} else {
@@ -414,7 +420,7 @@ public class CWorld implements CustomCropsWorld {
@Override
public void addGlassAt(WorldGlass glass, SimpleLocation location) {
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkPos());
if (chunk.isPresent()) {
chunk.get().addGlassAt(glass, location);
} else {
@@ -424,7 +430,7 @@ public class CWorld implements CustomCropsWorld {
@Override
public void addScarecrowAt(WorldScarecrow scarecrow, SimpleLocation location) {
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkPos());
if (chunk.isPresent()) {
chunk.get().addScarecrowAt(scarecrow, location);
} else {
@@ -434,7 +440,7 @@ public class CWorld implements CustomCropsWorld {
@Override
public void removeSprinklerAt(SimpleLocation location) {
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkPos());
if (chunk.isPresent()) {
chunk.get().removeSprinklerAt(location);
} else {
@@ -444,7 +450,7 @@ public class CWorld implements CustomCropsWorld {
@Override
public void removePotAt(SimpleLocation location) {
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkPos());
if (chunk.isPresent()) {
chunk.get().removePotAt(location);
} else {
@@ -454,7 +460,7 @@ public class CWorld implements CustomCropsWorld {
@Override
public void removeCropAt(SimpleLocation location) {
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkPos());
if (chunk.isPresent()) {
chunk.get().removeCropAt(location);
} else {
@@ -464,7 +470,7 @@ public class CWorld implements CustomCropsWorld {
@Override
public void removeGlassAt(SimpleLocation location) {
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkPos());
if (chunk.isPresent()) {
chunk.get().removeGlassAt(location);
} else {
@@ -474,7 +480,7 @@ public class CWorld implements CustomCropsWorld {
@Override
public void removeScarecrowAt(SimpleLocation location) {
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkPos());
if (chunk.isPresent()) {
chunk.get().removeScarecrowAt(location);
} else {
@@ -484,7 +490,7 @@ public class CWorld implements CustomCropsWorld {
@Override
public CustomCropsBlock removeAnythingAt(SimpleLocation location) {
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkPos());
if (chunk.isPresent()) {
return chunk.get().removeBlockAt(location);
} else {
@@ -514,7 +520,7 @@ public class CWorld implements CustomCropsWorld {
@Override
public boolean isPotReachLimit(SimpleLocation location) {
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkPos());
if (chunk.isEmpty()) {
LogUtils.warn("Invalid operation: Querying pot amount from a not generated chunk");
return true;
@@ -525,7 +531,7 @@ public class CWorld implements CustomCropsWorld {
@Override
public boolean isCropReachLimit(SimpleLocation location) {
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkPos());
if (chunk.isEmpty()) {
LogUtils.warn("Invalid operation: Querying crop amount from a not generated chunk");
return true;
@@ -536,7 +542,7 @@ public class CWorld implements CustomCropsWorld {
@Override
public boolean isSprinklerReachLimit(SimpleLocation location) {
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkCoordinate());
Optional<CustomCropsChunk> chunk = getLoadedChunkAt(location.getChunkPos());
if (chunk.isEmpty()) {
LogUtils.warn("Invalid operation: Querying sprinkler amount from a not generated chunk");
return true;
@@ -559,4 +565,12 @@ public class CWorld implements CustomCropsWorld {
}
return true;
}
private boolean unloadIfNotLoaded(ChunkPos pos) {
if (!world.get().isChunkLoaded(pos.x(), pos.z())) {
unloadChunk(pos);
return true;
}
return false;
}
}

View File

@@ -29,7 +29,7 @@ import net.momirealms.customcrops.api.mechanic.world.level.*;
import net.momirealms.customcrops.api.util.LogUtils;
import net.momirealms.customcrops.mechanic.world.adaptor.BukkitWorldAdaptor;
import net.momirealms.customcrops.mechanic.world.adaptor.SlimeWorldAdaptor;
import net.momirealms.customcrops.utils.ConfigUtils;
import net.momirealms.customcrops.util.ConfigUtils;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
@@ -490,6 +490,7 @@ public class WorldManagerImpl implements WorldManager, Listener {
}
CustomCropsChunk chunk = optionalChunk.get();
// load the entities if not loaded
bukkitChunk.getEntities();
chunk.notifyOfflineUpdates();
}

View File

@@ -101,13 +101,13 @@ public class MemoryCrop extends AbstractCustomCropsBlock implements WorldCrop {
}
@Override
public void tick(int interval) {
public void tick(int interval, boolean offline) {
if (canTick(interval)) {
tick();
tick(offline);
}
}
private void tick() {
private void tick(boolean offline) {
Crop crop = getConfig();
if (crop == null) {
LogUtils.warn("Found a crop without config at " + getLocation() + ". Try removing the data.");
@@ -124,14 +124,14 @@ public class MemoryCrop extends AbstractCustomCropsBlock implements WorldCrop {
// check death conditions
for (DeathConditions deathConditions : crop.getDeathConditions()) {
for (Condition condition : deathConditions.getConditions()) {
if (condition.isConditionMet(this)) {
if (condition.isConditionMet(this, offline)) {
CustomCropsPlugin.get().getScheduler().runTaskSyncLater(() -> {
CustomCropsPlugin.get().getWorldManager().removeCropAt(location);
CustomCropsPlugin.get().getItemManager().removeAnythingAt(bukkitLocation);
if (deathConditions.getDeathItem() != null) {
CustomCropsPlugin.get().getItemManager().placeItem(bukkitLocation, deathConditions.getItemCarrier(), deathConditions.getDeathItem());
}
}, bukkitLocation, deathConditions.getDeathDelay());
}, bukkitLocation, offline ? 0 : deathConditions.getDeathDelay());
return;
}
}
@@ -144,7 +144,7 @@ public class MemoryCrop extends AbstractCustomCropsBlock implements WorldCrop {
// check grow conditions
for (Condition condition : crop.getGrowConditions().getConditions()) {
if (!condition.isConditionMet(this)) {
if (!condition.isConditionMet(this, offline)) {
return;
}
}

View File

@@ -54,7 +54,7 @@ public class MemoryGlass extends AbstractCustomCropsBlock implements WorldGlass
}
@Override
public void tick(int interval) {
public void tick(int interval, boolean offline) {
}
}

View File

@@ -189,12 +189,13 @@ public class MemoryPot extends AbstractCustomCropsBlock implements WorldPot {
}
@Override
public void tick(int interval) {
public void tick(int interval, boolean offline) {
if (canTick(interval)) {
tick();
}
}
// if the tick is triggered by offline growth
private void tick() {
Pot pot = getConfig();
if (pot == null) {

View File

@@ -54,7 +54,7 @@ public class MemoryScarecrow extends AbstractCustomCropsBlock implements WorldSc
}
@Override
public void tick(int interval) {
public void tick(int interval, boolean offline) {
}
}

View File

@@ -26,6 +26,7 @@ import net.momirealms.customcrops.api.mechanic.item.ItemType;
import net.momirealms.customcrops.api.mechanic.item.Pot;
import net.momirealms.customcrops.api.mechanic.item.Sprinkler;
import net.momirealms.customcrops.api.mechanic.requirement.State;
import net.momirealms.customcrops.api.mechanic.world.ChunkPos;
import net.momirealms.customcrops.api.mechanic.world.SimpleLocation;
import net.momirealms.customcrops.api.mechanic.world.level.AbstractCustomCropsBlock;
import net.momirealms.customcrops.api.mechanic.world.level.CustomCropsWorld;
@@ -34,10 +35,10 @@ import net.momirealms.customcrops.api.mechanic.world.level.WorldSprinkler;
import net.momirealms.customcrops.api.util.LogUtils;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.inventory.ItemStack;
import java.util.Objects;
import java.util.Optional;
import java.util.*;
public class MemorySprinkler extends AbstractCustomCropsBlock implements WorldSprinkler {
@@ -97,13 +98,14 @@ public class MemorySprinkler extends AbstractCustomCropsBlock implements WorldSp
}
@Override
public void tick(int interval) {
public void tick(int interval, boolean offline) {
if (canTick(interval)) {
tick();
tick(offline);
}
}
private void tick() {
// if the tick is triggered by offline growth
private void tick(boolean offline) {
Sprinkler sprinkler = getConfig();
if (sprinkler == null) {
LogUtils.warn("Found a sprinkler without config at " + getLocation() + ". Try removing the data.");
@@ -127,7 +129,9 @@ public class MemorySprinkler extends AbstractCustomCropsBlock implements WorldSp
Location bukkitLocation = location.getBukkitLocation();
if (bukkitLocation == null) return;
CustomCropsPlugin.get().getScheduler().runTaskSync(() -> {
sprinkler.trigger(ActionTrigger.WORK, new State(null, new ItemStack(Material.AIR), bukkitLocation));
State state = new State(null, new ItemStack(Material.AIR), bukkitLocation);
if (offline) state.setArg("{offline}", "true");
sprinkler.trigger(ActionTrigger.WORK, state);
if (updateState && sprinkler.get3DItemWithWater() != null) {
CustomCropsPlugin.get().getItemManager().removeAnythingAt(bukkitLocation);
CustomCropsPlugin.get().getItemManager().placeItem(bukkitLocation, sprinkler.getItemCarrier(), sprinkler.get3DItemID());
@@ -135,11 +139,26 @@ public class MemorySprinkler extends AbstractCustomCropsBlock implements WorldSp
}, bukkitLocation);
int range = sprinkler.getRange();
CustomCropsWorld world = CustomCropsPlugin.get().getWorldManager().getCustomCropsWorld(location.getWorldName()).get();
HashMap<ChunkPos, ArrayList<SimpleLocation>> map = new HashMap<>();
for (int i = -range; i <= range; i++) {
for (int j = -range; j <= range; j++) {
for (int k : new int[]{-1,0}) {
SimpleLocation potLocation = location.copy().add(i,k,j);
var cPos = potLocation.getChunkPos();
var list = map.computeIfAbsent(cPos, key -> new ArrayList<>());
list.add(potLocation);
}
}
}
CustomCropsWorld world = CustomCropsPlugin.get().getWorldManager().getCustomCropsWorld(location.getWorldName()).get();
World bkWorld = world.getWorld();
for (Map.Entry<ChunkPos, ArrayList<SimpleLocation>> entry : map.entrySet()) {
var chunkPos = entry.getKey();
CustomCropsPlugin.get().getScheduler().runTaskSync(() -> {
// load the chunk firstly to load CustomCrops data
bkWorld.getChunkAt(chunkPos.x(), chunkPos.z());
for (SimpleLocation potLocation : entry.getValue()) {
Optional<WorldPot> pot = world.getPotAt(potLocation);
if (pot.isPresent()) {
WorldPot worldPot = pot.get();
@@ -152,13 +171,13 @@ public class MemorySprinkler extends AbstractCustomCropsBlock implements WorldSp
}
worldPot.setWater(current + sprinkler.getWater());
if (current == 0) {
CustomCropsPlugin.get().getScheduler().runTaskSync(() -> CustomCropsPlugin.get().getItemManager().updatePotState(potLocation.getBukkitLocation(), potConfig, true, worldPot.getFertilizer()), potLocation.getBukkitLocation());
CustomCropsPlugin.get().getItemManager().updatePotState(potLocation.getBukkitLocation(), potConfig, true, worldPot.getFertilizer());
}
}
}
}
}
}
}, bkWorld, chunkPos.x(), chunkPos.z());
}
}
}

View File

@@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.utils;
package net.momirealms.customcrops.util;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

View File

@@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.utils;
package net.momirealms.customcrops.util;
import com.google.common.base.Preconditions;
import net.momirealms.customcrops.api.CustomCropsPlugin;
@@ -70,7 +70,8 @@ public class ConfigUtils {
section.getInt("pot.tick-interval", 2),
getRandomTickModeByString(section.getString("sprinkler.mode")),
section.getInt("sprinkler.tick-interval", 2),
section.getBoolean("offline-grow", false),
section.getBoolean("offline-growth.enable", false),
section.getInt("offline-growth.max-offline-seconds", 1200),
section.getBoolean("season.enable", false),
section.getBoolean("season.auto-alternation", false),
section.getInt("season.duration", 28),

View File

@@ -1,4 +1,4 @@
package net.momirealms.customcrops.utils;
package net.momirealms.customcrops.util;
import net.momirealms.customcrops.api.mechanic.misc.CRotation;
import org.bukkit.entity.Entity;

View File

@@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.utils;
package net.momirealms.customcrops.util;
import org.bukkit.Bukkit;
import org.bukkit.event.Cancellable;

View File

@@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.utils;
package net.momirealms.customcrops.util;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer;

View File

@@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.utils;
package net.momirealms.customcrops.util;
import de.tr7zw.changeme.nbtapi.NBTItem;
import org.bukkit.Bukkit;

View File

@@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.utils;
package net.momirealms.customcrops.util;
import net.momirealms.customcrops.api.mechanic.misc.CRotation;
import org.bukkit.Rotation;

View File

@@ -46,6 +46,16 @@ worlds:
# For crops, under the same conditions, the growth rate of crops is basically the same
# For sprinklers and pots, they would work periodically.
min-tick-unit: 300
# Offline growth settings
# This option allows crops to grow even if the world is unloaded or the server is closed
# This may lead to some issues caused by timeliness conditions for instance seasons
offline-growth:
enable: false
# Maximum offline time recorded in seconds
# Please do not set this option to a value that is too large,
# as it may cause chunks that have been unloaded for a long time
# taking long to load
max-offline-seconds: 1200
# Settings for crops
crop:
# [RANDOM_TICK]