9
0
mirror of https://github.com/Xiao-MoMi/Custom-Crops.git synced 2025-12-25 18:09:28 +00:00
This commit is contained in:
Xiao-MoMi
2023-05-15 23:33:58 +08:00
parent 6895ddccdd
commit c123782dbd
17 changed files with 459 additions and 172 deletions

View File

@@ -90,6 +90,7 @@ public class PlatformManager extends Function {
public void onBreakVanilla(BlockBreakEvent event) {
if (event.isCancelled()) return;
Block block = event.getBlock();
if (block.getType() == Material.NOTE_BLOCK) plugin.getWorldDataManager().removeCorrupted(SimpleLocation.getByBukkitLocation(block.getLocation()));
onBreakSomething(event.getPlayer(), block.getLocation(), block.getType().name(), event);
}
@@ -227,12 +228,83 @@ public class PlatformManager extends Function {
return;
}
if (onInteractBrokenPot(id, location)) {
return;
}
if (onInteractWithWateringCan(player, item_in_hand_id, item_in_hand, id, location)) {
return;
}
}
}
private boolean onInteractBrokenPot(String id, Location location) {
if (!id.equals("NOTE_BLOCK")) {
return false;
}
SimpleLocation simpleLocation = SimpleLocation.getByBukkitLocation(location);
String replacer;
String potKey = plugin.getWorldDataManager().removeCorrupted(simpleLocation);
Pot pot = plugin.getWorldDataManager().getPotData(simpleLocation);
if (pot != null) {
replacer = pot.isWet() ? pot.getConfig().getWetPot(pot.getFertilizer()) : pot.getConfig().getDryPot(pot.getFertilizer());
} else {
if (potKey == null) {
return false;
}
PotConfig potConfig = plugin.getPotManager().getPotConfig(potKey);
if (potConfig == null) {
return true;
}
replacer = potConfig.getDryPot(null);
}
plugin.getPlatformInterface().placeNoteBlock(location, replacer);
furtherFix(location, 1);
return true;
}
public void furtherFix(Location location, int range) {
if (range >= ConfigManager.fixRange) return;
List<Location> locations = new ArrayList<>();
for (int i = -range; i <= range; i++) {
for (int j = -range; j <= range; j++) {
if (i == -range || i == range || j == range || j == -range) {
locations.add(location.clone().add(i, 0, j));
}
}
}
int success = 0;
for (Location check : locations) {
SimpleLocation simpleLocation = SimpleLocation.getByBukkitLocation(check);
String id = plugin.getPlatformInterface().getBlockID(check.getBlock());
String potKey = plugin.getWorldDataManager().removeCorrupted(simpleLocation);
if (!id.equals("NOTE_BLOCK")) {
continue;
}
String replacer;
Pot pot = plugin.getWorldDataManager().getPotData(simpleLocation);
if (pot != null) {
replacer = pot.isWet() ? pot.getConfig().getWetPot(pot.getFertilizer()) : pot.getConfig().getDryPot(pot.getFertilizer());
} else {
if (potKey == null) {
continue;
}
PotConfig potConfig = plugin.getPotManager().getPotConfig(potKey);
if (potConfig == null) {
continue;
}
replacer = potConfig.getDryPot(null);
}
plugin.getPlatformInterface().placeNoteBlock(check, replacer);
success++;
}
if (success != 0) {
furtherFix(location, range + 1);
}
}
public boolean onBreakGlass(Player player, String id, Location location, Cancellable event) {
if (!id.equals(ConfigManager.greenhouseBlock)) {
return false;
@@ -499,7 +571,7 @@ public class PlatformManager extends Function {
}
event.setCancelled(true);
doPassiveFillAction(player, item_in_hand, passiveFillMethod, bottomLoc);
doPassiveFillAction(player, item_in_hand, passiveFillMethod, location);
plugin.getWorldDataManager().addWaterToPot(SimpleLocation.getByBukkitLocation(bottomLoc), potWaterEvent.getWater(), pot_id);
return true;
}
@@ -921,8 +993,7 @@ public class PlatformManager extends Function {
tryToWaterPot(tempLoc, id, particle, water);
}
}
}
else {
} else {
for (int i = -extend; i <= extend; i++) {
Location tempLoc = location.clone().add(-1, 0, i);
for (int j = 0; j < length; j++){
@@ -931,8 +1002,7 @@ public class PlatformManager extends Function {
}
}
}
}
else {
} else {
if (yaw > 45 && yaw < 135) {
for (int i = -extend; i <= extend; i++) {
Location tempLoc = location.clone().add(1, 0, i);
@@ -941,8 +1011,7 @@ public class PlatformManager extends Function {
tryToWaterPot(tempLoc, id, particle, water);
}
}
}
else {
} else {
for (int i = -extend; i <= extend; i++) {
Location tempLoc = location.clone().add(i, 0, 1);
for (int j = 0; j < length; j++){

View File

@@ -62,6 +62,7 @@ public class ConfigManager extends Function {
public static int cacheSaveInterval;
public static int intervalConsume;
public static int intervalWork;
public static int fixRange;
public static boolean disableMoistureMechanic;
public static boolean preventTrampling;
public static boolean onlyInLoadedChunks;
@@ -148,6 +149,7 @@ public class ConfigManager extends Function {
private void loadOtherSetting(ConfigurationSection section) {
enableSkillBonus = section.getBoolean("skill-bonus.enable", false);
bonusFormula = section.getString("skill-bonus.formula");
fixRange = section.getInt("corrupt-fix-range", 4);
}
public int getCropLimit(String world) {

View File

@@ -46,7 +46,7 @@ public class MigrateWorld extends Function {
@Override
@SuppressWarnings("ResultOfMethodCallIgnored")
public void init() {
File chunks_folder = ConfigUtils.getChunkFolder(worldName);
File chunks_folder = ConfigUtils.getFile(worldName, "chunks");
if (!chunks_folder.exists()) chunks_folder.mkdirs();
File[] data_files = chunks_folder.listFiles();
if (data_files == null) return;
@@ -68,7 +68,7 @@ public class MigrateWorld extends Function {
@Override
@SuppressWarnings("ResultOfMethodCallIgnored")
public void disable() {
File chunks_folder = ConfigUtils.getChunkFolder(worldName);
File chunks_folder = ConfigUtils.getFile(worldName, "chunks");
if (!chunks_folder.exists()) chunks_folder.mkdirs();
for (Map.Entry<ChunkCoordinate, CCChunk> entry : chunkMap.entrySet()) {
ChunkCoordinate chunkCoordinate = entry.getKey();
@@ -194,7 +194,7 @@ public class MigrateWorld extends Function {
return chunk.getSprinklerData(simpleLocation);
}
public void addWaterToPot(SimpleLocation simpleLocation, int amount, @Nullable String pot_id) {
public void addWaterToPot(SimpleLocation simpleLocation, int amount, @NotNull String pot_id) {
CCChunk chunk = chunkMap.get(simpleLocation.getChunkCoordinate());
if (chunk != null) {
chunk.addWaterToPot(simpleLocation, amount, pot_id);

View File

@@ -109,4 +109,8 @@ public class PotConfig {
public String getKey() {
return key;
}
public boolean isEnableFertilized() {
return enableFertilized;
}
}

View File

@@ -130,24 +130,17 @@ public class CCChunk implements Serializable {
sprinklerMap.put(simpleLocation, sprinkler);
}
public void addWaterToPot(SimpleLocation simpleLocation, int amount, @Nullable String pot_id) {
public void addWaterToPot(SimpleLocation simpleLocation, int amount, @NotNull String pot_id) {
Pot pot = potMap.get(simpleLocation);
if (pot != null) {
if (pot.addWater(amount)) {
CustomCrops.getInstance().getScheduler().runTask(() -> changePotModel(simpleLocation, pot));
changePotModel(simpleLocation, pot);
}
return;
}
if (pot_id == null) {
Location bukkitLoc = simpleLocation.getBukkitLocation();
if (bukkitLoc == null) return;
String id = CustomCrops.getInstance().getPlatformInterface().getBlockID(bukkitLoc.getBlock());
pot_id = CustomCrops.getInstance().getPotManager().getPotKeyByBlockID(id);
if (pot_id == null) return;
}
Pot newPot = new Pot(pot_id, null, amount);
potMap.put(simpleLocation, newPot);
CustomCrops.getInstance().getScheduler().runTask(() -> changePotModel(simpleLocation, newPot));
changePotModel(simpleLocation, newPot);
}
public void addFertilizerToPot(SimpleLocation simpleLocation, Fertilizer fertilizer, @NotNull String pot_id) {
@@ -173,6 +166,7 @@ public class CCChunk implements Serializable {
public void scheduleSprinklerTask(CCWorld ccWorld, int force) {
Random randomGenerator = ThreadLocalRandom.current();
int delay = force == -1 ? ConfigManager.pointGainInterval * 1000 : force * 1000;
delay = Math.max(delay - 10000, 10000);
for (SimpleLocation simpleLocation : sprinklerMap.keySet()) {
ccWorld.pushSprinklerTask(simpleLocation, randomGenerator.nextInt(delay));
}
@@ -189,19 +183,20 @@ public class CCChunk implements Serializable {
public void changePotModel(SimpleLocation simpleLocation, Pot pot) {
Location location = simpleLocation.getBukkitLocation();
if (location == null) return;
if (CustomCrops.getInstance().getPlatformInterface().removeAnyBlock(location)) {
String replacer = pot.isWet() ? pot.getConfig().getWetPot(pot.getFertilizer()) : pot.getConfig().getDryPot(pot.getFertilizer());
if (ConfigUtils.isVanillaItem(replacer)) {
Block block = location.getBlock();
block.setType(Material.valueOf(replacer));
if (block.getBlockData() instanceof Farmland farmland && ConfigManager.disableMoistureMechanic) {
farmland.setMoisture(pot.isWet() ? farmland.getMaximumMoisture() : 0);
block.setBlockData(farmland);
}
}
else CustomCrops.getInstance().getPlatformInterface().placeNoteBlock(location, replacer);
} else {
if (!CustomCrops.getInstance().getPlatformInterface().removeAnyBlock(location)) {
CustomCrops.getInstance().getWorldDataManager().removePotData(simpleLocation);
return;
}
String replacer = pot.isWet() ? pot.getConfig().getWetPot(pot.getFertilizer()) : pot.getConfig().getDryPot(pot.getFertilizer());
if (ConfigUtils.isVanillaItem(replacer)) {
Block block = location.getBlock();
block.setType(Material.valueOf(replacer));
if (block.getBlockData() instanceof Farmland farmland && ConfigManager.disableMoistureMechanic) {
farmland.setMoisture(pot.isWet() ? farmland.getMaximumMoisture() : 0);
block.setBlockData(farmland);
}
} else {
CustomCrops.getInstance().getPlatformInterface().placeNoteBlock(location, replacer);
}
}
}

View File

@@ -18,7 +18,6 @@
package net.momirealms.customcrops.api.object.world;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.customplugin.PlatformInterface;
import net.momirealms.customcrops.api.object.Function;
import net.momirealms.customcrops.api.object.ItemMode;
import net.momirealms.customcrops.api.object.action.Action;
@@ -35,7 +34,6 @@ import net.momirealms.customcrops.api.object.fertilizer.SoilRetain;
import net.momirealms.customcrops.api.object.fertilizer.SpeedGrow;
import net.momirealms.customcrops.api.object.pot.Pot;
import net.momirealms.customcrops.api.object.pot.PotConfig;
import net.momirealms.customcrops.api.object.pot.PotManager;
import net.momirealms.customcrops.api.object.season.CCSeason;
import net.momirealms.customcrops.api.object.season.SeasonData;
import net.momirealms.customcrops.api.object.sprinkler.Sprinkler;
@@ -68,16 +66,24 @@ public class CCWorld extends Function {
private final Reference<World> world;
private final ConcurrentHashMap<ChunkCoordinate, CCChunk> chunkMap;
private final ScheduledThreadPoolExecutor schedule;
private long current_day;
private long currentDay;
private ScheduledFuture<?> timerTask;
private int pointTimer;
private int cacheTimer;
private int workCounter;
private int consumeCounter;
private final HashSet<SimpleLocation> plantToday;
private File chunks_folder;
private final HashSet<SimpleLocation> plantInPoint;
private final ConcurrentHashMap<SimpleLocation, String> corruptedPot;
private final File chunksFolder;
private final File dateFile;
private final File corruptedFile;
private final CustomCrops plugin;
public CCWorld(World world) {
public CCWorld(World world, CustomCrops plugin) {
this.plugin = plugin;
this.chunksFolder = ConfigUtils.getFile(world, "chunks");
this.dateFile = ConfigUtils.getFile(world, "data.yml");
this.corruptedFile = ConfigUtils.getFile(world, "corrupted.yml");
this.world = new WeakReference<>(world);
this.worldName = world.getName();
this.chunkMap = new ConcurrentHashMap<>(64);
@@ -85,13 +91,15 @@ public class CCWorld extends Function {
this.schedule.setMaximumPoolSize(ConfigManager.maxPoolSize);
this.schedule.setKeepAliveTime(ConfigManager.keepAliveTime, TimeUnit.SECONDS);
this.schedule.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
this.plantToday = new HashSet<>(128);
this.plantInPoint = new HashSet<>(128);
this.corruptedPot = new ConcurrentHashMap<>(128);
this.cacheTimer = ConfigManager.cacheSaveInterval;
}
@Override
public void init() {
loadDateData();
loadCorruptedPots();
if (!ConfigManager.onlyInLoadedChunks) {
loadAllChunkData();
}
@@ -101,15 +109,50 @@ public class CCWorld extends Function {
public void disable() {
closePool();
saveDateData();
saveCorruptedPots();
saveAllChunkData();
CustomCrops.getInstance().getSeasonManager().unloadSeasonData(worldName);
plugin.getSeasonManager().unloadSeasonData(worldName);
}
public void load() {
this.pointTimer = ConfigManager.pointGainInterval;
this.cacheTimer = ConfigManager.cacheSaveInterval;
this.consumeCounter = ConfigManager.intervalConsume;
this.workCounter = ConfigManager.intervalWork;
this.scheduleTask();
}
public void unload() {
if (this.timerTask != null) {
this.timerTask.cancel(false);
this.timerTask = null;
}
}
public void loadCorruptedPots() {
YamlConfiguration dataFile = ConfigUtils.readData(corruptedFile);
for (Map.Entry<String, Object> entry : dataFile.getValues(false).entrySet()) {
corruptedPot.put(SimpleLocation.getByString(entry.getKey(), worldName), (String) entry.getValue());
}
}
public void saveCorruptedPots() {
YamlConfiguration dataFile = new YamlConfiguration();
for (Map.Entry<SimpleLocation, String> entry : corruptedPot.entrySet()) {
SimpleLocation simpleLocation = entry.getKey();
dataFile.set(simpleLocation.getX() + "," + simpleLocation.getY() + "," + simpleLocation.getZ(), entry.getValue());
}
try {
dataFile.save(corruptedFile);
} catch (IOException e) {
AdventureUtils.consoleMessage("<red>[CustomCrops] Failed to save corrupted data for world: " + worldName);
}
}
@SuppressWarnings("ResultOfMethodCallIgnored")
public void loadAllChunkData() {
chunks_folder = ConfigUtils.getChunkFolder(worldName);
if (!chunks_folder.exists()) chunks_folder.mkdirs();
File[] data_files = chunks_folder.listFiles();
if (!chunksFolder.exists()) chunksFolder.mkdirs();
File[] data_files = chunksFolder.listFiles();
if (data_files == null) return;
List<File> outdated = new ArrayList<>();
for (File file : data_files) {
@@ -132,32 +175,13 @@ public class CCWorld extends Function {
}
}
public void loadDateData() {
YamlConfiguration dataFile;
if (ConfigManager.worldFolderPath.equals("")) {
dataFile = ConfigUtils.readData(new File(CustomCrops.getInstance().getDataFolder().getParentFile().getParentFile(), worldName + File.separator + "customcrops" + File.separator + "data.yml"));
} else {
dataFile = ConfigUtils.readData(new File(ConfigManager.worldFolderPath + worldName + File.separator + "customcrops" + File.separator + "data.yml"));
}
if (ConfigManager.enableSeason) {
SeasonData seasonData;
if (dataFile.contains("season") && dataFile.contains("date")) {
seasonData = new SeasonData(worldName, CCSeason.valueOf(dataFile.getString("season")), dataFile.getInt("date"));
} else {
seasonData = new SeasonData(worldName);
}
CustomCrops.getInstance().getSeasonManager().loadSeasonData(seasonData);
}
this.current_day = dataFile.getLong("day", 0);
}
@SuppressWarnings("ResultOfMethodCallIgnored")
public void saveAllChunkData() {
for (Map.Entry<ChunkCoordinate, CCChunk> entry : chunkMap.entrySet()) {
ChunkCoordinate chunkCoordinate = entry.getKey();
CCChunk chunk = entry.getValue();
String fileName = chunkCoordinate.getFileName() + ".ccdata";
File file = new File(chunks_folder, fileName);
File file = new File(chunksFolder, fileName);
if (chunk.isUseless() && file.exists()) {
file.delete();
continue;
@@ -173,7 +197,7 @@ public class CCWorld extends Function {
public void saveDateData() {
YamlConfiguration dataFile = new YamlConfiguration();
if (ConfigManager.enableSeason && !ConfigManager.rsHook) {
SeasonData seasonData = CustomCrops.getInstance().getSeasonManager().getSeasonData(worldName);
SeasonData seasonData = plugin.getSeasonManager().getSeasonData(worldName);
if (seasonData == null) {
dataFile.set("season", "SPRING");
dataFile.set("date", 1);
@@ -182,32 +206,31 @@ public class CCWorld extends Function {
dataFile.set("date", seasonData.getDate());
}
}
dataFile.set("day", current_day);
dataFile.set("day", currentDay);
try {
dataFile.save(new File(CustomCrops.getInstance().getDataFolder().getParentFile().getParentFile(), ConfigManager.worldFolderPath + worldName + File.separator + "customcrops" + File.separator + "data.yml"));
dataFile.save(dateFile);
} catch (IOException e) {
AdventureUtils.consoleMessage("<red>[CustomCrops] Failed to save season data for world: " + worldName);
}
}
public void load() {
this.pointTimer = ConfigManager.pointGainInterval;
this.cacheTimer = ConfigManager.cacheSaveInterval;
this.consumeCounter = ConfigManager.intervalConsume;
this.workCounter = ConfigManager.intervalWork;
this.scheduleTask();
}
public void unload() {
if (this.timerTask != null) {
this.timerTask.cancel(false);
this.timerTask = null;
public void loadDateData() {
YamlConfiguration dataFile = ConfigUtils.readData(dateFile);
if (ConfigManager.enableSeason) {
SeasonData seasonData;
if (dataFile.contains("season") && dataFile.contains("date")) {
seasonData = new SeasonData(worldName, CCSeason.valueOf(dataFile.getString("season")), dataFile.getInt("date"));
} else {
seasonData = new SeasonData(worldName);
}
plugin.getSeasonManager().loadSeasonData(seasonData);
}
this.currentDay = dataFile.getLong("day", 0);
}
private void scheduleTask() {
if (this.timerTask == null) {
this.timerTask = CustomCrops.getInstance().getScheduler().runTaskTimerAsync(() -> {
this.timerTask = plugin.getScheduler().runTaskTimerAsync(() -> {
World current = world.get();
if (current != null) {
if (ConfigManager.debug) {
@@ -227,10 +250,10 @@ public class CCWorld extends Function {
}
private void tryDayCycleTask(long time, long day) {
if (time < 100 && day != current_day) {
current_day = day;
if (time < 100 && day != currentDay) {
currentDay = day;
if (ConfigManager.enableSeason && !ConfigManager.rsHook && ConfigManager.autoSeasonChange) {
CustomCrops.getInstance().getSeasonManager().addDate(worldName);
plugin.getSeasonManager().addDate(worldName);
}
}
if (ConfigManager.cacheSaveInterval != -1) {
@@ -239,6 +262,7 @@ public class CCWorld extends Function {
if (ConfigManager.debug) Log.info("== Save cache ==");
cacheTimer = ConfigManager.cacheSaveInterval;
schedule.execute(this::saveDateData);
schedule.execute(this::saveCorruptedPots);
schedule.execute(this::saveAllChunkData);
}
}
@@ -255,7 +279,7 @@ public class CCWorld extends Function {
public void onReachPoint() {
if (ConfigManager.enableScheduleSystem) {
if (ConfigManager.debug) Log.info("== Grow point ==");
plantToday.clear();
plantInPoint.clear();
int size = schedule.getQueue().size();
if (size != 0) {
schedule.getQueue().clear();
@@ -264,14 +288,18 @@ public class CCWorld extends Function {
for (CCChunk chunk : chunkMap.values()) {
chunk.scheduleGrowTask(this, -1);
}
workCounter--;
consumeCounter--;
if (consumeCounter <= 0) {
if (workCounter > 0) {
workCounter--;
}
if (consumeCounter > 0) {
consumeCounter--;
}
if (consumeCounter == 0) {
consumeCounter = ConfigManager.intervalConsume;
if (ConfigManager.debug) Log.info("== Consume time ==");
scheduleConsumeTask(-1);
}
if (workCounter <= 0) {
if (workCounter == 0) {
workCounter = ConfigManager.intervalWork;
if (ConfigManager.debug) Log.info("== Work time ==");
scheduleSprinklerWork(-1);
@@ -285,9 +313,10 @@ public class CCWorld extends Function {
@SuppressWarnings("ResultOfMethodCallIgnored")
public void unloadChunk(ChunkCoordinate chunkCoordinate) {
if (!ConfigManager.onlyInLoadedChunks) return;
CCChunk chunk = chunkMap.remove(chunkCoordinate);
if (chunk != null) {
File file = new File(chunks_folder, chunkCoordinate.getFileName() + ".ccdata");
File file = new File(chunksFolder, chunkCoordinate.getFileName() + ".ccdata");
if (chunk.isUseless() && file.exists()) {
file.delete();
return;
@@ -302,7 +331,8 @@ public class CCWorld extends Function {
@SuppressWarnings("ResultOfMethodCallIgnored")
public void loadChunk(ChunkCoordinate chunkCoordinate) {
File file = new File(chunks_folder, chunkCoordinate.getFileName() + ".ccdata");
if (!ConfigManager.onlyInLoadedChunks) return;
File file = new File(chunksFolder, chunkCoordinate.getFileName() + ".ccdata");
if (file.exists()) {
boolean delete = false;
try (FileInputStream fis = new FileInputStream(file); ObjectInputStream ois = new ObjectInputStream(fis)) {
@@ -335,6 +365,46 @@ public class CCWorld extends Function {
schedule.schedule(new ConsumeCheckTask(simpleLocation), delay, TimeUnit.MILLISECONDS);
}
public String removeCorrupted(SimpleLocation simpleLocation) {
return corruptedPot.remove(simpleLocation);
}
public void fixCorruptedData() {
for (SimpleLocation simpleLocation : corruptedPot.keySet()) {
CustomCrops.getInstance().getScheduler().runTaskAsyncLater(new FixTask(simpleLocation), ThreadLocalRandom.current().nextInt(30000));
}
}
public class FixTask implements Runnable {
private final SimpleLocation simpleLocation;
public FixTask(SimpleLocation simpleLocation) {
this.simpleLocation = simpleLocation;
}
@Override
public void run() {
String key = corruptedPot.remove(simpleLocation);
PotConfig potConfig = plugin.getPotManager().getPotConfig(key);
if (potConfig == null) return;
Pot pot = getPotData(simpleLocation);
boolean wet = false;
Fertilizer fertilizer = null;
if (pot != null) {
wet = pot.isWet();
fertilizer = pot.getFertilizer();
}
Location location = simpleLocation.getBukkitLocation();
if (location == null) return;
String replacer = wet ? potConfig.getWetPot(fertilizer) : potConfig.getDryPot(fertilizer);
CompletableFuture<Chunk> asyncGetChunk = location.getWorld().getChunkAtAsync(location.getBlockX() >> 4, location.getBlockZ() >> 4);
asyncGetChunk.whenComplete((result, throwable) ->
plugin.getScheduler().runTask(() -> plugin.getPlatformInterface().placeNoteBlock(location, replacer)
));
}
}
public class ConsumeCheckTask implements Runnable {
private final SimpleLocation simpleLocation;
@@ -344,25 +414,39 @@ public class CCWorld extends Function {
}
public void run() {
Pot pot = getPotData(simpleLocation);
if (pot == null) return;
if (pot.isWet() && CustomCrops.getInstance().getFertilizerManager().getConfigByFertilizer(pot.getFertilizer()) instanceof SoilRetain soilRetain && soilRetain.canTakeEffect()) {
if (pot.isWet() && plugin.getFertilizerManager().getConfigByFertilizer(pot.getFertilizer()) instanceof SoilRetain soilRetain && soilRetain.canTakeEffect()) {
pot.setWater(pot.getWater() + 1);
}
if (pot.reduceWater() | pot.reduceFertilizer()) {
PotConfig potConfig = pot.getConfig();
Fertilizer fertilizer = pot.getFertilizer();
boolean wet = pot.isWet();
if (!wet && fertilizer == null) {
removePotData(simpleLocation);
}
Location location = simpleLocation.getBukkitLocation();
if (location == null) {
return;
}
CustomCrops.getInstance().getScheduler().runTask(() -> {
if (CustomCrops.getInstance().getPlatformInterface().removeAnyBlock(location)) {
PotConfig potConfig = pot.getConfig();
if (wet && fertilizer == null && !potConfig.isEnableFertilized()) {
return;
}
CompletableFuture<Chunk> asyncGetChunk = location.getWorld().getChunkAtAsync(location.getBlockX() >> 4, location.getBlockZ() >> 4);
asyncGetChunk.whenComplete((result, throwable) ->
plugin.getScheduler().runTask(() -> {
if (!plugin.getPlatformInterface().removeAnyBlock(location)) {
plugin.getWorldDataManager().removePotData(simpleLocation);
return;
}
String replacer = wet ? potConfig.getWetPot(fertilizer) : potConfig.getDryPot(fertilizer);
if (ConfigUtils.isVanillaItem(replacer)) {
Block block = location.getBlock();
@@ -372,12 +456,10 @@ public class CCWorld extends Function {
block.setBlockData(farmland);
}
} else {
CustomCrops.getInstance().getPlatformInterface().placeNoteBlock(location, replacer);
plugin.getPlatformInterface().placeNoteBlock(location, replacer);
}
} else {
CustomCrops.getInstance().getWorldDataManager().removePotData(SimpleLocation.getByBukkitLocation(location));
}
});
));
}
}
}
@@ -399,10 +481,11 @@ public class CCWorld extends Function {
removeSprinklerData(simpleLocation);
return;
}
int water = sprinkler.getWater();
if (water < 1) {
sprinkler.setWater(--water);
if (water <= 0) {
removeSprinklerData(simpleLocation);
return;
}
SprinklerAnimation sprinklerAnimation = sprinklerConfig.getSprinklerAnimation();
@@ -416,50 +499,91 @@ public class CCWorld extends Function {
}
}
sprinkler.setWater(--water);
if (water == 0) {
removeSprinklerData(simpleLocation);
}
int range = sprinklerConfig.getRange();
PlatformInterface platformInterface = CustomCrops.getInstance().getPlatformInterface();
PotManager potManager = CustomCrops.getInstance().getPotManager();
String[] whiteList = sprinklerConfig.getPotWhitelist();
int amount = sprinklerConfig.getWaterFillAbility();
if (whiteList == null) {
for (int i = -range; i <= range; i++) {
for (int j = -range; j <= range; j++) {
SimpleLocation potLoc = simpleLocation.add(i, -1, j);
Location bLoc = potLoc.getBukkitLocation();
if (bLoc != null) {
String blockID = platformInterface.getBlockID(potLoc.getBukkitLocation().getBlock());
String current_id = potManager.getPotKeyByBlockID(blockID);
if (current_id != null) {
addWaterToPot(potLoc, amount, current_id);
}
}
}
int random = sprinklerAnimation == null ? 10000 : sprinklerAnimation.duration() * 1000;
String[] whiteList = sprinklerConfig.getPotWhitelist();
for (int i = -range; i <= range; i++) {
for (int j = -range; j <= range; j++) {
SimpleLocation potSLoc = simpleLocation.add(i, -1, j);
schedule.schedule(new WaterPotTask(potSLoc, amount, whiteList), ThreadLocalRandom.current().nextInt(random), TimeUnit.MILLISECONDS);
}
} else {
for (int i = -range; i <= range; i++) {
outer:
for (int j = -range; j <= range; j++) {
SimpleLocation potLoc = simpleLocation.add(i, -1, j);
Location bLoc = potLoc.getBukkitLocation();
if (bLoc != null) {
String blockID = platformInterface.getBlockID(bLoc.getBlock());
String current_id = potManager.getPotKeyByBlockID(blockID);
if (current_id == null) continue;
for (String pot : whiteList) {
if (pot.equals(current_id)) {
addWaterToPot(potLoc, amount, current_id);
continue outer;
}
}
}
public class WaterPotTask implements Runnable {
@NotNull
private final SimpleLocation simpleLocation;
private final int amount;
@Nullable
private final String[] whitelist;
public WaterPotTask(@NotNull SimpleLocation simpleLocation, int amount, @Nullable String[] whitelist) {
this.simpleLocation = simpleLocation;
this.amount = amount;
this.whitelist = whitelist;
}
@Override
public void run() {
Location location = simpleLocation.getBukkitLocation();
if (location == null) return;
CompletableFuture<Chunk> asyncGetChunk = location.getWorld().getChunkAtAsync(location.getBlockX() >> 4, location.getBlockZ() >> 4);
asyncGetChunk.whenComplete((result, throwable) ->
plugin.getScheduler().runTask(() -> {
String blockID = plugin.getPlatformInterface().getBlockID(location.getBlock());
String potKey = plugin.getPotManager().getPotKeyByBlockID(blockID);
if (potKey != null) {
if (whitelist != null) {
for (String pot : whitelist) {
if (pot.equals(potKey)) {
addWaterToPot(simpleLocation, amount, potKey);
break;
}
}
} else {
addWaterToPot(simpleLocation, amount, potKey);
}
} else if (blockID.equals("NOTE_BLOCK")) {
// Only ItemsAdder can go to this step
Pot pot = getPotData(simpleLocation);
if (pot != null) {
// mark it as glitched
potKey = pot.getPotKey();
corruptedPot.put(simpleLocation, potKey);
if (ConfigManager.debug) AdventureUtils.consoleMessage("[CustomCrops] Trying to fix corrupted pot found at: " + simpleLocation);
if (whitelist == null) {
pot.addWater(amount);
} else {
for (String potID : whitelist) {
if (potID.equals(potKey)) {
pot.addWater(amount);
break;
}
}
}
// only custom blocks would corrupt
String replacer = pot.getConfig().getWetPot(pot.getFertilizer());
plugin.getPlatformInterface().placeNoteBlock(location, replacer);
} else {
potKey = corruptedPot.get(simpleLocation);
if (potKey != null) {
PotConfig potConfig = plugin.getPotManager().getPotConfig(potKey);
if (potConfig != null) {
String replacer = potConfig.getDryPot(null);
plugin.getPlatformInterface().placeNoteBlock(location, replacer);
} else {
corruptedPot.remove(simpleLocation);
}
}
}
}
}
}
));
}
}
@@ -503,9 +627,9 @@ public class CCWorld extends Function {
}
int points = 1;
Pot pot = CustomCrops.getInstance().getWorldDataManager().getPotData(simpleLocation.add(0,-1,0));
Pot pot = plugin.getWorldDataManager().getPotData(simpleLocation.add(0,-1,0));
if (pot != null) {
FertilizerConfig fertilizerConfig = CustomCrops.getInstance().getFertilizerManager().getConfigByFertilizer(pot.getFertilizer());
FertilizerConfig fertilizerConfig = plugin.getFertilizerManager().getConfigByFertilizer(pot.getFertilizer());
if (fertilizerConfig instanceof SpeedGrow speedGrow) {
points += speedGrow.getPointBonus();
}
@@ -564,9 +688,9 @@ public class CCWorld extends Function {
return chunk.isEntitiesLoaded();
});
loadEntities.whenComplete((result, throwable) ->
CustomCrops.getInstance().getScheduler().runTask(() -> {
if (CustomCrops.getInstance().getPlatformInterface().removeCustomItem(location, itemMode)) {
CustomCrops.getInstance().getPlatformInterface().placeCustomItem(location, finalNextModel, itemMode);
plugin.getScheduler().runTask(() -> {
if (plugin.getPlatformInterface().removeCustomItem(location, itemMode)) {
plugin.getPlatformInterface().placeCustomItem(location, finalNextModel, itemMode);
} else {
removeCropData(simpleLocation);
}
@@ -574,9 +698,9 @@ public class CCWorld extends Function {
}
else {
asyncGetChunk.whenComplete((result, throwable) ->
CustomCrops.getInstance().getScheduler().runTask(() -> {
if (CustomCrops.getInstance().getPlatformInterface().removeCustomItem(location, itemMode)) {
CustomCrops.getInstance().getPlatformInterface().placeCustomItem(location, finalNextModel, itemMode);
plugin.getScheduler().runTask(() -> {
if (plugin.getPlatformInterface().removeCustomItem(location, itemMode)) {
plugin.getPlatformInterface().placeCustomItem(location, finalNextModel, itemMode);
} else {
removeCropData(simpleLocation);
}
@@ -613,11 +737,11 @@ public class CCWorld extends Function {
}
private void growIfNotDuplicated(SimpleLocation simpleLocation) {
if (plantToday.contains(simpleLocation)) {
if (plantInPoint.contains(simpleLocation)) {
return;
}
pushCropTask(simpleLocation, ThreadLocalRandom.current().nextInt(ConfigManager.pointGainInterval * 1000));
plantToday.add(simpleLocation);
plantInPoint.add(simpleLocation);
}
public GrowingCrop getCropData(SimpleLocation simpleLocation) {
@@ -766,4 +890,9 @@ public class CCWorld extends Function {
}
});
}
@Nullable
public String getCorruptedPotOriginalKey(SimpleLocation simpleLocation) {
return corruptedPot.get(simpleLocation);
}
}

View File

@@ -17,7 +17,6 @@
package net.momirealms.customcrops.api.object.world;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
@@ -115,7 +114,7 @@ public class SimpleLocation implements Serializable {
}
public static SimpleLocation getByString(String location, String world) {
String[] loc = StringUtils.split(location, ",");
String[] loc = location.split(",");
return new SimpleLocation(world, Integer.parseInt(loc[0]), Integer.parseInt(loc[1]), Integer.parseInt(loc[2]));
}

View File

@@ -72,7 +72,7 @@ public class WorldDataManager extends Function {
public void loadWorld(World world) {
if (!isWorldAllowed(world)) return;
CCWorld ccWorld = new CCWorld(world);
CCWorld ccWorld = new CCWorld(world, plugin);
ccWorld.init();
ccWorld.load();
ccWorld.onReachPoint();
@@ -262,4 +262,28 @@ public class WorldDataManager extends Function {
ccWorld.unloadChunk(new ChunkCoordinate(chunk.getX(), chunk.getZ()));
}
}
@Nullable
public String getCorruptedPotOriginalKey(SimpleLocation simpleLocation) {
CCWorld ccWorld = worldMap.get(simpleLocation.getWorldName());
if (ccWorld != null) {
return ccWorld.getCorruptedPotOriginalKey(simpleLocation);
}
return null;
}
public String removeCorrupted(SimpleLocation simpleLocation) {
CCWorld ccWorld = worldMap.get(simpleLocation.getWorldName());
if (ccWorld != null) {
return ccWorld.removeCorrupted(simpleLocation);
}
return null;
}
public void fixCorruptedData(String world) {
CCWorld ccWorld = worldMap.get(world);
if (ccWorld != null) {
ccWorld.fixCorruptedData();
}
}
}

View File

@@ -17,7 +17,6 @@
package net.momirealms.customcrops.api.object.world;
import net.momirealms.customcrops.api.object.basic.ConfigManager;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.world.ChunkLoadEvent;
@@ -45,13 +44,12 @@ public class WorldListener implements Listener {
@EventHandler
public void onChunkLoad(ChunkLoadEvent event) {
if (!ConfigManager.onlyInLoadedChunks || event.isNewChunk()) return;
if (event.isNewChunk()) return;
worldManager.loadChunk(event.getChunk(), event.getWorld());
}
@EventHandler
public void onChunkUnload(ChunkUnloadEvent event) {
if (!ConfigManager.onlyInLoadedChunks) return;
worldManager.unloadChunk(event.getChunk(), event.getWorld());
}
}

View File

@@ -45,6 +45,7 @@ import net.momirealms.customcrops.api.object.requirement.*;
import net.momirealms.customcrops.api.object.season.CCSeason;
import net.momirealms.customcrops.helper.Log;
import org.bukkit.Particle;
import org.bukkit.World;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.MemorySection;
import org.bukkit.configuration.file.YamlConfiguration;
@@ -473,13 +474,23 @@ public class ConfigUtils {
return (a << 24) | (r << 16) | (g << 8) | b;
}
public static File getChunkFolder(String world) {
File chunks_folder;
public static File getFile(String world, String fileName) {
File file;
if (ConfigManager.worldFolderPath.equals("")) {
chunks_folder = new File(CustomCrops.getInstance().getDataFolder().getParentFile().getParentFile(), world + File.separator + "customcrops" + File.separator + "chunks");
file = new File(CustomCrops.getInstance().getDataFolder().getParentFile().getParentFile(), world + File.separator + "customcrops" + File.separator + fileName);
} else {
chunks_folder = new File(ConfigManager.worldFolderPath, world + File.separator + "customcrops" + File.separator + "chunks");
file = new File(ConfigManager.worldFolderPath, world + File.separator + "customcrops" + File.separator + fileName);
}
return chunks_folder;
return file;
}
public static File getFile(World world, String fileName) {
File file;
if (ConfigManager.worldFolderPath.equals("")) {
file = new File(world.getWorldFolder(), "customcrops" + File.separator + fileName);
} else {
file = new File(ConfigManager.worldFolderPath, world + File.separator + "customcrops" + File.separator + fileName);
}
return file;
}
}

View File

@@ -30,6 +30,7 @@ public class CustomCropsCommand extends AbstractMainCommand {
regSubCommand(ForceCommand.INSTANCE);
regSubCommand(MigrateCommand.INSTANCE);
regSubCommand(ConvertCommand.INSTANCE);
regSubCommand(FixCommand.INSTANCE);
// regSubCommand(CorruptionTest.INSTANCE);
// regSubCommand(PerformanceTest.INSTANCE);
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.command.subcmd;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.basic.MessageManager;
import net.momirealms.customcrops.api.util.AdventureUtils;
import net.momirealms.customcrops.command.AbstractSubCommand;
import org.bukkit.command.CommandSender;
import java.util.List;
public class FixCommand extends AbstractSubCommand {
public static final FixCommand INSTANCE = new FixCommand();
public FixCommand() {
super("fixcorrupted");
}
@Override
public boolean onCommand(CommandSender sender, List<String> args) {
if (lackArgs(sender, 1, args.size())) return true;
String world = args.get(0);
CustomCrops.getInstance().getWorldDataManager().fixCorruptedData(world);
AdventureUtils.sendMessage(sender, MessageManager.prefix + "Fixing would be ongoing in next 30s");
return true;
}
}

View File

@@ -29,7 +29,6 @@ import net.momirealms.customcrops.api.object.season.SeasonData;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
import net.momirealms.customcrops.api.util.AdventureUtils;
import net.momirealms.customcrops.command.AbstractSubCommand;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.YamlConfiguration;
@@ -123,7 +122,7 @@ public class MigrateCommand extends AbstractSubCommand {
JsonArray jsonArray = jsonObject.getAsJsonArray("pot");
for (JsonElement jsonElement : jsonArray) {
String loc = jsonElement.getAsString();
String[] locs = StringUtils.split(loc, ",");
String[] locs = loc.split(",");
SimpleLocation simpleLocation = new SimpleLocation(worldName, Integer.parseInt(locs[0]), Integer.parseInt(locs[1]), Integer.parseInt(locs[2]));
migrateWorld.addWaterToPot(simpleLocation, 1, "default");
}
@@ -136,7 +135,7 @@ public class MigrateCommand extends AbstractSubCommand {
YamlConfiguration data = YamlConfiguration.loadConfiguration(new File(ccDataFolder, "fertilizers.yml"));
for (String key : data.getKeys(false)) {
String[] loc = StringUtils.split(key, ",");
String[] loc = key.split(",");
SimpleLocation location = new SimpleLocation(worldName, Integer.parseInt(loc[0]), Integer.parseInt(loc[1]), Integer.parseInt(loc[2]));
String fertilizer = data.getString(key + ".type");
int times = data.getInt(key + ".times");
@@ -158,7 +157,7 @@ public class MigrateCommand extends AbstractSubCommand {
JsonArray jsonArray = en.getValue().getAsJsonArray();
int size = jsonArray.size();
for (int i = 0; i < size; i++) {
String[] loc = StringUtils.split(jsonArray.get(i).getAsString(), ",");
String[] loc = jsonArray.get(i).getAsString().split(",");
migrateWorld.addScarecrow(new SimpleLocation(worldName, Integer.parseInt(loc[0]), Integer.parseInt(loc[1]), Integer.parseInt(loc[2])));
}
}
@@ -177,7 +176,7 @@ public class MigrateCommand extends AbstractSubCommand {
String stageStr = crop.substring(crop.indexOf("_stage_") + 7);
int stage = Integer.parseInt(stageStr);
growingCrop = new GrowingCrop(crop.substring(0, crop.indexOf("_stage_")), stage);
String[] loc = StringUtils.split(entry.getKey(), ",");
String[] loc = entry.getKey().split(",");
SimpleLocation simpleLocation = new SimpleLocation(worldName, Integer.parseInt(loc[0]), Integer.parseInt(loc[1]), Integer.parseInt(loc[2]));
migrateWorld.addCropData(simpleLocation, growingCrop);
}

View File

@@ -28,7 +28,6 @@ package net.momirealms.customcrops.helper;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import net.momirealms.customcrops.CustomCrops;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.io.InputStream;
@@ -110,7 +109,7 @@ public final class LibraryLoader {
File serverDir = pluginDataFolder.getParentFile().getParentFile();
File helperDir = new File(serverDir, "libraries");
String[] split = StringUtils.split(dependency.groupId(), ".");
String[] split = dependency.groupId().split("\\.");
File jarDir;
StringJoiner stringJoiner = new StringJoiner(File.separator);
for (String str : split) {

View File

@@ -19,6 +19,7 @@ package net.momirealms.customcrops.integration.papi;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.basic.ConfigManager;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
@@ -26,7 +27,7 @@ import org.jetbrains.annotations.Nullable;
public class SeasonPapi extends PlaceholderExpansion {
private CustomCrops plugin;
private final CustomCrops plugin;
public SeasonPapi(CustomCrops plugin) {
this.plugin = plugin;
@@ -68,6 +69,11 @@ public class SeasonPapi extends PlaceholderExpansion {
if (online_player == null) return null;
return String.valueOf(plugin.getIntegrationManager().getSeasonInterface().getDate(player.getPlayer().getWorld().getName()));
}
case "daysleft" -> {
Player online_player = player.getPlayer();
if (online_player == null) return null;
return String.valueOf(1 + ConfigManager.seasonInterval - plugin.getIntegrationManager().getSeasonInterface().getDate(player.getPlayer().getWorld().getName()));
}
}
}
case 2 -> {
@@ -78,6 +84,9 @@ public class SeasonPapi extends PlaceholderExpansion {
case "date" -> {
return String.valueOf(plugin.getIntegrationManager().getSeasonInterface().getDate(split[1]));
}
case "daysleft" -> {
return String.valueOf(1 + ConfigManager.seasonInterval - plugin.getIntegrationManager().getSeasonInterface().getDate(split[1]));
}
}
}
}

View File

@@ -25,11 +25,12 @@ schedule-system:
enable: true
# The average interval for a crop to gain one point (measured in seconds)
# 平均每个农作物获得一生长点的时间间隔(秒)
point-gain-interval: 600
# Water amount and fertilizer would reduce every two points are gained
# As the default point-gain-interval is 600s, so here it would be 1200s(20min = a minecraft day)
# 默认每个生长点进行一次水分、肥料消耗/洒水器工作
consume-water-fertilizer-every-x-point: 2
point-gain-interval: 300
# Water amount and fertilizer would reduce every 4 points are gained
# set it to -1 if you don't want CustomCrops to control consumption/sprinkler tasks
# 默认每个生长点进行一次水分、肥料消耗/洒水器工作
# 设置为-1以禁用CustomCrops对水分、肥料消耗/洒水器任务的掌管
consume-water-fertilizer-every-x-point: 4
# Sprinkler would work every two points are gained
sprinkler-work-every-x-point: 2
# Save cache to file interval (seconds)
@@ -65,7 +66,7 @@ optimization:
mechanics:
# Does the system only work in loaded chunks (Requires you to stop the server before changing this setting)
# 插件是否只在加载中的区块工作 (需要关闭服务器再设置此项)
only-work-in-loaded-chunks: false
only-work-in-loaded-chunks: true
# 17/2/1 = 85%/10%/5%
# 2/2/1 = 40%/40%/20%
default-quality-ratio: 17/2/1
@@ -112,4 +113,6 @@ other-settings:
formula: '{base} + {level} * 0.01'
# MMOCore profession name
# MMOCore职业名
MMOCore-profession-name: 'farmer'
MMOCore-profession-name: 'farmer'
# Fixed corrupted pots when interacting
corrupt-fix-range: 4