9
0
mirror of https://github.com/Xiao-MoMi/Custom-Crops.git synced 2025-12-22 00:19:24 +00:00
This commit is contained in:
Xiao-MoMi
2022-10-03 22:10:00 +08:00
parent 20d921d3e4
commit e185bff763
22 changed files with 530 additions and 207 deletions

View File

@@ -70,6 +70,9 @@ public final class CustomCrops extends JavaPlugin {
ConfigUtil.reloadConfigs();
if (MainConfig.cropMode) AdventureUtil.consoleMessage("[CustomCrops] Crop Mode: Tripwire");
else AdventureUtil.consoleMessage("[CustomCrops] Crop Mode: ItemFrame");
this.pluginCommand = new PluginCommand();
Objects.requireNonNull(Bukkit.getPluginCommand("customcrops")).setExecutor(pluginCommand);
Objects.requireNonNull(Bukkit.getPluginCommand("customcrops")).setTabCompleter(pluginCommand);

View File

@@ -36,6 +36,7 @@ public class FertilizerUseEvent extends PlayerEvent implements Cancellable {
super(who);
this.cancelled = false;
this.potLoc = potLoc;
this.fertilizer = fertilizer;
}
@Override

View File

@@ -33,6 +33,7 @@ public class WaterEvent extends PlayerEvent implements Cancellable {
public WaterEvent(@NotNull Player who, ItemStack itemStack) {
super(who);
this.cancelled = false;
this.itemStack = itemStack;
}
@Override

View File

@@ -1,7 +1,9 @@
package net.momirealms.customcrops.commands;
import net.momirealms.customcrops.config.MainConfig;
import net.momirealms.customcrops.config.MessageConfig;
import net.momirealms.customcrops.utils.AdventureUtil;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import java.util.ArrayList;
@@ -67,6 +69,17 @@ public abstract class AbstractSubCommand implements SubCommand {
subCommandMap.put(command.getSubCommand(), command);
}
public List<String> getWorlds(List<String> args) {
List<World> worlds = MainConfig.getWorldsList();
List<String> worldNames = new ArrayList<>();
for (World world : worlds) {
if (world.getName().startsWith(args.get(0))) {
worldNames.add(world.getName());
}
}
return worldNames;
}
public void setSubCommandMap(Map<String, SubCommand> subCommandMap) {
this.subCommandMap = subCommandMap;
}

View File

@@ -2,6 +2,7 @@ package net.momirealms.customcrops.commands;
import net.momirealms.customcrops.commands.subcmd.ReloadCommand;
import net.momirealms.customcrops.commands.subcmd.SetSeasonCommand;
import net.momirealms.customcrops.commands.subcmd.SimulateCommand;
import net.momirealms.customcrops.config.MessageConfig;
import net.momirealms.customcrops.utils.AdventureUtil;
import org.bukkit.command.Command;
@@ -40,6 +41,7 @@ public class PluginCommand implements TabExecutor {
private void regDefaultSubCommands() {
regSubCommand(ReloadCommand.INSTANCE);
regSubCommand(SetSeasonCommand.INSTANCE);
regSubCommand(SimulateCommand.INSTANCE);
}
public void regSubCommand(SubCommand executor) {

View File

@@ -15,14 +15,6 @@ public final class ReloadCommand extends AbstractSubCommand {
private ReloadCommand() {
super("reload", null);
regSubCommand(new AbstractSubCommand("config", null) {
@Override
public boolean onCommand(CommandSender sender, List<String> args) {
ConfigUtil.reloadConfigs();
AdventureUtil.sendMessage(sender, MessageConfig.prefix + MessageConfig.reload);
return true;
}
});
}
@Override

View File

@@ -10,6 +10,7 @@ import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import java.util.ArrayList;
import java.util.List;
public class SetSeasonCommand extends AbstractSubCommand {
@@ -18,14 +19,6 @@ public class SetSeasonCommand extends AbstractSubCommand {
public SetSeasonCommand() {
super("setseason", null);
regSubCommand(new AbstractSubCommand("config", null) {
@Override
public boolean onCommand(CommandSender sender, List<String> args) {
AdventureUtil.sendMessage(sender, MessageConfig.prefix + MessageConfig.setSeason);
return true;
}
});
}
@Override
@@ -54,12 +47,21 @@ public class SetSeasonCommand extends AbstractSubCommand {
return super.onCommand(sender, args);
}
public static void setSeason() {
MainConfig.load();
FertilizerConfig.load();
MessageConfig.load();
SeasonConfig.load();
SprinklerConfig.load();
WaterCanConfig.load();
@Override
public List<String> onTabComplete(CommandSender sender, List<String> args) {
if (args.size() == 1) {
return getWorlds(args);
}
if (args.size() == 2) {
List<String> seasons = List.of("Spring","Summer","Autumn","Winter");
List<String> seasonList = new ArrayList<>();
for (String season : seasons) {
if (season.startsWith(args.get(1))) {
seasonList.add(season);
}
}
return seasonList;
}
return super.onTabComplete(sender, args);
}
}

View File

@@ -0,0 +1,74 @@
package net.momirealms.customcrops.commands.subcmd;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.commands.AbstractSubCommand;
import net.momirealms.customcrops.commands.SubCommand;
import net.momirealms.customcrops.config.MessageConfig;
import net.momirealms.customcrops.utils.AdventureUtil;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import java.util.List;
public class SimulateCommand extends AbstractSubCommand {
public static final SubCommand INSTANCE = new SimulateCommand();
private SimulateCommand() {
super("simulate", null);
}
@Override
public boolean onCommand(CommandSender sender, List<String> args) {
if (args.size() < 4) {
AdventureUtil.sendMessage(sender, MessageConfig.prefix + MessageConfig.lackArgs);
}
else {
World world = Bukkit.getWorld(args.get(0));
if (world == null) {
AdventureUtil.sendMessage(sender, MessageConfig.prefix + MessageConfig.worldNotExists);
return true;
}
int sprinklerTime;
int growTime;
int dryTime;
try {
sprinklerTime = Integer.parseInt(args.get(1));
growTime = Integer.parseInt(args.get(3));
dryTime = Integer.parseInt(args.get(2));
if (sprinklerTime <= 0 || growTime <= 0 || dryTime <= 0 || (sprinklerTime + growTime + dryTime) > 23999) {
AdventureUtil.sendMessage(sender, MessageConfig.prefix + "Time should be a positive number between 1-23999");
return true;
}
}
catch (IllegalArgumentException e) {
AdventureUtil.sendMessage(sender, MessageConfig.prefix + "Time should be a positive number between 1-23999");
e.printStackTrace();
return true;
}
Bukkit.getScheduler().runTaskAsynchronously(CustomCrops.plugin, () -> {
CustomCrops.plugin.getCropManager().grow(world, growTime, sprinklerTime, dryTime);
});
AdventureUtil.sendMessage(sender, MessageConfig.prefix + MessageConfig.growSimulation);
}
return true;
}
@Override
public List<String> onTabComplete(CommandSender sender, List<String> args) {
if (args.size() == 1) {
return getWorlds(args);
}
if (args.size() == 2) {
return List.of("<SprinklerWorkTime>");
}
if (args.size() == 3) {
return List.of("<PotDryTime>");
}
if (args.size() == 4) {
return List.of("<CropGrowTime>");
}
return super.onTabComplete(sender, args);
}
}

View File

@@ -37,11 +37,10 @@ public class MainConfig {
public static World[] worlds;
public static List<World> worldList;
public static boolean whiteOrBlack;
public static boolean asyncTimeCheck;
public static String customPlugin;
public static boolean OraxenHook;
public static boolean realisticSeasonHook;
public static String cropMode;
public static boolean cropMode;
public static List<AntiGrief> antiGriefs;
public static SkillXP skillXP;
public static double dryGrowChance;
@@ -55,6 +54,8 @@ public class MainConfig {
public static int waterToWaterCan;
public static int wateringCanToSprinkler;
public static int timeToGrow;
public static int timeToWork;
public static int timeToDry;
public static String lang;
public static boolean preventInWrongSeason;
public static boolean notifyInWrongSeason;
@@ -79,6 +80,10 @@ public class MainConfig {
public static double fertilizerInfoY;
public static int fertilizerInfoDuration;
public static String fertilizerInfo;
public static boolean enableParticles;
public static boolean enableAnimations;
public static boolean autoGrow;
public static boolean enableCompensation;
public static void load() {
ConfigUtil.update("config.yml");
@@ -95,12 +100,18 @@ public class MainConfig {
}
}
worldList = List.of(worlds);
cropMode = config.getString("crops.mode", "tripwire");
asyncTimeCheck = config.getBoolean("optimization.async-time-check", false);
cropMode = config.getString("crops.mode", "tripwire").equals("tripwire");
limitation = config.getBoolean("optimization.limitation.enable", true);
wireAmount = config.getInt("optimization.limitation.tripwire-amount", 64);
frameAmount = config.getInt("optimization.limitation.itemframe-amount", 64);
autoGrow = config.getBoolean("mechanics.auto-grow.enable", true);
enableCompensation = config.getBoolean("mechanics.auto-grow.time-compensation", true);
timeToGrow = config.getInt("mechanics.auto-grow.crops-grow-time", 20000);
timeToWork = config.getInt("mechanics.auto-grow.sprinkler-work-time", 300);
timeToDry = config.getInt("mechanics.auto-grow.pot-dry-time", 200);
dryGrowChance = config.getDouble("mechanics.dry-pot-grow-chance", 0.5);
waterBucketToSprinkler = config.getInt("mechanics.fill.water-bucket-to-sprinkler", 3);
waterToWaterCan = config.getInt("mechanics.fill.waterblock-to-watering-can", 1);
wateringCanToSprinkler = config.getInt("mechanics.fill.watering-can-to-sprinkler", 1);
@@ -113,6 +124,9 @@ public class MainConfig {
enableBoneMeal = config.getBoolean("mechanics.bone-meal", true);
boneMealChance = config.getDouble("mechanics.chance", 0.5);
enableParticles = !config.getBoolean("optimization.disable-water-particles", false);
enableAnimations = !config.getBoolean("optimization.disable-sprinkler-animation", false);
try {
boneMealSuccess = Particle.valueOf(config.getString("mechanics.success-particle", "VILLAGER_HAPPY"));
}

View File

@@ -45,6 +45,7 @@ public class MessageConfig {
public static String noSeason;
public static String worldNotExists;
public static String seasonNotExists;
public static String wrongSeason;
public static void load() {
YamlConfiguration config = ConfigUtil.getConfig("messages" + File.separator + "messages_" + MainConfig.lang +".yml");
@@ -68,5 +69,6 @@ public class MessageConfig {
noSeason = config.getString("messages.no-season");
worldNotExists = config.getString("messages.world-not-exist");
seasonNotExists = config.getString("messages.season-not-exist");
wrongSeason = config.getString("messages.wrong-season");
}
}

View File

@@ -34,10 +34,7 @@ import net.momirealms.customcrops.utils.FurnitureUtil;
import net.momirealms.customcrops.utils.HologramUtil;
import net.momirealms.customcrops.utils.LimitationUtil;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.*;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
@@ -318,6 +315,11 @@ public abstract class HandlerP extends Function {
1,1
);
}
if (MainConfig.enableParticles) {
player.getWorld().spawnParticle(Particle.WATER_SPLASH, block.getLocation().add(0.5,1, 0.5),10,0.1,0.1,0.1);
}
}
break;
}
@@ -363,6 +365,10 @@ public abstract class HandlerP extends Function {
return true;
}
if (fertilizer.getParticle() != null) {
potLoc.getWorld().spawnParticle(fertilizer.getParticle(), potLoc.clone().add(0.5,1.1,0.5), 5,0.25,0.1,0.25, 0);
}
if (SoundConfig.useFertilizer.isEnable()) {
AdventureUtil.playerSound(
player,
@@ -373,7 +379,7 @@ public abstract class HandlerP extends Function {
}
if (player.getGameMode() != GameMode.CREATIVE) itemStack.setAmount(itemStack.getAmount() - 1);
customWorld.addFertilizer(potLoc, fertilizer);
customWorld.addFertilizer(potLoc, fertilizer.getWithTimes(fertilizer.getTimes()));
return true;
}
@@ -388,6 +394,7 @@ public abstract class HandlerP extends Function {
if (customWorld == null) return;
//remove fertilizer
customWorld.removeFertilizer(location);
customWorld.removeWatered(location);
}
public void onQuit(Player player) {
@@ -395,6 +402,10 @@ public abstract class HandlerP extends Function {
}
public void waterPot(int width, int length, Location location, float yaw){
//TODO
CustomWorld customWorld = cropManager.getCustomWorld(location.getWorld());
if (customWorld == null) return;
int extend = width / 2;
if (yaw < 45 && yaw > -135) {
if (yaw > -45) {
@@ -402,13 +413,8 @@ public abstract class HandlerP extends Function {
Location tempLoc = location.clone().add(i, 0, -1);
for (int j = 0; j < length; j++){
tempLoc.add(0,0,1);
String blockID = customInterface.getBlockID(tempLoc);
if(blockID != null){
if(blockID.equals(BasicItemConfig.dryPot)){
customInterface.removeBlock(tempLoc);
customInterface.placeNoteBlock(tempLoc, BasicItemConfig.wetPot);
}
}
customWorld.setPlayerWatered(tempLoc);
waterPot(tempLoc);
}
}
}
@@ -417,13 +423,8 @@ public abstract class HandlerP extends Function {
Location tempLoc = location.clone().add(-1, 0, i);
for (int j = 0; j < length; j++){
tempLoc.add(1,0,0);
String blockID = customInterface.getBlockID(tempLoc);
if(blockID != null){
if(blockID.equals(BasicItemConfig.dryPot)){
customInterface.removeBlock(tempLoc);
customInterface.placeNoteBlock(tempLoc, BasicItemConfig.wetPot);
}
}
customWorld.setPlayerWatered(tempLoc);
waterPot(tempLoc);
}
}
}
@@ -434,13 +435,8 @@ public abstract class HandlerP extends Function {
Location tempLoc = location.clone().add(1, 0, i);
for (int j = 0; j < length; j++){
tempLoc.subtract(1,0,0);
String blockID = customInterface.getBlockID(tempLoc);
if(blockID != null){
if(blockID.equals(BasicItemConfig.dryPot)){
customInterface.removeBlock(tempLoc);
customInterface.placeNoteBlock(tempLoc, BasicItemConfig.wetPot);
}
}
customWorld.setPlayerWatered(tempLoc);
waterPot(tempLoc);
}
}
}
@@ -449,14 +445,22 @@ public abstract class HandlerP extends Function {
Location tempLoc = location.clone().add(i, 0, 1);
for (int j = 0; j < length; j++){
tempLoc.subtract(0,0,1);
customWorld.setPlayerWatered(tempLoc);
waterPot(tempLoc);
}
}
}
}
}
private void waterPot(Location tempLoc) {
String blockID = customInterface.getBlockID(tempLoc);
if(blockID != null){
if(blockID.equals(BasicItemConfig.dryPot)){
customInterface.removeBlock(tempLoc);
customInterface.placeNoteBlock(tempLoc, BasicItemConfig.wetPot);
}
}
}
if (MainConfig.enableParticles) {
tempLoc.getWorld().spawnParticle(Particle.WATER_SPLASH, tempLoc.clone().add(0.5,1, 0.5),3,0.1,0.1,0.1);
}
}
}

View File

@@ -25,16 +25,20 @@ import dev.lone.itemsadder.api.Events.CustomBlockBreakEvent;
import dev.lone.itemsadder.api.Events.CustomBlockInteractEvent;
import dev.lone.itemsadder.api.Events.FurnitureBreakEvent;
import dev.lone.itemsadder.api.Events.FurnitureInteractEvent;
import net.kyori.adventure.key.Key;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.crop.Crop;
import net.momirealms.customcrops.api.event.WaterEvent;
import net.momirealms.customcrops.config.CropConfig;
import net.momirealms.customcrops.config.MainConfig;
import net.momirealms.customcrops.config.SoundConfig;
import net.momirealms.customcrops.config.WaterCanConfig;
import net.momirealms.customcrops.integrations.customplugin.HandlerP;
import net.momirealms.customcrops.integrations.customplugin.itemsadder.listeners.ItemsAdderBlockListener;
import net.momirealms.customcrops.integrations.customplugin.itemsadder.listeners.ItemsAdderFurnitureListener;
import net.momirealms.customcrops.managers.CropManager;
import net.momirealms.customcrops.objects.WaterCan;
import net.momirealms.customcrops.utils.AdventureUtil;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
@@ -82,7 +86,8 @@ public abstract class ItemsAdderHandler extends HandlerP {
if (action == Action.RIGHT_CLICK_BLOCK || action == Action.RIGHT_CLICK_AIR) {
Block block = event.getClickedBlock();
if (block != null && (block.getType().isInteractable() || block.getType() == Material.TRIPWIRE)) return;
if (block != null && ((block.getType().isInteractable() && block.getType() != Material.NOTE_BLOCK) || block.getType() == Material.TRIPWIRE)) return;
ItemStack item = event.getItem();
if (item == null || item.getType() == Material.AIR) return;
@@ -126,16 +131,11 @@ public abstract class ItemsAdderHandler extends HandlerP {
private boolean useWateringCan(Location potLoc, String namespacedID, Player player, @NotNull CustomStack can) {
WaterCan waterCan = WaterCanConfig.CANS.get(namespacedID);
if (waterCan == null) return false;
if (can.hasCustomDurability()) {
if (can.getDurability() > 0) {
can.setDurability(can.getDurability() - 1);
}
else return true;
}
NBTItem nbtItem = new NBTItem(can.getItemStack());
ItemStack itemStack = can.getItemStack();
NBTItem nbtItem = new NBTItem(itemStack);
int water = nbtItem.getInteger("WaterAmount");
if (water > 0) {
@@ -145,9 +145,49 @@ public abstract class ItemsAdderHandler extends HandlerP {
return true;
}
nbtItem.setInteger("WaterAmount", water - 1);
//TODO check
can.getItemStack().setItemMeta(nbtItem.getItem().getItemMeta());
NBTCompound nbtCompound = nbtItem.getCompound("itemsadder");
if (nbtCompound.hasKey("custom_durability")){
int dur = nbtCompound.getInteger("custom_durability");
int max_dur = nbtCompound.getInteger("max_custom_durability");
if (dur > 0){
nbtCompound.setInteger("custom_durability", dur - 1);
nbtCompound.setDouble("fake_durability", (int) itemStack.getType().getMaxDurability() * (double) (dur/max_dur));
nbtItem.setInteger("Damage", (int) (itemStack.getType().getMaxDurability() * (1 - (double) dur/max_dur)));
}
else {
AdventureUtil.playerSound(player, net.kyori.adventure.sound.Sound.Source.PLAYER, Key.key("minecraft:item.shield.break"), 1, 1);
itemStack.setAmount(itemStack.getAmount() - 1);
}
}
nbtItem.setInteger("WaterAmount", --water);
if (SoundConfig.waterPot.isEnable()) {
AdventureUtil.playerSound(
player,
SoundConfig.waterPot.getSource(),
SoundConfig.waterPot.getKey(),
1,1
);
}
if (MainConfig.enableActionBar) {
String canID = customInterface.getItemID(itemStack);
WaterCan canConfig = WaterCanConfig.CANS.get(canID);
if (canConfig == null) return true;
AdventureUtil.playerActionbar(
player,
(MainConfig.actionBarLeft +
MainConfig.actionBarFull.repeat(water) +
MainConfig.actionBarEmpty.repeat(canConfig.getMax() - water) +
MainConfig.actionBarRight)
.replace("{max_water}", String.valueOf(canConfig.getMax()))
.replace("{water}", String.valueOf(water))
);
}
itemStack.setItemMeta(nbtItem.getItem().getItemMeta());
super.waterPot(waterCan.width(), waterCan.getLength(), potLoc, player.getLocation().getYaw());
}

View File

@@ -29,6 +29,7 @@ import net.momirealms.customcrops.api.crop.Crop;
import net.momirealms.customcrops.api.event.SeedPlantEvent;
import net.momirealms.customcrops.config.*;
import net.momirealms.customcrops.integrations.AntiGrief;
import net.momirealms.customcrops.integrations.season.CCSeason;
import net.momirealms.customcrops.managers.CropManager;
import net.momirealms.customcrops.managers.CustomWorld;
import net.momirealms.customcrops.objects.Sprinkler;
@@ -104,10 +105,8 @@ public class ItemsAdderWireHandler extends ItemsAdderHandler {
final String blockID = cb.getNamespacedID();
//interact crop
if (blockID.contains("_stage_")) {
if (!blockID.equals(BasicItemConfig.deadCrop)) {
//ripe crops
if (!hasNextStage(blockID) && MainConfig.canRightClickHarvest) {
if (!blockID.equals(BasicItemConfig.deadCrop) && !hasNextStage(blockID) && MainConfig.canRightClickHarvest) {
if (MainConfig.emptyHand && event.hasItem()) return;
Location seedLoc = block.getLocation();
CustomBlock.remove(seedLoc);
@@ -119,7 +118,6 @@ public class ItemsAdderWireHandler extends ItemsAdderHandler {
super.tryMisc(player, event.getItem(), potLoc);
}
}
}
//interact pot (must have an item)
else if (blockID.equals(BasicItemConfig.wetPot) || blockID.equals(BasicItemConfig.dryPot)) {
@@ -162,6 +160,14 @@ public class ItemsAdderWireHandler extends ItemsAdderHandler {
return;
}
CCSeason[] seasons = crop.getSeasons();
if (seasons != null) {
if (cropManager.isWrongSeason(seedLoc, seasons)) {
if (MainConfig.notifyInWrongSeason) AdventureUtil.playerMessage(player, MessageConfig.prefix + MessageConfig.wrongSeason);
if (MainConfig.preventInWrongSeason) return;
}
}
SeedPlantEvent seedPlantEvent = new SeedPlantEvent(player, seedLoc, crop);
Bukkit.getPluginManager().callEvent(seedPlantEvent);
if (seedPlantEvent.isCancelled()) {

View File

@@ -46,7 +46,9 @@ import net.momirealms.customcrops.objects.QualityRatio;
import net.momirealms.customcrops.objects.actions.ActionInterface;
import net.momirealms.customcrops.objects.fertilizer.Fertilizer;
import net.momirealms.customcrops.objects.fertilizer.QualityCrop;
import net.momirealms.customcrops.objects.fertilizer.RetainingSoil;
import net.momirealms.customcrops.objects.fertilizer.YieldIncreasing;
import net.momirealms.customcrops.utils.AdventureUtil;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Location;
@@ -83,26 +85,26 @@ public class CropManager extends Function {
this.itemSpawnListener = new ItemSpawnListener(this);
this.worldListener = new WorldListener(this);
//new Time Check task
this.timerTask = new TimerTask(this);
if (MainConfig.asyncTimeCheck) this.timerTask.runTaskTimerAsynchronously(CustomCrops.plugin, 1, 100);
else this.timerTask.runTaskTimer(CustomCrops.plugin, 1,100);
//Crop mode
if (MainConfig.cropMode.equalsIgnoreCase("tripwire")) this.cropMode = new WireCropImpl(this);
else this.cropMode = new FrameCropImpl(this);
//Custom Plugin
if (MainConfig.customPlugin.equals("itemsadder")) {
customInterface = new ItemsAdderHook();
if (MainConfig.cropMode.equalsIgnoreCase("tripwire")) this.handler = new ItemsAdderWireHandler(this);
if (MainConfig.cropMode) this.handler = new ItemsAdderWireHandler(this);
else this.handler = new ItemsAdderFrameHandler(this);
}
else if (MainConfig.customPlugin.equals("oraxen")){
customInterface = new OraxenHook();
if (MainConfig.cropMode.equalsIgnoreCase("tripwire")) this.handler = new OraxenWireHandler(this);
if (MainConfig.cropMode) this.handler = new OraxenWireHandler(this);
else this.handler = new OraxenFrameHandler(this);
}
//Crop mode
if (MainConfig.cropMode) this.cropMode = new WireCropImpl(this);
else this.cropMode = new FrameCropImpl(this);
//new Time Check task
this.timerTask = new TimerTask(this);
this.timerTask.runTaskTimerAsynchronously(CustomCrops.plugin, 1,100);
handler.load();
if (SeasonConfig.enable) {
@@ -141,6 +143,11 @@ public class CropManager extends Function {
if (MainConfig.getWorldsList().contains(world)) {
CustomWorld customWorld = new CustomWorld(world, this);
customWorlds.put(world, customWorld);
if (MainConfig.autoGrow && MainConfig.enableCompensation) {
if (world.getTime() < 24000 - MainConfig.timeToWork - MainConfig.timeToDry - 1200 && world.getTime() > 1500) {
Bukkit.getScheduler().runTaskLaterAsynchronously(CustomCrops.plugin, () -> grow(world, MainConfig.timeToGrow, MainConfig.timeToWork, MainConfig.timeToDry), 100);
}
}
}
}
@@ -152,11 +159,11 @@ public class CropManager extends Function {
seasonInterface.unloadWorld(world);
}
public void grow(World world, int time) {
public void grow(World world, int cropTime, int sprinklerTime, int dryTime) {
CustomWorld customWorld = customWorlds.get(world);
if (customWorld == null) return;
if (MainConfig.cropMode.equals("tripwire")) customWorld.growWire(time);
else customWorld.growFrame(time);
if (MainConfig.cropMode) customWorld.growWire(cropTime, sprinklerTime, dryTime);
else customWorld.growFrame(cropTime, sprinklerTime, dryTime);
}
public CropModeInterface getCropMode() {
@@ -199,15 +206,18 @@ public class CropManager extends Function {
public void potDryJudge(Location potLoc) {
World world = potLoc.getWorld();
CustomWorld customWorld = customWorlds.get(world);
if (customWorld == null) {
if (customWorld == null) return;
if (!customWorld.isPotWet(potLoc)) {
makePotDry(potLoc);
return;
}
else if (!customWorld.isPotWet(potLoc)) {
Fertilizer fertilizer = customWorld.getFertilizer(potLoc);
if (!(fertilizer instanceof RetainingSoil retainingSoil && Math.random() < retainingSoil.getChance())) {
makePotDry(potLoc);
}
}
private void makePotDry(Location potLoc) {
public void makePotDry(Location potLoc) {
customInterface.removeBlock(potLoc);
customInterface.placeNoteBlock(potLoc, BasicItemConfig.dryPot);
}
@@ -216,8 +226,10 @@ public class CropManager extends Function {
String potID = customInterface.getBlockID(potLoc);
if (potID == null) return;
if (!potID.equals(BasicItemConfig.dryPot)) return;
Bukkit.getScheduler().runTask(CustomCrops.plugin, () -> {
customInterface.removeBlock(potLoc);
customInterface.placeNoteBlock(potLoc, BasicItemConfig.wetPot);
});
}
@Nullable

View File

@@ -17,6 +17,11 @@
package net.momirealms.customcrops.managers;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.stream.JsonReader;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.event.CustomWorldEvent;
import net.momirealms.customcrops.config.ConfigUtil;
@@ -34,11 +39,12 @@ import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.io.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
@@ -49,19 +55,28 @@ public class CustomWorld {
private final ConcurrentHashMap<SimpleLocation, Sprinkler> sprinklerCache;
private final ConcurrentHashMap<SimpleLocation, Fertilizer> fertilizerCache;
private final Set<SimpleLocation> watered;
private HashSet<SimpleLocation> tempWatered;
private final HashSet<SimpleLocation> playerWatered;
private final CropManager cropManager;
private final HashSet<BukkitTask> tasksCache;
private final BukkitScheduler bukkitScheduler;
public CustomWorld(World world, CropManager cropManager) {
this.world = world;
this.cropCache = new ConcurrentHashMap<>(4096);
this.fertilizerCache = new ConcurrentHashMap<>(2048);
this.sprinklerCache = new ConcurrentHashMap<>(1024);
this.tasksCache = new HashSet<>(4096);
this.cropManager = cropManager;
this.bukkitScheduler = Bukkit.getScheduler();
this.watered = Collections.synchronizedSet(new HashSet<>());
this.playerWatered = new HashSet<>();
this.tempWatered = new HashSet<>();
Bukkit.getScheduler().runTaskAsynchronously(CustomCrops.plugin, () -> {
loadCropCache();
loadSprinklerCache();
loadFertilizerCache();
loadPot();
Bukkit.getScheduler().runTask(CustomCrops.plugin, () -> {
CustomWorldEvent customWorldEvent = new CustomWorldEvent(world, WorldState.LOAD);
Bukkit.getPluginManager().callEvent(customWorldEvent);
@@ -74,12 +89,18 @@ public class CustomWorld {
unloadCrop();
unloadSprinkler();
unloadFertilizer();
unloadPot();
}
else {
Bukkit.getScheduler().runTaskAsynchronously(CustomCrops.plugin, () -> {
unloadCrop();
unloadSprinkler();
unloadFertilizer();
unloadPot();
for (BukkitTask task : tasksCache) {
task.cancel();
}
tasksCache.clear();
Bukkit.getScheduler().runTask(CustomCrops.plugin, () -> {
CustomWorldEvent customWorldEvent = new CustomWorldEvent(world, WorldState.UNLOAD);
Bukkit.getPluginManager().callEvent(customWorldEvent);
@@ -88,6 +109,44 @@ public class CustomWorld {
}
}
public void loadPot() {
try {
JsonParser jsonParser = new JsonParser();
JsonElement json= jsonParser.parse(new FileReader(new File(CustomCrops.plugin.getDataFolder().getParentFile().getParentFile(), world.getName() + File.separator + "customcrops_data" + File.separator + "pot.json")));
if (json.isJsonObject()) {
JsonObject jsonObject = json.getAsJsonObject();
if (jsonObject.has("pot")) {
JsonArray jsonArray = jsonObject.getAsJsonArray("pot");
String name = world.getName();
for (JsonElement jsonElement : jsonArray) {
String loc = jsonElement.getAsString();
String[] locs = StringUtils.split(loc, ",");
watered.add(new SimpleLocation(name, Integer.parseInt(locs[0]), Integer.parseInt(locs[1]), Integer.parseInt(locs[2])));
}
}
}
}
catch (FileNotFoundException e) {
//bypass
}
}
public void unloadPot() {
JsonObject jsonObject = new JsonObject();
JsonArray jsonArray = new JsonArray();
watered.addAll(playerWatered);
for (SimpleLocation simpleLocation : watered) {
jsonArray.add(simpleLocation.getX() + "," + simpleLocation.getY() + "," + simpleLocation.getZ());
}
watered.clear();
jsonObject.add("pot", jsonArray);
try (FileWriter fileWriter = new FileWriter(new File(CustomCrops.plugin.getDataFolder().getParentFile().getParentFile(), world.getName() + File.separator + "customcrops_data" + File.separator + "pot.json"))){
fileWriter.write(jsonObject.toString().replace("\\\\", "\\"));
} catch (IOException e) {
e.printStackTrace();
}
}
private void loadFertilizerCache() {
YamlConfiguration data = loadData("fertilizers", world.getName());
for (String key : data.getKeys(false)) {
@@ -181,51 +240,89 @@ public class CustomWorld {
}
}
public void growWire(int time) {
BukkitScheduler bukkitScheduler = Bukkit.getScheduler();
public void growWire(int cropTime, int sprinklerTime, int dryTime) {
route(sprinklerTime);
Random randomGenerator = new Random();
CropModeInterface cropMode = cropManager.getCropMode();
bukkitScheduler.runTaskAsynchronously(CustomCrops.plugin, () -> {
route();
tempWatered.removeAll(watered);
for (SimpleLocation simpleLocation : tempWatered) {
bukkitScheduler.runTaskLater(CustomCrops.plugin, () -> {
Location dryLoc = MiscUtils.getLocation(simpleLocation);
if (dryLoc == null) return;
cropManager.potDryJudge(dryLoc);
}, sprinklerTime + randomGenerator.nextInt(dryTime));
}
for (SimpleLocation location : cropCache.keySet()) {
bukkitScheduler.runTaskLaterAsynchronously(CustomCrops.plugin, () -> {
BukkitTask task = bukkitScheduler.runTaskLaterAsynchronously(CustomCrops.plugin, () -> {
Location seedLoc = MiscUtils.getLocation(location);
if (seedLoc == null) return;
if (cropMode.growJudge(seedLoc)) {
cropCache.remove(location);
}
}, new Random().nextInt(time));
}, sprinklerTime + dryTime + randomGenerator.nextInt(cropTime));
tasksCache.add(task);
}
});
}
public void growFrame(int time) {
BukkitScheduler bukkitScheduler = Bukkit.getScheduler();
public void growFrame(int cropTime, int sprinklerTime, int dryTime) {
route(sprinklerTime);
Random randomGenerator = new Random();
CropModeInterface cropMode = cropManager.getCropMode();
bukkitScheduler.runTaskAsynchronously(CustomCrops.plugin, () -> {
route();
tempWatered.removeAll(watered);
for (SimpleLocation simpleLocation : tempWatered) {
bukkitScheduler.runTaskLaterAsynchronously(CustomCrops.plugin, () -> {
Location dryLoc = MiscUtils.getLocation(simpleLocation);
if (dryLoc == null) return;
cropManager.potDryJudge(dryLoc);
}, sprinklerTime + randomGenerator.nextInt(dryTime));
}
for (SimpleLocation location : cropCache.keySet()) {
long random = new Random().nextInt(time);
bukkitScheduler.runTaskLater(CustomCrops.plugin, () -> {
long random = randomGenerator.nextInt(cropTime);
BukkitTask task1 = bukkitScheduler.runTaskLater(CustomCrops.plugin, () -> {
Location seedLoc = MiscUtils.getLocation(location);
if (seedLoc == null) return;
cropMode.loadChunk(seedLoc);
}, random);
bukkitScheduler.runTaskLater(CustomCrops.plugin, () -> {
}, random + dryTime + random);
BukkitTask task2 = bukkitScheduler.runTaskLater(CustomCrops.plugin, () -> {
Location seedLoc = MiscUtils.getLocation(location);
if (seedLoc == null) return;
if (cropMode.growJudge(seedLoc)) {
cropCache.remove(location);
}
}, random + 5);
}, sprinklerTime + dryTime + random + 5);
tasksCache.add(task1);
tasksCache.add(task2);
}
});
}
private void route() {
watered.clear();
for (Map.Entry<SimpleLocation, Sprinkler> sprinklerEntry : sprinklerCache.entrySet()) {
sprinklerWork(sprinklerEntry.getKey(), sprinklerEntry.getValue());
private void route(int sprinklerTime) {
for (BukkitTask task : tasksCache) {
task.cancel();
}
tasksCache.clear();
tempWatered = new HashSet<>(watered);
watered.clear();
watered.addAll(playerWatered);
playerWatered.clear();
Random randomGenerator = new Random();
for (Map.Entry<SimpleLocation, Sprinkler> sprinklerEntry : sprinklerCache.entrySet()) {
BukkitTask task = bukkitScheduler.runTaskLaterAsynchronously(CustomCrops.plugin, () -> {
sprinklerWork(sprinklerEntry.getKey(), sprinklerEntry.getValue());
}, randomGenerator.nextInt(sprinklerTime));
tasksCache.add(task);
}
for (Map.Entry<SimpleLocation, Fertilizer> fertilizerEntry : fertilizerCache.entrySet()) {
Fertilizer fertilizer = fertilizerEntry.getValue();
if (fertilizer.getTimes() > 1) {
@@ -273,6 +370,10 @@ public class CustomWorld {
fertilizerCache.remove(MiscUtils.getSimpleLocation(potLoc));
}
public void removeWatered(Location potLoc) {
watered.remove(MiscUtils.getSimpleLocation(potLoc));
}
public void addFertilizer(Location potLoc, Fertilizer fertilizer) {
fertilizerCache.put(MiscUtils.getSimpleLocation(potLoc), fertilizer);
}
@@ -297,4 +398,12 @@ public class CustomWorld {
public void addSprinkler(Location location, Sprinkler sprinkler) {
sprinklerCache.put(MiscUtils.getSimpleLocation(location), sprinkler);
}
public void setPotWet(Location location) {
watered.add(MiscUtils.getSimpleLocation(location));
}
public void setPlayerWatered(Location location) {
playerWatered.add(MiscUtils.getSimpleLocation(location));
}
}

View File

@@ -79,14 +79,7 @@ public class FrameCropImpl implements CropModeInterface {
if (potID == null) return true;
Fertilizer fertilizer = cropManager.getFertilizer(potLoc);
boolean certainGrow = false;
if (potID.equals(BasicItemConfig.wetPot)) {
if (!(fertilizer instanceof RetainingSoil retainingSoil && Math.random() < retainingSoil.getChance())) {
cropManager.potDryJudge(potLoc);
}
certainGrow = true;
}
boolean certainGrow = potID.equals(BasicItemConfig.wetPot);
int nextStage = Integer.parseInt(cropNameList[2]) + 1;
String temp = StringUtils.chop(id);

View File

@@ -17,6 +17,7 @@
package net.momirealms.customcrops.managers;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.crop.Crop;
import net.momirealms.customcrops.config.BasicItemConfig;
import net.momirealms.customcrops.config.CropConfig;
@@ -28,6 +29,7 @@ import net.momirealms.customcrops.objects.fertilizer.Gigantic;
import net.momirealms.customcrops.objects.fertilizer.RetainingSoil;
import net.momirealms.customcrops.objects.fertilizer.SpeedGrow;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
@@ -58,8 +60,10 @@ public class WireCropImpl implements CropModeInterface{
Crop crop = CropConfig.CROPS.get(cropKey);
if (crop == null) return true;
if (cropManager.isWrongSeason(location, crop.getSeasons())) {
Bukkit.getScheduler().runTask(CustomCrops.plugin, () -> {
customInterface.removeBlock(location);
customInterface.placeWire(location, BasicItemConfig.deadCrop);
});
return true;
}
Location potLoc = location.clone().subtract(0,1,0);
@@ -68,13 +72,7 @@ public class WireCropImpl implements CropModeInterface{
Fertilizer fertilizer = cropManager.getFertilizer(potLoc);
boolean certainGrow = false;
if (potID.equals(BasicItemConfig.wetPot)) {
if (!(fertilizer instanceof RetainingSoil retainingSoil && Math.random() < retainingSoil.getChance())) {
cropManager.potDryJudge(potLoc);
}
certainGrow = true;
}
boolean certainGrow = potID.equals(BasicItemConfig.wetPot);
int nextStage = Integer.parseInt(cropNameList[2]) + 1;
String temp = StringUtils.chop(blockID);
@@ -96,6 +94,7 @@ public class WireCropImpl implements CropModeInterface{
chance += gigantic.getChance();
}
if (Math.random() < chance) {
Bukkit.getScheduler().runTask(CustomCrops.plugin, () -> {
customInterface.removeBlock(location);
if (giganticCrop.isBlock()) {
customInterface.placeWire(location, giganticCrop.getBlockID());
@@ -103,6 +102,7 @@ public class WireCropImpl implements CropModeInterface{
else {
customInterface.placeFurniture(location, giganticCrop.getBlockID());
}
});
}
}
return true;
@@ -111,7 +111,9 @@ public class WireCropImpl implements CropModeInterface{
}
private void addStage(Location seedLoc, String stage) {
Bukkit.getScheduler().runTask(CustomCrops.plugin, () -> {
customInterface.removeBlock(seedLoc);
customInterface.placeWire(seedLoc, stage);
});
}
}

View File

@@ -32,10 +32,11 @@ public class TimerTask extends BukkitRunnable {
@Override
public void run() {
if (!MainConfig.autoGrow) return;
for (World world : MainConfig.getWorldsList()) {
long time = world.getTime();
if (time > 950 && time < 1051) {
cropManager.grow(world, MainConfig.timeToGrow);
cropManager.grow(world, MainConfig.timeToGrow, MainConfig.timeToWork, MainConfig.timeToDry);
}
}
}

View File

@@ -39,9 +39,7 @@ worlds:
crops:
# Mode: tripwire/item_frame
mode: tripwire
@@ -52,12 +50,37 @@ optimization:
tripwire-amount: 64
itemframe-amount: 64
# Async time check
async-time-check: false
# Disable the water particles when using watering-cans
disable-water-particles: false
# Disable the animation when sprinkler works
disable-sprinkler-animation: false
mechanics:
# Mode: tripwire/item_frame
crops-mode: tripwire
# If enabled, crops would start growing at about 7am(at most 5 seconds inaccuracy) and finish growing in the rest of the day
# Note: All the crops can only start growing when a world's time is about 7am, so when a world is loaded and its time is 8am,
# crops would not grow in this day. You can enable time compensation make the crops grow when starting the server.
auto-grow:
enable: true
# For example, the time to start growing is 1000ticks(7am),
# sprinklers would finish their work in a random time between 1000~1300ticks,
# Pot would start drying in a random time between 1300~1500ticks
# and crops would grow in a random time between 1500~21300ticks
sprinkler-work-time: 300
pot-dry-time: 200
crops-grow-time: 20000
# Crops would start growing instantly when the world is loaded instead of waiting for the second day's 7am
time-compensation: true
# If the pot is wet, crop would 100% grow a stage per day
# Otherwise they would have a lower chance to grow.
# Recommend setting it to a value higher than 0 to make sure every crop can be ripe even if
# players don't take care of them, this is good for server performance because crop data would
# be removed from data file when the crop is ripe to avoid affecting server performance in the long term
dry-pot-grow-chance: 0.5
# Can player harvest crops with right click?
# if set "false" crops can't be harvested repeatedly
right-click-harvest:

View File

@@ -13,19 +13,21 @@ speed:
before-plant: true
#The particle to be displayed when using fertilizer
#https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Particle.html
particle: VILLAGER_HAPPY
particle: SPELL_WITCH
speed_2:
name: '뀍'
chance: 0.2
times: 14
item: customcrops:speed_2
before-plant: true
particle: SPELL_WITCH
speed_3:
name: '뀎'
chance: 0.3
times: 14
item: customcrops:speed_3
before-plant: true
particle: SPELL_WITCH
#Pot have a small chance to retain its water after crops grow
@@ -36,18 +38,21 @@ retaining:
times: 28
item: customcrops:retaining_1
before-plant: false
particle: SPELL
retaining_2:
name: '뀊'
chance: 0.2
times: 28
item: customcrops:retaining_2
before-plant: false
particle: SPELL
retaining_3:
name: '뀋'
chance: 0.3
times: 28
item: customcrops:retaining_3
before-plant: false
particle: SPELL
#When haveresting, players have a higher chance to get high quality crops.
@@ -59,6 +64,7 @@ quality:
ratio: 7/2/1
item: customcrops:quality_1
before-plant: true
particle: SCRAPE
quality_2:
name: '뀇'
chance: 1
@@ -66,6 +72,7 @@ quality:
ratio: 11/6/3
item: customcrops:quality_2
before-plant: true
particle: SCRAPE
quality_3:
name: '뀈'
chance: 1
@@ -73,6 +80,7 @@ quality:
ratio: 2/2/1
item: customcrops:quality_3
before-plant: true
particle: SCRAPE
#When haveresting, players have a higher chance to get more crops.
@@ -84,6 +92,7 @@ quantity:
bonus: 1
item: customcrops:quantity_1
before-plant: true
particle: TOTEM
quantity_2:
name: '뀐'
times: 14
@@ -91,6 +100,7 @@ quantity:
bonus: 2
item: customcrops:quantity_2
before-plant: true
particle: TOTEM
quantity_3:
name: '뀑'
times: 14
@@ -98,6 +108,7 @@ quantity:
bonus: 2
item: customcrops:quantity_3
before-plant: true
particle: TOTEM
#Crops have a higher chance to be gigantic
@@ -108,15 +119,18 @@ gigantic:
chance: 0.5
item: customcrops:gigantic_1
before-plant: true
particle: SPELL_MOB
gigantic_2:
name: '뀐'
times: 14
chance: 0.5
item: customcrops:gigantic_2
before-plant: true
particle: SPELL_MOB
gigantic_3:
name: '뀑'
times: 14
chance: 0.8
item: customcrops:gigantic_3
before-plant: true
particle: SPELL_MOB

View File

@@ -13,19 +13,21 @@ speed:
before-plant: true
#The particle to be displayed when using fertilizer
#https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Particle.html
particle: VILLAGER_HAPPY
particle: SPELL_WITCH
speed_2:
name: '뀍'
chance: 0.2
times: 14
item: speed_2
before-plant: true
particle: SPELL_WITCH
speed_3:
name: '뀎'
chance: 0.3
times: 14
item: speed_3
before-plant: true
particle: SPELL_WITCH
#Pot have a small chance to retain its water after crops grow
@@ -36,18 +38,21 @@ retaining:
times: 28
item: retaining_1
before-plant: false
particle: SPELL
retaining_2:
name: '뀊'
chance: 0.2
times: 28
item: retaining_2
before-plant: false
particle: SPELL
retaining_3:
name: '뀋'
chance: 0.3
times: 28
item: retaining_3
before-plant: false
particle: SPELL
#When haveresting, players have a higher chance to get high quality crops.
@@ -59,6 +64,7 @@ quality:
ratio: 7/2/1
item: quality_1
before-plant: true
particle: SCRAPE
quality_2:
name: '뀇'
times: 28
@@ -66,6 +72,7 @@ quality:
ratio: 11/6/3
item: quality_2
before-plant: true
particle: SCRAPE
quality_3:
name: '뀈'
times: 28
@@ -73,6 +80,7 @@ quality:
ratio: 2/2/1
item: quality_3
before-plant: true
particle: SCRAPE
#When haveresting, players have a higher chance to get more crops.
@@ -84,6 +92,7 @@ quantity:
bonus: 1
item: quantity_1
before-plant: true
particle: TOTEM
quantity_2:
name: '뀐'
times: 14
@@ -91,6 +100,7 @@ quantity:
bonus: 2
item: quantity_2
before-plant: true
particle: TOTEM
quantity_3:
name: '뀑'
times: 14
@@ -98,6 +108,7 @@ quantity:
bonus: 2
item: quantity_3
before-plant: true
particle: TOTEM
#Crops have a higher chance to be gigantic
@@ -109,15 +120,18 @@ gigantic:
chance: 0.02
item: gigantic_1
before-plant: true
particle: SPELL_MOB
gigantic_2:
name: '뀐'
times: 14
chance: 0.04
item: gigantic_2
before-plant: true
particle: SPELL_MOB
gigantic_3:
name: '뀑'
times: 14
chance: 0.08
item: gigantic_3
before-plant: true
particle: SPELL_MOB

View File

@@ -16,6 +16,7 @@ messages:
back-up: '<white>已完成数据备份!'
set-season: '<white>成功切换世界 {world} 的季节为 {season}!'
before-plant: '<white>这种肥料必须在种植前使用!'
wrong-season: '<white>当前季节不适合这个农作物生长'
no-season: '此世界没有季节'
season-disabled: '季节系统已被禁用'