9
0
mirror of https://github.com/Xiao-MoMi/Custom-Crops.git synced 2025-12-21 16:09:21 +00:00
This commit is contained in:
Xiao-MoMi
2022-08-02 16:02:53 +08:00
parent 3b02acf333
commit f3a09d94e0
18 changed files with 800 additions and 492 deletions

View File

@@ -58,13 +58,13 @@ public class ConfigReader {
}
public static void ReloadConfig(){
Sounds.loadSound();
Config.loadConfig();
Season.loadSeason();
Message.loadMessage();
Basic.loadBasic();
cropLoad();
fertilizerLoad();
Season.loadSeason();
Sounds.loadSound();
cropLoad();
}
public static class Config{
@@ -88,7 +88,7 @@ public class ConfigReader {
public static int timeToGrow;
public static int timeToWork;
public static boolean logTime;
public static boolean onlyLoadedGrow;
public static int growMode;
public static boolean quality;
public static boolean canAddWater;
public static boolean allWorld;
@@ -115,16 +115,16 @@ public class ConfigReader {
cropGrowTimeList = config.getLongList("config.grow-time");
cropGrowTimeList.forEach(time -> {
if(time < 0 || time > 23999){
AdventureManager.consoleMessage("<red>[CustomCrops] time should be between 0 and 23999");
AdventureManager.consoleMessage("<red>[CustomCrops] Grow time should be between 0 and 23999");
}
});
timeToGrow = config.getInt("config.time-to-grow",60)*20;
timeToWork = config.getInt("config.time-to-work",30)*20;
asyncCheck = config.getBoolean("config.async-time-check",false);
logTime = config.getBoolean("config.log-time-consume",false);
onlyLoadedGrow = !config.getBoolean("config.only-grow-in-loaded-chunks",true);
growMode = config.getInt("config.grow-mode",3);
if (growMode > 4 || growMode < 1) growMode = 3;
allWorld = config.getBoolean("config.all-world-grow",false);
hasParticle = config.getBoolean("config.water-particles", true);
rightClickHarvest = config.getBoolean("config.right-click-harvest", true);

View File

@@ -21,10 +21,7 @@ import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import net.momirealms.customcrops.commands.Executor;
import net.momirealms.customcrops.commands.Completer;
import net.momirealms.customcrops.datamanager.*;
import net.momirealms.customcrops.listener.BreakBlock;
import net.momirealms.customcrops.listener.InteractEntity;
import net.momirealms.customcrops.listener.ItemSpawn;
import net.momirealms.customcrops.listener.RightClick;
import net.momirealms.customcrops.listener.*;
import net.momirealms.customcrops.timer.CropTimer;
import net.momirealms.customcrops.utils.AdventureManager;
import net.momirealms.customcrops.utils.BackUp;
@@ -77,6 +74,8 @@ public final class CustomCrops extends JavaPlugin {
Bukkit.getPluginManager().registerEvents(new ItemSpawn(), this);
Bukkit.getPluginManager().registerEvents(new RightClick(), this);
Bukkit.getPluginManager().registerEvents(new BreakBlock(), this);
Bukkit.getPluginManager().registerEvents(new JoinAndQuit(), this);
Bukkit.getPluginManager().registerEvents(new BreakFurniture(), this);
Bukkit.getPluginManager().registerEvents(new InteractEntity(this), this);
if (ConfigReader.Season.enable){
@@ -103,6 +102,7 @@ public final class CustomCrops extends JavaPlugin {
if (this.cropManager != null){
this.cropManager.cleanData();
this.cropManager.updateData();
this.cropManager.saveData();
this.cropManager = null;
}
@@ -112,6 +112,7 @@ public final class CustomCrops extends JavaPlugin {
}
if (this.sprinklerManager != null){
this.sprinklerManager.cleanData();
this.sprinklerManager.updateData();
this.sprinklerManager.saveData();
this.sprinklerManager = null;
}

View File

@@ -67,7 +67,12 @@ public class Executor implements CommandExecutor {
return true;
}
Bukkit.getScheduler().runTaskAsynchronously(CustomCrops.instance, ()-> {
plugin.getCropManager().cropGrow(args[1]);
switch (ConfigReader.Config.growMode){
case 1 -> plugin.getCropManager().growModeOne(args[1]);
case 2 -> plugin.getCropManager().growModeTwo(args[1]);
case 3 -> plugin.getCropManager().growModeThree(args[1]);
case 4 -> plugin.getCropManager().growModeFour(args[1]);
}
});
if (sender instanceof Player player){
AdventureManager.playerMessage(player,ConfigReader.Message.prefix + ConfigReader.Message.forceGrow.replace("{world}",args[1]));
@@ -82,7 +87,12 @@ public class Executor implements CommandExecutor {
return true;
}
Bukkit.getScheduler().runTaskAsynchronously(CustomCrops.instance, ()-> {
plugin.getSprinklerManager().sprinklerWork(args[1]);
switch (ConfigReader.Config.growMode){
case 1 -> plugin.getSprinklerManager().workModeOne(args[1]);
case 2 -> plugin.getSprinklerManager().workModeTwo(args[1]);
case 3 -> plugin.getSprinklerManager().workModeThree(args[1]);
case 4 -> plugin.getSprinklerManager().workModeFour(args[1]);
}
});
if (sender instanceof Player player){
AdventureManager.playerMessage(player,ConfigReader.Message.prefix + ConfigReader.Message.forceWater.replace("{world}",args[1]));

View File

@@ -18,8 +18,8 @@
package net.momirealms.customcrops.datamanager;
import dev.lone.itemsadder.api.CustomBlock;
import dev.lone.itemsadder.api.CustomStack;
import net.momirealms.customcrops.fertilizer.QualityCrop;
import net.momirealms.customcrops.listener.JoinAndQuit;
import net.momirealms.customcrops.utils.AdventureManager;
import net.momirealms.customcrops.ConfigReader;
import net.momirealms.customcrops.CustomCrops;
@@ -37,8 +37,8 @@ import org.bukkit.scheduler.BukkitScheduler;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
@@ -83,7 +83,7 @@ public class CropManager {
}
/**
* 将hashmap中的数据保存到data中
* 将数据保存到data中
*/
public void updateData(){
Cache.forEach((location, String) -> {
@@ -108,139 +108,157 @@ public class CropManager {
}
/**
* 农作物生长
* 农作物生长Mode 1
* 仅加载区块生长
* @param worldName 进行生长判定的世界名
*/
public void cropGrow(String worldName){
public void growModeOne(String worldName){
Long time1 = System.currentTimeMillis();
updateData();
Long time2 = System.currentTimeMillis();
if(ConfigReader.Config.logTime){
AdventureManager.consoleMessage("性能监测: 农作物数据更新" + (time2-time1) + "ms");
if(!ConfigReader.Config.allWorld){
updateData();
}
Long time2 = System.currentTimeMillis();
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 农作物数据更新" + (time2-time1) + "ms");
if (data.contains(worldName)){
World world = Bukkit.getWorld(worldName);
data.getConfigurationSection(worldName).getKeys(false).forEach(chunk ->{
String[] split = StringUtils.split(chunk,",");
World world = Bukkit.getWorld(worldName);
if (ConfigReader.Config.onlyLoadedGrow || world.isChunkLoaded(Integer.parseInt(split[0]), Integer.parseInt(split[1]))){
if (world.isChunkLoaded(Integer.parseInt(split[0]), Integer.parseInt(split[1]))){
data.getConfigurationSection(worldName + "." + chunk).getValues(false).forEach((key, value) -> {
String[] coordinate = StringUtils.split(key, ",");
Location seedLocation = new Location(world,Double.parseDouble(coordinate[0]),Double.parseDouble(coordinate[1]),Double.parseDouble(coordinate[2]));
CustomBlock seedBlock = CustomBlock.byAlreadyPlaced(seedLocation.getBlock());
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(worldName).append(".").append(chunk).append(".").append(key);
if(seedBlock == null) {
data.set(stringBuilder.toString(), null);
return;
}
String namespacedID = seedBlock.getNamespacedID();
String id = seedBlock.getId();
if(namespacedID.equals(ConfigReader.Basic.dead)) {
data.set(stringBuilder.toString(), null);
return;
}
if(!namespacedID.contains("_stage_")) {
data.set(stringBuilder.toString(), null);
return;
}
Location potLocation = seedLocation.clone().subtract(0,1,0);
CustomBlock pot = CustomBlock.byAlreadyPlaced(potLocation.getBlock());
String potNamespacedID = pot.getNamespacedID();
String[] cropNameList = StringUtils.split(id,"_");
CropInstance cropInstance = ConfigReader.CROPS.get(cropNameList[0]);
if (pot == null || cropInstance == null){
data.set(stringBuilder.toString(), null);
return;
}
int random = new Random().nextInt(ConfigReader.Config.timeToGrow);
if (potNamespacedID.equals(ConfigReader.Basic.watered_pot)){
//如果启用季节限制且农作物有季节需求
if (ConfigReader.Season.enable && cropInstance.getSeasons() != null){
if (isWrongSeason(seedLocation, cropInstance.getSeasons(), worldName)){
data.set(stringBuilder.toString(), null);
bukkitScheduler.runTaskLater(CustomCrops.instance, () -> {
CustomBlock.remove(seedLocation);
CustomBlock.place(ConfigReader.Basic.dead, seedLocation);
}, random);
return;
}
}
int nextStage = Integer.parseInt(cropNameList[2]) + 1;
if (CustomBlock.getInstance(StringUtils.chop(namespacedID) + nextStage) != null && cropInstance.getGrowChance() > Math.random()) {
Fertilizer fertilizer = PotManager.Cache.get(SimpleLocation.fromLocation(potLocation));
if (fertilizer != null){
int times = fertilizer.getTimes();
if (times > 0){
fertilizer.setTimes(times - 1);
if (fertilizer instanceof SpeedGrow speedGrow){
if (Math.random() < speedGrow.getChance() && CustomBlock.getInstance(StringUtils.chop(namespacedID) + (nextStage + 1)) != null){
addStage(potLocation, seedLocation, namespacedID, nextStage + 1, random);
}else {
addStage(potLocation, seedLocation, namespacedID, nextStage, random);
}
}else if(fertilizer instanceof RetainingSoil retainingSoil){
if (Math.random() < retainingSoil.getChance()){
addStage(seedLocation, namespacedID, nextStage, random);
}else {
addStage(potLocation, seedLocation, namespacedID, nextStage, random);
}
}else if(fertilizer instanceof QualityCrop){
addStage(potLocation, seedLocation, namespacedID, nextStage, random);
}else {
AdventureManager.consoleMessage("<red>[CustomCrops] 发现未知类型肥料,已自动清除错误数据!</red>");
PotManager.Cache.remove(SimpleLocation.fromLocation(potLocation));
}
}else {
PotManager.Cache.remove(SimpleLocation.fromLocation(potLocation));
}
}
else {
addStage(potLocation, seedLocation, namespacedID, nextStage, random);
}
}
else if(cropInstance.getGiant() != null){
bukkitScheduler.runTaskLater(CustomCrops.instance, () ->{
CustomBlock.remove(potLocation);
CustomBlock.place(ConfigReader.Basic.pot, potLocation);
if(cropInstance.getGiantChance() > Math.random()){
data.set(stringBuilder.toString(), null);
CustomBlock.remove(seedLocation);
CustomBlock.place(cropInstance.getGiant(), seedLocation);
}
}, random);
}else {
if (!ConfigReader.Season.enable) data.set(stringBuilder.toString(), null);
bukkitScheduler.runTaskLater(CustomCrops.instance, () -> {
CustomBlock.remove(potLocation);
CustomBlock.place(ConfigReader.Basic.pot, potLocation);
}, random);
}
}else if(potNamespacedID.equals(ConfigReader.Basic.pot)){
if(!ConfigReader.Season.enable || cropInstance.getSeasons() == null) return;
if(isWrongSeason(seedLocation, cropInstance.getSeasons(), worldName)){
data.set(stringBuilder.toString(), null);
bukkitScheduler.runTaskLater(CustomCrops.instance, () -> {
CustomBlock.remove(seedLocation);
CustomBlock.place(ConfigReader.Basic.dead, seedLocation);
}, random);
}
}else {
data.set(stringBuilder.toString(), null);
if (growJudge(worldName, seedLocation)){
data.set(worldName + "." + chunk + "." + key, null);
}
});
}
});
}
Long time3 = System.currentTimeMillis();
if(ConfigReader.Config.logTime){
AdventureManager.consoleMessage("性能监测: 农作物生长过程" + (time3-time2) + "ms");
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 农作物生长过程" + (time3-time2) + "ms");
if(!ConfigReader.Config.allWorld){
saveData();
}
saveData();
Long time4 = System.currentTimeMillis();
if(ConfigReader.Config.logTime){
AdventureManager.consoleMessage("性能监测: 农作物数据保存" + (time4-time3) + "ms");
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 农作物数据保存" + (time4-time3) + "ms");
}
/**
* 农作物生长Mode 2
* 仅在线玩家的农作物生长
* @param worldName 进行生长判定的世界名
*/
public void growModeTwo(String worldName){
Long time1 = System.currentTimeMillis();
if(!ConfigReader.Config.allWorld){
updateData();
}
Long time2 = System.currentTimeMillis();
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 农作物数据更新" + (time2-time1) + "ms");
HashSet<String> players = new HashSet<>(JoinAndQuit.onlinePlayers);
if (data.contains(worldName)){
World world = Bukkit.getWorld(worldName);
data.getConfigurationSection(worldName).getKeys(false).forEach(chunk ->{
data.getConfigurationSection(worldName + "." + chunk).getValues(false).forEach((key, value) -> {
if (!players.contains(value)) return;
String[] coordinate = StringUtils.split(key, ",");
Location seedLocation = new Location(world,Double.parseDouble(coordinate[0]),Double.parseDouble(coordinate[1]),Double.parseDouble(coordinate[2]));
if (growJudge(worldName, seedLocation)){
data.set(worldName + "." + chunk + "." + key, null);
}
});
});
}
Long time3 = System.currentTimeMillis();
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 农作物生长过程" + (time3-time2) + "ms");
if(!ConfigReader.Config.allWorld){
saveData();
}
Long time4 = System.currentTimeMillis();
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 农作物数据保存" + (time4-time3) + "ms");
}
/**
* 农作物生长Mode 3
* 仅在线玩家和加载区块的农作物生长
* @param worldName 进行生长判定的世界名
*/
public void growModeThree(String worldName){
Long time1 = System.currentTimeMillis();
if(!ConfigReader.Config.allWorld){
updateData();
}
Long time2 = System.currentTimeMillis();
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 农作物数据更新" + (time2-time1) + "ms");
HashSet<String> players = new HashSet<>(JoinAndQuit.onlinePlayers);
if (data.contains(worldName)){
World world = Bukkit.getWorld(worldName);
data.getConfigurationSection(worldName).getKeys(false).forEach(chunk ->{
String[] split = StringUtils.split(chunk,",");
//区块被加载,则强行生长判定
if (world.isChunkLoaded(Integer.parseInt(split[0]), Integer.parseInt(split[1]))){
data.getConfigurationSection(worldName + "." + chunk).getValues(false).forEach((key, value) -> {
String[] coordinate = StringUtils.split(key, ",");
Location seedLocation = new Location(world,Double.parseDouble(coordinate[0]),Double.parseDouble(coordinate[1]),Double.parseDouble(coordinate[2]));
if (growJudge(worldName, seedLocation)){
data.set(worldName + "." + chunk + "." + key, null);
}
});
}
//区块未加载,玩家在线
else{
data.getConfigurationSection(worldName + "." + chunk).getValues(false).forEach((key, value) -> {
if (!players.contains(value)) return;
String[] coordinate = StringUtils.split(key, ",");
Location seedLocation = new Location(world,Double.parseDouble(coordinate[0]),Double.parseDouble(coordinate[1]),Double.parseDouble(coordinate[2]));
if (growJudge(worldName, seedLocation)){
data.set(worldName + "." + chunk + "." + key, null);
}
});
}
});
}
Long time3 = System.currentTimeMillis();
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 农作物生长过程" + (time3-time2) + "ms");
if(!ConfigReader.Config.allWorld){
saveData();
}
Long time4 = System.currentTimeMillis();
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 农作物数据保存" + (time4-time3) + "ms");
}
/**
* 农作物生长Mode 4
* 全部农作物生长
* @param worldName 进行生长判定的世界名
*/
public void growModeFour(String worldName){
Long time1 = System.currentTimeMillis();
if(!ConfigReader.Config.allWorld){
updateData();
}
Long time2 = System.currentTimeMillis();
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 农作物数据更新" + (time2-time1) + "ms");
if (data.contains(worldName)){
World world = Bukkit.getWorld(worldName);
data.getConfigurationSection(worldName).getKeys(false).forEach(chunk ->{
String[] split = StringUtils.split(chunk,",");
data.getConfigurationSection(worldName + "." + chunk).getValues(false).forEach((key, value) -> {
String[] coordinate = StringUtils.split(key, ",");
Location seedLocation = new Location(world,Double.parseDouble(coordinate[0]),Double.parseDouble(coordinate[1]),Double.parseDouble(coordinate[2]));
if (growJudge(worldName, seedLocation)){
data.set(worldName + "." + chunk + "." + key, null);
}
});
});
}
Long time3 = System.currentTimeMillis();
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 农作物生长过程" + (time3-time2) + "ms");
if(!ConfigReader.Config.allWorld){
saveData();
}
Long time4 = System.currentTimeMillis();
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 农作物数据保存" + (time4-time3) + "ms");
}
/**
@@ -248,135 +266,198 @@ public class CropManager {
* 对于使用动态加载世界的服务器有效
*/
public void cropGrowAll(){
Long time1 = System.currentTimeMillis();
updateData();
Long time2 = System.currentTimeMillis();
if(ConfigReader.Config.logTime){
AdventureManager.consoleMessage("性能监测: 农作物数据更新" + (time2-time1) + "ms");
}
Bukkit.getWorlds().forEach(world -> {
String worldName = world.getName();
if (data.contains(worldName)){
data.getConfigurationSection(worldName).getKeys(false).forEach(chunk ->{
String[] split = StringUtils.split(chunk,",");
if (ConfigReader.Config.onlyLoadedGrow || world.isChunkLoaded(Integer.parseInt(split[0]), Integer.parseInt(split[1]))){
data.getConfigurationSection(worldName + "." + chunk).getValues(false).forEach((key, value) -> {
String[] coordinate = StringUtils.split(key, ",");
Location seedLocation = new Location(world,Double.parseDouble(coordinate[0]),Double.parseDouble(coordinate[1]),Double.parseDouble(coordinate[2]));
CustomBlock seedBlock = CustomBlock.byAlreadyPlaced(seedLocation.getBlock());
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(worldName).append(".").append(chunk).append(".").append(key);
if(seedBlock == null) {
data.set(stringBuilder.toString(), null);
return;
}
String namespacedID = seedBlock.getNamespacedID();
String id = seedBlock.getId();
if(namespacedID.equals(ConfigReader.Basic.dead)) {
data.set(stringBuilder.toString(), null);
return;
}
if(!namespacedID.contains("_stage_")) {
data.set(stringBuilder.toString(), null);
return;
}
Location potLocation = seedLocation.clone().subtract(0,1,0);
CustomBlock pot = CustomBlock.byAlreadyPlaced(potLocation.getBlock());
String potNamespacedID = pot.getNamespacedID();
String[] cropNameList = StringUtils.split(id,"_");
CropInstance cropInstance = ConfigReader.CROPS.get(cropNameList[0]);
if (pot == null || cropInstance == null){
data.set(stringBuilder.toString(), null);
return;
}
int random = new Random().nextInt(ConfigReader.Config.timeToGrow);
if (potNamespacedID.equals(ConfigReader.Basic.watered_pot)){
if (ConfigReader.Season.enable && cropInstance.getSeasons() != null){
if (isWrongSeason(seedLocation, cropInstance.getSeasons(), worldName)){
data.set(stringBuilder.toString(), null);
bukkitScheduler.runTaskLater(CustomCrops.instance, () -> {
CustomBlock.remove(seedLocation);
CustomBlock.place(ConfigReader.Basic.dead, seedLocation);
}, random);
return;
}
}
int nextStage = Integer.parseInt(cropNameList[2]) + 1;
if (CustomBlock.getInstance(StringUtils.chop(namespacedID) + nextStage) != null && cropInstance.getGrowChance() > Math.random()) {
Fertilizer fertilizer = PotManager.Cache.get(SimpleLocation.fromLocation(potLocation));
if (fertilizer != null){
int times = fertilizer.getTimes();
if (times > 0){
fertilizer.setTimes(times - 1);
if (fertilizer instanceof SpeedGrow speedGrow){
if (Math.random() < speedGrow.getChance() && CustomBlock.getInstance(StringUtils.chop(namespacedID) + (nextStage + 1)) != null){
addStage(potLocation, seedLocation, namespacedID, nextStage + 1, random);
}else {
addStage(potLocation, seedLocation, namespacedID, nextStage, random);
}
}else if(fertilizer instanceof RetainingSoil retainingSoil){
if (Math.random() < retainingSoil.getChance()){
addStage(seedLocation, namespacedID, nextStage, random);
}else {
addStage(potLocation, seedLocation, namespacedID, nextStage, random);
}
}else if(fertilizer instanceof QualityCrop){
addStage(potLocation, seedLocation, namespacedID, nextStage, random);
}else {
AdventureManager.consoleMessage("<red>[CustomCrops] 发现未知类型肥料,已自动清除错误数据!</red>");
PotManager.Cache.remove(SimpleLocation.fromLocation(potLocation));
}
}else {
PotManager.Cache.remove(SimpleLocation.fromLocation(potLocation));
}
}
else {
addStage(potLocation, seedLocation, namespacedID, nextStage, random);
}
}
else if(cropInstance.getGiant() != null){
bukkitScheduler.runTaskLater(CustomCrops.instance, () ->{
CustomBlock.remove(potLocation);
CustomBlock.place(ConfigReader.Basic.pot, potLocation);
if(cropInstance.getGiantChance() > Math.random()){
data.set(stringBuilder.toString(), null);
CustomBlock.remove(seedLocation);
CustomBlock.place(cropInstance.getGiant(), seedLocation);
}
}, random);
}else {
if (!ConfigReader.Season.enable) data.set(stringBuilder.toString(), null);
bukkitScheduler.runTaskLater(CustomCrops.instance, () -> {
CustomBlock.remove(potLocation);
CustomBlock.place(ConfigReader.Basic.pot, potLocation);
}, random);
}
}else if(potNamespacedID.equals(ConfigReader.Basic.pot)){
if(!ConfigReader.Season.enable || cropInstance.getSeasons() == null) return;
if(isWrongSeason(seedLocation, cropInstance.getSeasons(), worldName)){
data.set(stringBuilder.toString(), null);
bukkitScheduler.runTaskLater(CustomCrops.instance, () -> {
CustomBlock.remove(seedLocation);
CustomBlock.place(ConfigReader.Basic.dead, seedLocation);
}, random);
}
}else {
data.set(stringBuilder.toString(), null);
}
});
}
});
}
});
Long time3 = System.currentTimeMillis();
if(ConfigReader.Config.logTime){
AdventureManager.consoleMessage("性能监测: 农作物生长过程" + (time3-time2) + "ms");
List<World> worlds = Bukkit.getWorlds();
for (int i = 0; i < worlds.size(); i++){
String worldName = worlds.get(i).getName();
bukkitScheduler.runTaskLaterAsynchronously(CustomCrops.instance, () -> {
switch (ConfigReader.Config.growMode){
case 1 -> growModeOne(worldName);
case 2 -> growModeTwo(worldName);
case 3 -> growModeThree(worldName);
case 4 -> growModeFour(worldName);
}
}, i * 40L);
}
saveData();
Long time4 = System.currentTimeMillis();
if(ConfigReader.Config.logTime){
AdventureManager.consoleMessage("性能监测: 农作物数据保存" + (time4-time3) + "ms");
}
/**
* 对某个位置进行生长判定
* @param worldName 世界名
* @param seedLocation 种子位置
* @return 是否消除数据
*/
private boolean growJudge(String worldName, Location seedLocation) {
CustomBlock seedBlock = CustomBlock.byAlreadyPlaced(seedLocation.getBlock());
//自定义农作物方块不存在
if(seedBlock == null) {
return true;
}
String namespacedID = seedBlock.getNamespacedID();
String id = seedBlock.getId();
//已死亡或不是农作物
if(namespacedID.equals(ConfigReader.Basic.dead) || !namespacedID.contains("_stage_")) {
return true;
}
//农作物下方自定义方块不存在
Location potLocation = seedLocation.clone().subtract(0,1,0);
CustomBlock pot = CustomBlock.byAlreadyPlaced(potLocation.getBlock());
if (pot == null){
return true;
}
//农作物实例不存在
String[] cropNameList = StringUtils.split(id,"_");
CropInstance cropInstance = ConfigReader.CROPS.get(cropNameList[0]);
if (cropInstance == null){
return true;
}
//获取自定义方块ID
String potNamespacedID = pot.getNamespacedID();
if (potNamespacedID.equals(ConfigReader.Basic.watered_pot)){
int random = new Random().nextInt(ConfigReader.Config.timeToGrow);
//如果启用季节限制且农作物有季节需求
if (ConfigReader.Season.enable && cropInstance.getSeasons() != null){
if (isWrongSeason(seedLocation, cropInstance.getSeasons(), worldName)){
bukkitScheduler.runTaskLater(CustomCrops.instance, () -> {
CustomBlock.remove(seedLocation);
CustomBlock.place(ConfigReader.Basic.dead, seedLocation);
}, random);
return true;
}
}
//获取下一阶段
int nextStage = Integer.parseInt(cropNameList[2]) + 1;
//下一阶段存在
if (CustomBlock.getInstance(StringUtils.chop(namespacedID) + nextStage) != null) {
//尝试获取肥料类型
Fertilizer fertilizer = PotManager.Cache.get(SimpleLocation.fromLocation(potLocation));
//有肥料
if (fertilizer != null){
//查询剩余使用次数
int times = fertilizer.getTimes();
if (times > 0){
fertilizer.setTimes(times - 1);
//生长激素
if (fertilizer instanceof SpeedGrow speedGrow){
if (cropInstance.getGrowChance() > Math.random()){
//农作物存在下两个阶段
if (Math.random() < speedGrow.getChance() && CustomBlock.getInstance(StringUtils.chop(namespacedID) + (nextStage + 1)) != null){
addStage(potLocation, seedLocation, namespacedID, nextStage + 1, random);
}else {
addStage(potLocation, seedLocation, namespacedID, nextStage, random);
}
}else {
notAddStage(potLocation, random);
}
}
//保湿土壤
else if(fertilizer instanceof RetainingSoil retainingSoil){
if (Math.random() < retainingSoil.getChance()){
if (cropInstance.getGrowChance() > Math.random()){
addStage(seedLocation, namespacedID, nextStage, random);
}
}else {
if (cropInstance.getGrowChance() > Math.random()){
addStage(potLocation, seedLocation, namespacedID, nextStage, random);
}else {
notAddStage(potLocation, random);
}
}
}
//品质肥料
else if(fertilizer instanceof QualityCrop){
if (cropInstance.getGrowChance() > Math.random()){
addStage(potLocation, seedLocation, namespacedID, nextStage, random);
}else {
notAddStage(potLocation, random);
}
}else {
//未知肥料类型处理
AdventureManager.consoleMessage("<red>[CustomCrops] Unknown fertilizer, Auto removed!</red>");
PotManager.Cache.remove(SimpleLocation.fromLocation(potLocation));
if (cropInstance.getGrowChance() > Math.random()){
addStage(potLocation, seedLocation, namespacedID, nextStage, random);
}else {
notAddStage(potLocation, random);
}
}
//肥料的最后一次使用
if (times == 1){
PotManager.Cache.remove(SimpleLocation.fromLocation(potLocation));
}
}
else {
//移除肥料信息,一般不会出现此情况
PotManager.Cache.remove(SimpleLocation.fromLocation(potLocation));
if (cropInstance.getGrowChance() > Math.random()){
addStage(potLocation, seedLocation, namespacedID, nextStage, random);
}else {
notAddStage(potLocation, random);
}
}
}
//没有肥料
else {
if (cropInstance.getGrowChance() > Math.random()){
addStage(potLocation, seedLocation, namespacedID, nextStage, random);
}else {
notAddStage(potLocation, random);
}
}
}
//农作物是否存在巨大化
else if(cropInstance.getGiant() != null){
//巨大化判定
if (cropInstance.getGiantChance() > Math.random()){
//成功巨大化,移除数据
bukkitScheduler.runTaskLater(CustomCrops.instance, () ->{
CustomBlock.remove(seedLocation);
CustomBlock.place(cropInstance.getGiant(), seedLocation);
CustomBlock.remove(potLocation);
CustomBlock.place(ConfigReader.Basic.pot, potLocation);
}, random);
return true;
}else {
//失败,转湿为干
bukkitScheduler.runTaskLater(CustomCrops.instance, () ->{
CustomBlock.remove(potLocation);
CustomBlock.place(ConfigReader.Basic.pot, potLocation);
}, random);
}
}else {
//若无下一阶段,无巨大化,未启用季节,则移除无用数据
if (!ConfigReader.Season.enable) return true;
bukkitScheduler.runTaskLater(CustomCrops.instance, () -> {
CustomBlock.remove(potLocation);
CustomBlock.place(ConfigReader.Basic.pot, potLocation);
}, random);
}
}
//干燥的种植盆
else if(potNamespacedID.equals(ConfigReader.Basic.pot)){
//未启用季节
if(!ConfigReader.Season.enable) return false;
//农作物无视季节
List<String> seasons = cropInstance.getSeasons();
if(seasons == null) return false;
//错误季节
if(isWrongSeason(seedLocation, seasons, worldName)){
bukkitScheduler.runTaskLater(CustomCrops.instance, () -> {
CustomBlock.remove(seedLocation);
CustomBlock.place(ConfigReader.Basic.dead, seedLocation);
}, new Random().nextInt(ConfigReader.Config.timeToGrow));
return true;
}
}
//不是种植盆
else {
return true;
}
return false;
}
/**
@@ -444,4 +525,16 @@ public class CropManager {
CustomBlock.place(stage, seedLocation);
}, random);
}
/**
* 停滞阶段(消耗水)
* @param potLocation 种植盆位置
* @param random 随机生长时间
*/
private void notAddStage(Location potLocation, int random){
bukkitScheduler.runTaskLater(CustomCrops.instance, () ->{
CustomBlock.remove(potLocation);
CustomBlock.place(ConfigReader.Basic.pot, potLocation);
}, random);
}
}

View File

@@ -1,7 +0,0 @@
package net.momirealms.customcrops.datamanager;
public class MushroomManager {
//A new feature coming
}

View File

@@ -18,10 +18,12 @@
package net.momirealms.customcrops.datamanager;
import dev.lone.itemsadder.api.CustomBlock;
import net.momirealms.customcrops.listener.JoinAndQuit;
import net.momirealms.customcrops.utils.AdventureManager;
import net.momirealms.customcrops.ConfigReader;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.utils.IAFurniture;
import net.momirealms.customcrops.utils.SimpleLocation;
import net.momirealms.customcrops.utils.Sprinkler;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit;
@@ -33,13 +35,19 @@ import org.bukkit.scheduler.BukkitScheduler;
import java.io.File;
import java.io.IOException;
import java.util.Random;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public class SprinklerManager {
public YamlConfiguration data;
public static ConcurrentHashMap<Location, Sprinkler> Cache = new ConcurrentHashMap<>();
public static ConcurrentHashMap<SimpleLocation, Sprinkler> Cache = new ConcurrentHashMap<>();
public static HashSet<SimpleLocation> RemoveCache = new HashSet<>();
private final BukkitScheduler bukkitScheduler;
public SprinklerManager(){
this.bukkitScheduler = Bukkit.getScheduler();
}
/**
* 载入数据
@@ -85,48 +93,55 @@ public class SprinklerManager {
}
/**
* 将hashmap中的数据保存到data中
* 将数据保存到data中
*/
public void updateData(){
Cache.forEach((location, sprinklerData) -> {
String world = location.getWorld().getName();
int x = location.getBlockX();
int z = location.getBlockZ();
StringBuilder stringBuilder = new StringBuilder().append(world).append(".").append(x/16).append(",").append(z/16).append(".").append(x).append(",").append(location.getBlockY()).append(",").append(z);
String world = location.getWorldName();
int x = location.getX();
int z = location.getZ();
StringBuilder stringBuilder = new StringBuilder().append(world).append(".").append(x/16).append(",").append(z/16).append(".").append(x).append(",").append(location.getY()).append(",").append(z);
data.set(stringBuilder+".range", sprinklerData.getRange());
data.set(stringBuilder+".water", sprinklerData.getWater());
data.set(stringBuilder+".player", Optional.ofNullable(sprinklerData.getPlayer()).orElse("none"));
});
Cache.clear();
HashSet<SimpleLocation> set = new HashSet<>(RemoveCache);
for (SimpleLocation location : set) {
String world = location.getWorldName();
int x = location.getX();
int z = location.getZ();
data.set(world + "." + x / 16 + "," + z / 16 + "." + x + "," + location.getY() + "," + z, null);
}
RemoveCache.clear();
}
/**
* 指定世界的洒水器工作
* 洒水器工作Mode 1
* @param worldName 世界名
*/
public void sprinklerWork(String worldName){
public void workModeOne(String worldName){
Long time1 = System.currentTimeMillis();
updateData();
Long time2 = System.currentTimeMillis();
if (ConfigReader.Config.logTime){
AdventureManager.consoleMessage("性能监测: 洒水器数据更新" + (time2-time1) + "ms");
if(!ConfigReader.Config.allWorld){
updateData();
}
Long time2 = System.currentTimeMillis();
if (ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 洒水器数据更新" + (time2-time1) + "ms");
if (data.contains(worldName)){
BukkitScheduler bukkitScheduler = Bukkit.getScheduler();
World world = Bukkit.getWorld(worldName);
data.getConfigurationSection(worldName).getKeys(false).forEach(chunk ->{
String[] split = StringUtils.split(chunk,",");
World world = Bukkit.getWorld(worldName);
if (ConfigReader.Config.onlyLoadedGrow || world.isChunkLoaded(Integer.parseInt(split[0]), Integer.parseInt(split[1]))) {
if (world.isChunkLoaded(Integer.parseInt(split[0]), Integer.parseInt(split[1]))) {
data.getConfigurationSection(worldName + "." + chunk).getValues(false).forEach((key, value) -> {
String[] coordinate = StringUtils.split(key, ",");
Location location = new Location(world,Double.parseDouble(coordinate[0])+0.5,Double.parseDouble(coordinate[1])+0.5,Double.parseDouble(coordinate[2])+0.5);
int random = new Random().nextInt(ConfigReader.Config.timeToWork);
if (value instanceof MemorySection map){
bukkitScheduler.callSyncMethod(CustomCrops.instance, ()->{
bukkitScheduler.runTask(CustomCrops.instance, ()->{
int water = (int) map.get("water");
int range = (int) map.get("range");
if(!IAFurniture.getFromLocation(location, world)){
data.set(worldName + "." + chunk + "." + key, null);
return null;
return;
}
if (water > 0){
data.set(worldName + "." + chunk + "." + key + ".water", water - 1);
@@ -136,10 +151,9 @@ public class SprinklerManager {
waterPot(location.clone().add(i,-1,j));
}
}
}, random);
}, new Random().nextInt(ConfigReader.Config.timeToWork));
}
if (range == 0) data.set(worldName + "." + chunk + "." + key, null);
return null;
});
}
});
@@ -147,73 +161,211 @@ public class SprinklerManager {
});
}
Long time3 = System.currentTimeMillis();
if(ConfigReader.Config.logTime){
AdventureManager.consoleMessage("性能监测: 洒水器工作过程" + (time3-time2) + "ms");
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 洒水器工作过程" + (time3-time2) + "ms");
if(!ConfigReader.Config.allWorld){
saveData();
}
saveData();
Long time4 = System.currentTimeMillis();
if(ConfigReader.Config.logTime){
AdventureManager.consoleMessage("性能监测: 洒水器数据保存" + (time4-time3) + "ms");
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 洒水器数据保存" + (time4-time3) + "ms");
}
/**
* 洒水器工作Mode 2
* @param worldName 世界名
*/
public void workModeTwo(String worldName){
Long time1 = System.currentTimeMillis();
if(!ConfigReader.Config.allWorld){
updateData();
}
Long time2 = System.currentTimeMillis();
if (ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 洒水器数据更新" + (time2-time1) + "ms");
HashSet<String> players = new HashSet<>(JoinAndQuit.onlinePlayers);
if (data.contains(worldName)){
World world = Bukkit.getWorld(worldName);
data.getConfigurationSection(worldName).getKeys(false).forEach(chunk ->{
data.getConfigurationSection(worldName + "." + chunk).getValues(false).forEach((key, value) -> {
if (value instanceof MemorySection map){
String player = (String) map.get("player");
if (player == null) {
data.set(worldName + "." + chunk + "." + key + ".player", "none");
return;
}
if (!players.contains(player)) return;
String[] coordinate = StringUtils.split(key, ",");
Location location = new Location(world,Double.parseDouble(coordinate[0])+0.5,Double.parseDouble(coordinate[1])+0.5,Double.parseDouble(coordinate[2])+0.5);
bukkitScheduler.callSyncMethod(CustomCrops.instance, ()->{
int water = (int) map.get("water");
int range = (int) map.get("range");
if (water > 0){
data.set(worldName + "." + chunk + "." + key + ".water", water - 1);
bukkitScheduler.runTaskLater(CustomCrops.instance, ()-> {
for(int i = -range; i <= range; i++){
for (int j = -range; j <= range; j++){
waterPot(location.clone().add(i,-1,j));
}
}
}, new Random().nextInt(ConfigReader.Config.timeToWork));
}
if (range == 0) data.set(worldName + "." + chunk + "." + key, null);
return null;
});
}
});
});
}
Long time3 = System.currentTimeMillis();
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 洒水器工作过程" + (time3-time2) + "ms");
if(!ConfigReader.Config.allWorld){
saveData();
}
Long time4 = System.currentTimeMillis();
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 洒水器数据保存" + (time4-time3) + "ms");
}
/**
* 洒水器工作Mode 3
* @param worldName 世界名
*/
public void workModeThree(String worldName){
Long time1 = System.currentTimeMillis();
if(!ConfigReader.Config.allWorld){
updateData();
}
Long time2 = System.currentTimeMillis();
if (ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 洒水器数据更新" + (time2-time1) + "ms");
HashSet<String> players = new HashSet<>(JoinAndQuit.onlinePlayers);
if (data.contains(worldName)){
World world = Bukkit.getWorld(worldName);
data.getConfigurationSection(worldName).getKeys(false).forEach(chunk ->{
String[] split = StringUtils.split(chunk,",");
if (world.isChunkLoaded(Integer.parseInt(split[0]), Integer.parseInt(split[1]))) {
data.getConfigurationSection(worldName + "." + chunk).getValues(false).forEach((key, value) -> {
String[] coordinate = StringUtils.split(key, ",");
Location location = new Location(world,Double.parseDouble(coordinate[0])+0.5,Double.parseDouble(coordinate[1])+0.5,Double.parseDouble(coordinate[2])+0.5);
if (value instanceof MemorySection map){
int water = (int) map.get("water");
int range = (int) map.get("range");
bukkitScheduler.runTask(CustomCrops.instance, ()->{
if(!IAFurniture.getFromLocation(location, world)){
data.set(worldName + "." + chunk + "." + key, null);
return;
}
if (water > 0){
data.set(worldName + "." + chunk + "." + key + ".water", water - 1);
bukkitScheduler.runTaskLater(CustomCrops.instance, ()-> {
for(int i = -range; i <= range; i++){
for (int j = -range; j <= range; j++){
waterPot(location.clone().add(i,-1,j));
}
}
}, new Random().nextInt(ConfigReader.Config.timeToWork));
}
if (range == 0) data.set(worldName + "." + chunk + "." + key, null);
});
}
});
}
else {
data.getConfigurationSection(worldName + "." + chunk).getValues(false).forEach((key, value) -> {
if (value instanceof MemorySection map){
String player = (String) map.get("player");
if (player == null) {
data.set(worldName + "." + chunk + "." + key + ".player", "none");
return;
}
if (!players.contains(player)) return;
String[] coordinate = StringUtils.split(key, ",");
Location location = new Location(world,Double.parseDouble(coordinate[0])+0.5,Double.parseDouble(coordinate[1])+0.5,Double.parseDouble(coordinate[2])+0.5);
int water = (int) map.get("water");
int range = (int) map.get("range");
if (water > 0){
data.set(worldName + "." + chunk + "." + key + ".water", water - 1);
bukkitScheduler.runTaskLater(CustomCrops.instance, ()-> {
for(int i = -range; i <= range; i++){
for (int j = -range; j <= range; j++){
waterPot(location.clone().add(i,-1,j));
}
}
}, new Random().nextInt(ConfigReader.Config.timeToWork));
}
if (range == 0) data.set(worldName + "." + chunk + "." + key, null);
}
});
}
});
}
Long time3 = System.currentTimeMillis();
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 洒水器工作过程" + (time3-time2) + "ms");
if(!ConfigReader.Config.allWorld){
saveData();
}
Long time4 = System.currentTimeMillis();
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 洒水器数据保存" + (time4-time3) + "ms");
}
/**
* 洒水器工作Mode 4
* @param worldName 世界名
*/
public void workModeFour(String worldName){
Long time1 = System.currentTimeMillis();
if(!ConfigReader.Config.allWorld){
updateData();
}
Long time2 = System.currentTimeMillis();
if (ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 洒水器数据更新" + (time2-time1) + "ms");
if (data.contains(worldName)){
World world = Bukkit.getWorld(worldName);
data.getConfigurationSection(worldName).getKeys(false).forEach(chunk ->{
data.getConfigurationSection(worldName + "." + chunk).getValues(false).forEach((key, value) -> {
String[] coordinate = StringUtils.split(key, ",");
Location location = new Location(world,Double.parseDouble(coordinate[0])+0.5,Double.parseDouble(coordinate[1])+0.5,Double.parseDouble(coordinate[2])+0.5);
if (value instanceof MemorySection map){
int water = (int) map.get("water");
int range = (int) map.get("range");
if (water > 0){
data.set(worldName + "." + chunk + "." + key + ".water", water - 1);
bukkitScheduler.runTaskLater(CustomCrops.instance, ()-> {
for(int i = -range; i <= range; i++){
for (int j = -range; j <= range; j++){
waterPot(location.clone().add(i,-1,j));
}
}
}, new Random().nextInt(ConfigReader.Config.timeToWork));
}
if (range == 0) data.set(worldName + "." + chunk + "." + key, null);
}
});
});
}
Long time3 = System.currentTimeMillis();
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 洒水器工作过程" + (time3-time2) + "ms");
if(!ConfigReader.Config.allWorld){
saveData();
}
Long time4 = System.currentTimeMillis();
if(ConfigReader.Config.logTime) AdventureManager.consoleMessage("性能监测: 洒水器数据保存" + (time4-time3) + "ms");
}
/**
* 所有世界的洒水器工作
*/
public void sprinklerWorkAll(){
Long time1 = System.currentTimeMillis();
updateData();
Long time2 = System.currentTimeMillis();
if (ConfigReader.Config.logTime){
AdventureManager.consoleMessage("性能监测: 洒水器数据更新" + (time2-time1) + "ms");
}
Bukkit.getWorlds().forEach(world -> {
String worldName = world.getName();
if (data.contains(worldName)){
BukkitScheduler bukkitScheduler = Bukkit.getScheduler();
data.getConfigurationSection(worldName).getKeys(false).forEach(chunk ->{
String[] split = StringUtils.split(chunk,",");
if (ConfigReader.Config.onlyLoadedGrow || world.isChunkLoaded(Integer.parseInt(split[0]), Integer.parseInt(split[1]))) {
data.getConfigurationSection(worldName + "." + chunk).getValues(false).forEach((key, value) -> {
String[] coordinate = StringUtils.split(key, ",");
Location location = new Location(world,Double.parseDouble(coordinate[0])+0.5,Double.parseDouble(coordinate[1])+0.5,Double.parseDouble(coordinate[2])+0.5);
int random = new Random().nextInt(ConfigReader.Config.timeToWork);
if (value instanceof MemorySection map){
bukkitScheduler.callSyncMethod(CustomCrops.instance, ()->{
int water = (int) map.get("water");
int range = (int) map.get("range");
if(!IAFurniture.getFromLocation(location, world)){
data.set(worldName + "." + chunk + "." + key, null);
return null;
}
if (water > 0){
data.set(worldName + "." + chunk + "." + key + ".water", water - 1);
bukkitScheduler.runTaskLater(CustomCrops.instance, ()-> {
for(int i = -range; i <= range; i++){
for (int j = -range; j <= range; j++){
waterPot(location.clone().add(i,-1,j));
}
}
}, random);
}
if (range == 0) data.set(worldName + "." + chunk + "." + key, null);
return null;
});
}
});
}
});
}
});
Long time3 = System.currentTimeMillis();
if(ConfigReader.Config.logTime){
AdventureManager.consoleMessage("性能监测: 洒水器工作过程" + (time3-time2) + "ms");
List<World> worlds = Bukkit.getWorlds();
for (int i = 0; i < worlds.size(); i++){
String worldName = worlds.get(i).getName();
bukkitScheduler.runTaskLaterAsynchronously(CustomCrops.instance, () -> {
switch (ConfigReader.Config.growMode){
case 1 -> workModeOne(worldName);
case 2 -> workModeTwo(worldName);
case 3 -> workModeThree(worldName);
case 4 -> workModeFour(worldName);
}
}, i * 40L);
}
saveData();
Long time4 = System.currentTimeMillis();
if(ConfigReader.Config.logTime){
AdventureManager.consoleMessage("性能监测: 洒水器数据保存" + (time4-time3) + "ms");
}
}
/**

View File

@@ -0,0 +1,23 @@
package net.momirealms.customcrops.listener;
import dev.lone.itemsadder.api.Events.FurnitureBreakEvent;
import net.momirealms.customcrops.ConfigReader;
import net.momirealms.customcrops.datamanager.SprinklerManager;
import net.momirealms.customcrops.utils.SimpleLocation;
import net.momirealms.customcrops.utils.Sprinkler;
import org.apache.commons.lang.StringUtils;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
public class BreakFurniture implements Listener {
@EventHandler
public void onBreakFurniture(FurnitureBreakEvent event){
Sprinkler config = ConfigReader.SPRINKLERS.get(StringUtils.split(event.getNamespacedID(),":")[1]);
if (config != null){
SimpleLocation simpleLocation = SimpleLocation.fromLocation(event.getBukkitEntity().getLocation());
SprinklerManager.Cache.remove(simpleLocation);
SprinklerManager.RemoveCache.add(simpleLocation);
}
}
}

View File

@@ -20,15 +20,15 @@ package net.momirealms.customcrops.listener;
import de.tr7zw.changeme.nbtapi.NBTCompound;
import de.tr7zw.changeme.nbtapi.NBTItem;
import dev.lone.itemsadder.api.CustomFurniture;
import dev.lone.itemsadder.api.Events.FurnitureBreakEvent;
import dev.lone.itemsadder.api.Events.FurnitureInteractEvent;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import net.momirealms.customcrops.ConfigReader;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.datamanager.SprinklerManager;
import net.momirealms.customcrops.utils.AdventureManager;
import net.momirealms.customcrops.utils.HoloUtil;
import net.momirealms.customcrops.utils.Sprinkler;
import net.momirealms.customcrops.utils.WateringCan;
import net.momirealms.customcrops.utils.*;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.ArmorStand;
@@ -54,106 +54,102 @@ public class InteractEntity implements Listener {
}
@EventHandler
public void onEntityInteract(PlayerInteractAtEntityEvent event){
Entity entity = event.getRightClicked();
if(entity instanceof ArmorStand armorStand){
if(CustomFurniture.byAlreadySpawned(armorStand) == null) return;
Sprinkler config = ConfigReader.SPRINKLERS.get(CustomFurniture.byAlreadySpawned(armorStand).getId());
if(config != null){
long time = System.currentTimeMillis();
Player player = event.getPlayer();
if (time - (coolDown.getOrDefault(player, time - 250)) < 250) {
return;
}
coolDown.put(player, time);
ItemStack itemStack = player.getInventory().getItemInMainHand();
Location location = armorStand.getLocation();
String world = location.getWorld().getName();
int x = location.getBlockX();
int z = location.getBlockZ();
int maxWater = config.getWater();
int currentWater = 0;
Location loc = location.clone().subtract(0,1,0).getBlock().getLocation().add(0,1,0);
Sprinkler sprinkler = SprinklerManager.Cache.get(loc);
if (itemStack.getType() == Material.WATER_BUCKET){
itemStack.setType(Material.BUCKET);
if (sprinkler != null){
currentWater = sprinkler.getWater();
currentWater += ConfigReader.Config.sprinklerRefill;
if (currentWater > maxWater){
currentWater = maxWater;
}
sprinkler.setWater(currentWater);
}else {
String path = world + "." + x / 16 + "," + z / 16 + "." + x + "," + location.getBlockY() + "," + z + ".water";
currentWater = plugin.getSprinklerManager().data.getInt(path);
currentWater += ConfigReader.Config.sprinklerRefill;
if (currentWater > maxWater){
currentWater = maxWater;
}
plugin.getSprinklerManager().data.set(path, currentWater);
public void onEntityInteract(FurnitureInteractEvent event){
Sprinkler config = ConfigReader.SPRINKLERS.get(StringUtils.split(event.getNamespacedID(),":")[1]);
if(config != null){
long time = System.currentTimeMillis();
Player player = event.getPlayer();
if (time - (coolDown.getOrDefault(player, time - 200)) < 200) {
return;
}
coolDown.put(player, time);
ItemStack itemStack = player.getInventory().getItemInMainHand();
Location location = event.getBukkitEntity().getLocation();
String world = location.getWorld().getName();
int x = location.getBlockX();
int z = location.getBlockZ();
int maxWater = config.getWater();
int currentWater = 0;
Location loc = location.clone().subtract(0,1,0).getBlock().getLocation().add(0,1,0);
Sprinkler sprinkler = SprinklerManager.Cache.get(SimpleLocation.fromLocation(loc));
if (itemStack.getType() == Material.WATER_BUCKET){
itemStack.setType(Material.BUCKET);
if (sprinkler != null){
currentWater = sprinkler.getWater();
currentWater += ConfigReader.Config.sprinklerRefill;
if (currentWater > maxWater){
currentWater = maxWater;
}
AdventureManager.playerSound(player, ConfigReader.Sounds.addWaterToSprinklerSource, ConfigReader.Sounds.addWaterToSprinklerKey);
sprinkler.setWater(currentWater);
}else {
String path = world + "." + x / 16 + "," + z / 16 + "." + x + "," + location.getBlockY() + "," + z + ".water";
currentWater = plugin.getSprinklerManager().data.getInt(path);
currentWater += ConfigReader.Config.sprinklerRefill;
if (currentWater > maxWater){
currentWater = maxWater;
}
plugin.getSprinklerManager().data.set(path, currentWater);
}
else {
if (ConfigReader.Config.canAddWater && itemStack.getType() != Material.AIR){
NBTItem nbtItem = new NBTItem(itemStack);
int water = nbtItem.getInteger("WaterAmount");
if (water > 0){
NBTCompound nbtCompound = nbtItem.getCompound("itemsadder");
if (nbtCompound != null) {
String id = nbtCompound.getString("id");
Optional<WateringCan> can = Optional.ofNullable(ConfigReader.CANS.get(id));
if (can.isPresent()) {
WateringCan wateringCan = can.get();
water--;
nbtItem.setInteger("WaterAmount", water);
AdventureManager.playerSound(player, ConfigReader.Sounds.addWaterToSprinklerSource, ConfigReader.Sounds.addWaterToSprinklerKey);
if (sprinkler != null){
currentWater = sprinkler.getWater();
currentWater++;
if (currentWater > maxWater){
currentWater = maxWater;
}
sprinkler.setWater(currentWater);
}else {
String path = world + "." + x / 16 + "," + z / 16 + "." + x + "," + location.getBlockY() + "," + z + ".water";
currentWater = plugin.getSprinklerManager().data.getInt(path);
currentWater++;
if (currentWater > maxWater){
currentWater = maxWater;
}
plugin.getSprinklerManager().data.set(path, currentWater);
AdventureManager.playerSound(player, ConfigReader.Sounds.addWaterToSprinklerSource, ConfigReader.Sounds.addWaterToSprinklerKey);
}
else {
if (ConfigReader.Config.canAddWater && itemStack.getType() != Material.AIR){
NBTItem nbtItem = new NBTItem(itemStack);
int water = nbtItem.getInteger("WaterAmount");
if (water > 0){
NBTCompound nbtCompound = nbtItem.getCompound("itemsadder");
if (nbtCompound != null) {
String id = nbtCompound.getString("id");
Optional<WateringCan> can = Optional.ofNullable(ConfigReader.CANS.get(id));
if (can.isPresent()) {
WateringCan wateringCan = can.get();
water--;
nbtItem.setInteger("WaterAmount", water);
AdventureManager.playerSound(player, ConfigReader.Sounds.addWaterToSprinklerSource, ConfigReader.Sounds.addWaterToSprinklerKey);
if (sprinkler != null){
currentWater = sprinkler.getWater();
currentWater++;
if (currentWater > maxWater){
currentWater = maxWater;
}
if (ConfigReader.Message.hasWaterInfo){
String string = ConfigReader.Message.waterLeft + ConfigReader.Message.waterFull.repeat(water) +
ConfigReader.Message.waterEmpty.repeat(wateringCan.getMax() - water) + ConfigReader.Message.waterRight;
AdventureManager.playerActionbar(player, string.replace("{max_water}", String.valueOf(wateringCan.getMax())).replace("{water}", String.valueOf(water)));
sprinkler.setWater(currentWater);
}else {
String path = world + "." + x / 16 + "," + z / 16 + "." + x + "," + location.getBlockY() + "," + z + ".water";
currentWater = plugin.getSprinklerManager().data.getInt(path);
currentWater++;
if (currentWater > maxWater){
currentWater = maxWater;
}
if (ConfigReader.Basic.hasWaterLore){
String string = (ConfigReader.Basic.waterLeft + ConfigReader.Basic.waterFull.repeat(water) +
ConfigReader.Basic.waterEmpty.repeat(wateringCan.getMax() - water) + ConfigReader.Basic.waterRight).replace("{max_water}", String.valueOf(wateringCan.getMax())).replace("{water}", String.valueOf(water));
List<String> lores = nbtItem.getCompound("display").getStringList("Lore");
lores.clear();
ConfigReader.Basic.waterLore.forEach(lore -> lores.add(GsonComponentSerializer.gson().serialize(MiniMessage.miniMessage().deserialize(lore.replace("{water_info}", string)))));
}
itemStack.setItemMeta(nbtItem.getItem().getItemMeta());
plugin.getSprinklerManager().data.set(path, currentWater);
}
if (ConfigReader.Message.hasWaterInfo){
String string = ConfigReader.Message.waterLeft + ConfigReader.Message.waterFull.repeat(water) +
ConfigReader.Message.waterEmpty.repeat(wateringCan.getMax() - water) + ConfigReader.Message.waterRight;
AdventureManager.playerActionbar(player, string.replace("{max_water}", String.valueOf(wateringCan.getMax())).replace("{water}", String.valueOf(water)));
}
if (ConfigReader.Basic.hasWaterLore){
String string = (ConfigReader.Basic.waterLeft + ConfigReader.Basic.waterFull.repeat(water) +
ConfigReader.Basic.waterEmpty.repeat(wateringCan.getMax() - water) + ConfigReader.Basic.waterRight).replace("{max_water}", String.valueOf(wateringCan.getMax())).replace("{water}", String.valueOf(water));
List<String> lores = nbtItem.getCompound("display").getStringList("Lore");
lores.clear();
ConfigReader.Basic.waterLore.forEach(lore -> lores.add(GsonComponentSerializer.gson().serialize(MiniMessage.miniMessage().deserialize(lore.replace("{water_info}", string)))));
}
itemStack.setItemMeta(nbtItem.getItem().getItemMeta());
}
}else {
currentWater = getCurrentWater(location, world, x, z, sprinkler);
}
}
else {
}else {
currentWater = getCurrentWater(location, world, x, z, sprinkler);
}
}
if (ConfigReader.Message.hasSprinklerInfo){
String string = ConfigReader.Message.sprinklerLeft + ConfigReader.Message.sprinklerFull.repeat(currentWater) +
ConfigReader.Message.sprinklerEmpty.repeat(maxWater - currentWater) + ConfigReader.Message.sprinklerRight;
if(HoloUtil.cache.get(location.add(0, ConfigReader.Message.sprinklerOffset,0)) == null) {
HoloUtil.showHolo(string.replace("{max_water}", String.valueOf(maxWater)).replace("{water}", String.valueOf(currentWater)), player, location, ConfigReader.Message.sprinklerTime);
}
else {
currentWater = getCurrentWater(location, world, x, z, sprinkler);
}
}
if (ConfigReader.Message.hasSprinklerInfo){
String string = ConfigReader.Message.sprinklerLeft + ConfigReader.Message.sprinklerFull.repeat(currentWater) +
ConfigReader.Message.sprinklerEmpty.repeat(maxWater - currentWater) + ConfigReader.Message.sprinklerRight;
if(HoloUtil.cache.get(location.add(0, ConfigReader.Message.sprinklerOffset,0)) == null) {
HoloUtil.showHolo(string.replace("{max_water}", String.valueOf(maxWater)).replace("{water}", String.valueOf(currentWater)), player, location, ConfigReader.Message.sprinklerTime);
}
}
}

View File

@@ -0,0 +1,23 @@
package net.momirealms.customcrops.listener;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import java.util.HashSet;
public class JoinAndQuit implements Listener {
public static HashSet<String> onlinePlayers = new HashSet<>();
@EventHandler
public void onJoin(PlayerJoinEvent event){
onlinePlayers.add(event.getPlayer().getName());
}
@EventHandler
public void onQuit(PlayerQuitEvent event){
onlinePlayers.remove(event.getPlayer().getName());
}
}

View File

@@ -138,7 +138,7 @@ public class RightClick implements Listener {
return;
}
itemStack.setAmount(itemStack.getAmount() - 1);
CropManager.Cache.put(location, cropName);
CropManager.Cache.put(location, player.getName());
CustomBlock.place((nbtCompound.getString("namespace") + ":" + cropName + "_stage_1"), location);
AdventureManager.playerSound(player, ConfigReader.Sounds.plantSeedSource, ConfigReader.Sounds.plantSeedKey);
return;
@@ -279,8 +279,11 @@ public class RightClick implements Listener {
return;
}
Sprinkler sprinklerData = new Sprinkler(sprinkler.getRange(), 0);
sprinklerData.setPlayer(player.getName());
itemStack.setAmount(itemStack.getAmount() - 1);
SprinklerManager.Cache.put(location.add(0,1,0), sprinklerData);
SimpleLocation simpleLocation = SimpleLocation.fromLocation(location.add(0,1,0));
SprinklerManager.Cache.put(simpleLocation, sprinklerData);
SprinklerManager.RemoveCache.remove(simpleLocation);
IAFurniture.placeFurniture(sprinkler.getNamespacedID_2(),location);
AdventureManager.playerSound(player, ConfigReader.Sounds.placeSprinklerSource, ConfigReader.Sounds.placeSprinklerKey);
return;
@@ -420,7 +423,7 @@ public class RightClick implements Listener {
AdventureManager.playerSound(player, ConfigReader.Sounds.harvestSource, ConfigReader.Sounds.harvestKey);
if(cropInstance.getReturnStage() != null){
CustomBlock.place(cropInstance.getReturnStage(), location);
CropManager.Cache.put(location, cropNameList[0]);
CropManager.Cache.put(location, player.getName());
}
}
}

View File

@@ -49,10 +49,20 @@ public class TimeCheck extends BukkitRunnable {
}, ConfigReader.Config.timeToGrow);
}else {
Bukkit.getScheduler().runTaskAsynchronously(CustomCrops.instance, () -> {
plugin.getCropManager().cropGrow(world.getName());
switch (ConfigReader.Config.growMode){
case 1 -> plugin.getCropManager().growModeOne(world.getName());
case 2 -> plugin.getCropManager().growModeTwo(world.getName());
case 3 -> plugin.getCropManager().growModeThree(world.getName());
case 4 -> plugin.getCropManager().growModeFour(world.getName());
}
});
Bukkit.getScheduler().runTaskLaterAsynchronously(CustomCrops.instance, ()->{
plugin.getSprinklerManager().sprinklerWork(world.getName());
switch (ConfigReader.Config.growMode){
case 1 -> plugin.getSprinklerManager().workModeOne(world.getName());
case 2 -> plugin.getSprinklerManager().workModeTwo(world.getName());
case 3 -> plugin.getSprinklerManager().workModeThree(world.getName());
case 4 -> plugin.getSprinklerManager().workModeFour(world.getName());
}
}, ConfigReader.Config.timeToGrow);
}
}

View File

@@ -37,6 +37,7 @@ public class IAFurniture {
/**
* 判断指定位置的盔甲架是不是洒水器
* 仅限加载中的区块
* @param location 位置
* @param world 世界
* @return 是/否

View File

@@ -21,6 +21,7 @@ public class Sprinkler {
private int water;
private int range;
private String player;
private String namespacedID_1;
private String namespacedID_2;
@@ -33,9 +34,11 @@ public class Sprinkler {
public String getNamespacedID_1() {return namespacedID_1;}
public String getNamespacedID_2() {return namespacedID_2;}
public int getRange() {return range;}
public String getPlayer() {return player;}
public void setRange(int range) {this.range = range;}
public void setNamespacedID_2(String namespacedID_2) {this.namespacedID_2 = namespacedID_2;}
public void setNamespacedID_1(String namespacedID_1) {this.namespacedID_1 = namespacedID_1;}
public void setWater(int water) {this.water = water;}
public void setPlayer(String player) {this.player = player;}
}

View File

@@ -1,3 +1,4 @@
#=============================================================#
#ItemsAdder items namespacedID
basic:
pot: customcrops:pot
@@ -5,7 +6,7 @@ basic:
greenhouse-glass: customcrops:greenhouse_glass
dead-crop: customcrops:crop_stage_death
soil-detector: customcrops:soil_detector
#=============================================================#
water-can:
watering_can_1:
item: customcrops:watering_can_1
@@ -29,7 +30,7 @@ water-can:
max: 6
width: 3
length: 5
#=============================================================#
lore:
#Should lore be changed when using watering-can
watering-can:
@@ -45,7 +46,7 @@ lore:
full: '뀁뀃'
empty: '뀁뀄'
right: '뀁뀅</font>'
#=============================================================#
sprinkler:
sprinkler_1:
range: 1
@@ -58,3 +59,4 @@ sprinkler:
max-water: 7
3Ditem: customcrops:sprinkler_2
2Ditem: customcrops:sprinkler_2_item
#=============================================================#

View File

@@ -1,7 +1,8 @@
config:
#=============================================================#
#english spanish chinese
lang: english
#=============================================================#
integration:
#integration to prevent other players' grief
Residence: false
@@ -16,31 +17,46 @@ config:
AureliumSkills: false
mcMMO: false
MMOCore: false
#=============================================================#
#Mode 1:
# Crops in loaded chunks will grow
#Mode 2:
# Online players' crops will grow
#Mode 3:
# Mode 1 + Mode 2
#Mode 4:
# No support in this mode!
# All the crops will grow (May cause lag)
grow-mode: 3
#The time to start growing(ticks)
#1000ticks is 7am in game. (0-23999)
#Sprinklers will work after all crops finish growing
grow-time:
- 1000
#Time in random a single crop need to growseconds
#This prevents a large amount of crops grow at the same time
#Large amount of block replacement would cause lag.
time-to-grow: 60
#Similar to "time-to-grow", this prevent all sprinklers work at the same time
time-to-work: 30
#Async Time Check (requires restart)
#Crops might not grow when using async.
#It is not really necessary to be Async
async-time-check: false
#Worlds where crops would grow
whitelist-worlds:
- world
#Should all the worlds' crops grow?
#This is useful for per player per world server.
#In this mode, whitelist world can only have one as the standard of time & season judgment.
all-world-grow: false
#=============================================================#
quality:
#If disabled, you need to configurate the loot in ItemsAdder config
enable: true
#Default ratio
default-ratio: 17/2/1
#Async Time Check (requires restart)
#Crops might not grow when using async.
#It is not really necessary to be Async
async-time-check: false
#=============================================================#
#Water Amount to refill when using water bucket
sprinkler-refill: 2
#Water Amount to refill with a sigle click to water block
@@ -49,11 +65,13 @@ config:
water-can-add-water-to-sprinkler: true
#Should particles be displayed when using watering can?
water-particles: true
#Worlds where crops would grow
whitelist-worlds:
- world
#=============================================================#
#Will bone meal accelerate the growth of crop
bone-meal:
enable: true
chance: 0.5
success-particle: VILLAGER_HAPPY
#=============================================================#
#Should we limit the max amount of crops and sprinkler in one chunk
#Recommended to enable because ItemsAdder might throw StackOverFlow
#when there are too many custom blocks in one chunk
@@ -61,38 +79,15 @@ config:
enable: true
crop: 64
sprinkler: 8
#Test performance
log-time-consume: false
#Defaultly crops will only grow in loaded chunks.
#If you want a mechanic similar to OriginRealms just DISABLE SEASON and REPEATED HARVESTING.
#In this way crops data will be removed from file when it comes to its final stage.
#In other words, plugin will only record the crops still on growing.
#NEVER SET "only-grow-in-loaded-chunks" FALSE IF YOU ARE USING THE FEATURES MENTIONED ABOVE.
#Otherwise it would be laggy because too many data in cache.
only-grow-in-loaded-chunks: true
#Should all the worlds' crops grow?
#This is useful for per player per world server.
#In this mode, whitelist world can only have one as the standard of time & season judgment.
all-world-grow: false
#=============================================================#
#can player harvest crops with right click?
#if set "false" crops can't be harvested repeatedly
right-click-harvest: true
#If "right-click-harvest" is true
#Should player be allowed to harvest with items in hand
harvest-with-empty-hand: true
#Should player be prevented from planting if wrong season
prevent-plant-if-wrong-season: true
#Should notify player of the wrong season?
should-notify-if-wrong-season: true
#Will bone meal accelerate the growth of crop
bone-meal:
enable: true
chance: 0.5
success-particle: VILLAGER_HAPPY
#=============================================================#

View File

@@ -27,7 +27,7 @@ speed:
times: 14
item: customcrops:speed_3
before-plant: true
#=============================================================#
#Pot have a small chance to retain its water after crops grow
retaining:
retaining_1:
@@ -50,7 +50,7 @@ retaining:
times: 28
item: customcrops:retaining_3
before-plant: false
#=============================================================#
#When haveresting, players have a higher chance to get high quality crops.
quality:
quality_1:
@@ -72,4 +72,5 @@ quality:
times: 28
chance: 2/2/1
item: customcrops:quality_3
before-plant: true
before-plant: true
#=============================================================#

View File

@@ -1,5 +1,6 @@
season:
#require a restart to apply
enable: true
auto-season-change:

View File

@@ -61,15 +61,16 @@ config:
#记录生长判断和洒水所需的时间(测试性能用)
log-time-consume: false
#是否只有加载中的区块农作物才会生长
#如果你不使用季节、可重复收获特性
#插件data只会记录正在生长中某个阶段的农作物数据
#生长到最后一阶段农作物生长数据就会清除
#那么可以尝试设置此值为false来让数据内全部农作物生长
#如果你使用上述特性中的任意一个请不要设置为false
#否则农作物生长到最后一阶段不会从数据中清除,过大的数据量
#可能会导致服务器严重卡顿
only-grow-in-loaded-chunks: true
#Mode 1:
# 加载中区块的农作物生长
#Mode 2:
# 在线玩家的农作物生长
#Mode 3:
# Mode 1 + Mode 2
#Mode 4:
# 所有农作物生长
# 可能会造成卡顿!不建议使用此模式
grow-mode: 3
#是否所有加载中的世界都要进行生长判断
#本选项适用于使用玩家独立世界的服务器