9
0
mirror of https://github.com/Xiao-MoMi/Custom-Crops.git synced 2025-12-25 18:09:28 +00:00
This commit is contained in:
XiaoMoMi
2023-07-09 02:34:49 +08:00
parent e7ec94595d
commit 3f81be450e
248 changed files with 1479 additions and 1329 deletions

View File

@@ -0,0 +1,292 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.ProtocolManager;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import net.momirealms.customcrops.api.CustomCropsAPIImpl;
import net.momirealms.customcrops.api.CustomCropsPlugin;
import net.momirealms.customcrops.api.object.basic.ConfigManager;
import net.momirealms.customcrops.api.object.basic.MessageManager;
import net.momirealms.customcrops.api.object.crop.CropManager;
import net.momirealms.customcrops.api.object.fertilizer.FertilizerManager;
import net.momirealms.customcrops.api.object.hologram.HologramManager;
import net.momirealms.customcrops.api.object.pot.PotManager;
import net.momirealms.customcrops.api.object.scheduler.Scheduler;
import net.momirealms.customcrops.api.object.season.SeasonManager;
import net.momirealms.customcrops.api.object.sprinkler.SprinklerManager;
import net.momirealms.customcrops.api.object.wateringcan.WateringCanManager;
import net.momirealms.customcrops.api.object.world.WorldDataManager;
import net.momirealms.customcrops.command.CustomCropsCommand;
import net.momirealms.customcrops.customplugin.Platform;
import net.momirealms.customcrops.customplugin.PlatformInterface;
import net.momirealms.customcrops.customplugin.PlatformManager;
import net.momirealms.customcrops.customplugin.itemsadder.ItemsAdderPluginImpl;
import net.momirealms.customcrops.customplugin.oraxen.OraxenPluginImpl;
import net.momirealms.customcrops.helper.LibraryLoader;
import net.momirealms.customcrops.helper.VersionHelper;
import net.momirealms.customcrops.integration.IntegrationManager;
import net.momirealms.customcrops.util.AdventureUtils;
import net.momirealms.protectionlib.ProtectionLib;
import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.command.PluginCommand;
import org.bukkit.plugin.PluginManager;
import java.util.TimeZone;
public final class CustomCrops extends CustomCropsPlugin {
private static BukkitAudiences adventure;
private static CustomCrops plugin;
private static ProtocolManager protocolManager;
private Platform platform;
private PlatformInterface platformInterface;
private CropManager cropManager;
private IntegrationManager integrationManager;
private WorldDataManager worldDataManager;
private SprinklerManager sprinklerManager;
private WateringCanManager wateringCanManager;
private FertilizerManager fertilizerManager;
private SeasonManager seasonManager;
private PotManager potManager;
private ConfigManager configManager;
private MessageManager messageManager;
private PlatformManager platformManager;
private HologramManager hologramManager;
private VersionHelper versionHelper;
private Scheduler scheduler;
@Override
public void onLoad(){
plugin = this;
this.loadLibs();
ProtectionLib.initialize(this);
}
@Override
public void onEnable() {
adventure = BukkitAudiences.create(this);
protocolManager = ProtocolLibrary.getProtocolManager();
this.versionHelper = new VersionHelper(this);
if (versionHelper.isSpigot()) {
AdventureUtils.consoleMessage("<red>========================[CustomCrops]=========================");
AdventureUtils.consoleMessage("<red> Spigot is not officially supported by CustomCrops");
AdventureUtils.consoleMessage("<red> Please use Paper or its forks");
AdventureUtils.consoleMessage("<red> Paper download link: https://papermc.io/downloads");
AdventureUtils.consoleMessage("<red>==============================================================");
Bukkit.getPluginManager().disablePlugin(this);
return;
}
if (!this.loadPlatform()) return;
this.registerCommands();
AdventureUtils.consoleMessage("[CustomCrops] Running on <white>" + Bukkit.getVersion());
ProtectionLib.hook();
this.scheduler = new Scheduler(this);
this.configManager = new ConfigManager(this);
this.messageManager = new MessageManager(this);
this.cropManager = new CropManager(this);
this.integrationManager = new IntegrationManager(this);
this.seasonManager = new SeasonManager(this);
this.worldDataManager = new WorldDataManager(this);
this.sprinklerManager = new SprinklerManager(this);
this.wateringCanManager = new WateringCanManager(this);
this.fertilizerManager = new FertilizerManager(this);
this.potManager = new PotManager(this);
this.hologramManager = new HologramManager(this);
this.platformManager = new PlatformManager(this);
super.customCropsAPI = new CustomCropsAPIImpl(this);
this.reload();
for (World world : Bukkit.getWorlds()) {
this.worldDataManager.loadWorld(world);
}
AdventureUtils.consoleMessage("[CustomCrops] Plugin Enabled!");
if (ConfigManager.enableBStats) new Metrics(this, 16593);
if (ConfigManager.checkUpdate) this.versionHelper.checkUpdate();
}
public void reload() {
this.configManager.unload();
this.messageManager.unload();
this.cropManager.unload();
this.integrationManager.unload();
this.worldDataManager.unload();
this.sprinklerManager.unload();
this.wateringCanManager.unload();
this.fertilizerManager.unload();
this.potManager.unload();
this.seasonManager.unload();
this.platformManager.unload();
this.hologramManager.unload();
this.configManager.load();
this.messageManager.load();
this.integrationManager.load();
this.cropManager.load();
this.worldDataManager.load();
this.sprinklerManager.load();
this.wateringCanManager.load();
this.fertilizerManager.load();
this.potManager.load();
this.seasonManager.load();
this.platformManager.load();
this.hologramManager.load();
}
@Override
public void onDisable() {
if (adventure != null) adventure.close();
if (this.cropManager != null) this.cropManager.unload();
if (this.worldDataManager != null) this.worldDataManager.disable();
if (this.seasonManager != null) this.seasonManager.unload();
if (this.sprinklerManager != null) this.sprinklerManager.unload();
if (this.wateringCanManager != null) this.wateringCanManager.unload();
if (this.fertilizerManager != null) this.fertilizerManager.unload();
if (this.platformManager != null) this.platformManager.unload();
if (this.potManager != null) this.potManager.unload();
if (this.messageManager != null) this.messageManager.unload();
if (this.configManager != null) this.configManager.unload();
if (this.integrationManager != null) this.integrationManager.unload();
if (this.hologramManager != null) this.hologramManager.unload();
if (this.scheduler != null) this.scheduler.disable();
}
private void loadLibs() {
TimeZone timeZone = TimeZone.getDefault();
String libRepo = timeZone.getID().startsWith("Asia") ? "https://maven.aliyun.com/repository/public/" : "https://repo.maven.apache.org/maven2/";
LibraryLoader.load("dev.dejvokep","boosted-yaml","1.3.1", libRepo);
LibraryLoader.load("commons-io","commons-io","2.11.0", libRepo);
LibraryLoader.load("net.objecthunter","exp4j","0.4.8", libRepo);
}
private void registerCommands() {
CustomCropsCommand customCropsCommand = new CustomCropsCommand();
PluginCommand pluginCommand = Bukkit.getPluginCommand("customcrops");
if (pluginCommand != null) {
pluginCommand.setExecutor(customCropsCommand);
pluginCommand.setTabCompleter(customCropsCommand);
}
}
private boolean loadPlatform() {
PluginManager pluginManager = Bukkit.getPluginManager();
if (pluginManager.getPlugin("ItemsAdder") != null) {
this.platform = Platform.ItemsAdder;
this.platformInterface = new ItemsAdderPluginImpl();
}
else if (pluginManager.getPlugin("Oraxen") != null) {
this.platform = Platform.Oraxen;
this.platformInterface = new OraxenPluginImpl();
}
if (this.platform == null) {
AdventureUtils.consoleMessage("<red>========================[CustomCrops]=========================");
AdventureUtils.consoleMessage("<red> Please install ItemsAdder or Oraxen as dependency.");
AdventureUtils.consoleMessage("<red> ItemsAdder Link: https://www.spigotmc.org/resources/73355/");
AdventureUtils.consoleMessage("<red> Oraxen link: https://www.spigotmc.org/resources/72448/");
AdventureUtils.consoleMessage("<red>==============================================================");
Bukkit.getPluginManager().disablePlugin(this);
return false;
} else {
AdventureUtils.consoleMessage("[CustomCrops] Platform: <green>" + platform.name());
return true;
}
}
public static BukkitAudiences getAdventure() {
return adventure;
}
public static CustomCrops getInstance() {
return plugin;
}
public static ProtocolManager getProtocolManager() {
return protocolManager;
}
public CropManager getCropManager() {
return cropManager;
}
public VersionHelper getVersionHelper() {
return versionHelper;
}
public Platform getPlatform() {
return platform;
}
public IntegrationManager getIntegrationManager() {
return integrationManager;
}
public PlatformInterface getPlatformInterface() {
return platformInterface;
}
public WorldDataManager getWorldDataManager() {
return worldDataManager;
}
public SprinklerManager getSprinklerManager() {
return sprinklerManager;
}
public PotManager getPotManager() {
return potManager;
}
public WateringCanManager getWateringCanManager() {
return wateringCanManager;
}
public FertilizerManager getFertilizerManager() {
return fertilizerManager;
}
public SeasonManager getSeasonManager() {
return seasonManager;
}
public ConfigManager getConfigManager() {
return configManager;
}
public MessageManager getMessageManager() {
return messageManager;
}
public PlatformManager getPlatformManager() {
return platformManager;
}
public HologramManager getHologramManager() {
return hologramManager;
}
public Scheduler getScheduler() {
return scheduler;
}
}

View File

@@ -0,0 +1,127 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.CCGrowingCrop;
import net.momirealms.customcrops.api.object.CCPot;
import net.momirealms.customcrops.api.object.CCSprinkler;
import net.momirealms.customcrops.api.object.CCWorldSeason;
import net.momirealms.customcrops.api.object.season.CCSeason;
import net.momirealms.customcrops.api.object.season.SeasonData;
import net.momirealms.customcrops.api.object.world.CCWorld;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
import org.bukkit.Location;
import org.bukkit.World;
import org.jetbrains.annotations.Nullable;
import java.util.Locale;
public class CustomCropsAPIImpl implements CustomCropsAPI {
private static CustomCropsAPIImpl instance;
private final CustomCrops plugin;
public CustomCropsAPIImpl(CustomCrops plugin) {
this.plugin = plugin;
instance = this;
}
public static CustomCropsAPIImpl getInstance() {
return instance;
}
@Nullable
public CCPot getPotAt(Location location) {
return plugin.getWorldDataManager().getPotData(SimpleLocation.getByBukkitLocation(location));
}
@Nullable
public CCGrowingCrop getCropAt(Location location) {
return plugin.getWorldDataManager().getCropData(SimpleLocation.getByBukkitLocation(location));
}
public boolean isGreenhouseGlass(Location location) {
return plugin.getWorldDataManager().isGreenhouse(SimpleLocation.getByBukkitLocation(location));
}
public boolean hasScarecrowInChunk(Location location) {
return plugin.getWorldDataManager().hasScarecrow(SimpleLocation.getByBukkitLocation(location));
}
public CCSprinkler getSprinklerAt(Location location) {
return plugin.getWorldDataManager().getSprinklerData(SimpleLocation.getByBukkitLocation(location));
}
public void setSeason(String world, String season) {
SeasonData seasonData = plugin.getSeasonManager().getSeasonData(world);
if (seasonData != null) {
seasonData.changeSeason(CCSeason.valueOf(season.toUpperCase(Locale.ENGLISH)));
}
}
public void setDate(String world, int date) {
SeasonData seasonData = plugin.getSeasonManager().getSeasonData(world);
if (seasonData != null) {
seasonData.setDate(date);
}
}
public void addDate(String world) {
SeasonData seasonData = plugin.getSeasonManager().getSeasonData(world);
if (seasonData != null) {
seasonData.addDate();
}
}
@Nullable
public CCWorldSeason getSeason(String world) {
SeasonData seasonData = plugin.getSeasonManager().getSeasonData(world);
if (seasonData != null) {
return seasonData.getSeason();
}
return null;
}
public void grow(World world, int seconds) {
CustomCrops.getInstance().getScheduler().runTaskAsync(() -> {
CCWorld ccworld = CustomCrops.getInstance().getWorldDataManager().getWorld(world.getName());
if (ccworld != null) {
ccworld.scheduleConsumeTask(seconds);
}
});
}
public void sprinklerWork(World world, int seconds) {
CustomCrops.getInstance().getScheduler().runTaskAsync(() -> {
CCWorld ccworld = CustomCrops.getInstance().getWorldDataManager().getWorld(world.getName());
if (ccworld != null) {
ccworld.scheduleSprinklerWork(seconds);
}
});
}
public void consume(World world, int seconds) {
CustomCrops.getInstance().getScheduler().runTaskAsync(() -> {
CCWorld ccworld = CustomCrops.getInstance().getWorldDataManager().getWorld(world.getName());
if (ccworld != null) {
ccworld.scheduleConsumeTask(seconds);
}
});
}
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object;
import net.kyori.adventure.sound.Sound;
import net.momirealms.customcrops.CustomCrops;
import org.bukkit.Particle;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
public class BoneMeal {
private final String item;
private final String returned;
private final ArrayList<Pair<Double, Integer>> pairs;
private final Sound sound;
private final Particle particle;
public BoneMeal(
String item,
@Nullable String returned,
@NotNull ArrayList<Pair<Double, Integer>> pairs,
@Nullable Sound sound,
@Nullable Particle particle
) {
this.item = item;
this.returned = returned;
this.pairs = pairs;
this.sound = sound;
this.particle = particle;
}
public boolean isRightItem(String id) {
return item.equals(id);
}
public ItemStack getReturned() {
if (returned == null) return null;
return CustomCrops.getInstance().getIntegrationManager().build(returned);
}
public int getPoint() {
for (Pair<Double, Integer> pair : pairs) {
if (Math.random() < pair.left()) {
return pair.right();
}
}
return 0;
}
@Nullable
public Sound getSound() {
return sound;
}
@Nullable
public Particle getParticle() {
return particle;
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.util.FakeEntityUtils;
import org.bukkit.Location;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
import java.util.concurrent.ThreadLocalRandom;
public class CrowTask extends BukkitRunnable {
private int timer;
private final int entityID;
private final Vector vectorUp;
private final Location cropLoc;
private final Player player;
private final float yaw;
private final ItemStack fly;
public CrowTask(Player player, Location crop_location, String fly_model, String stand_model) {
this.cropLoc = crop_location.clone();
this.timer = 0;
this.fly = CustomCrops.getInstance().getIntegrationManager().build(fly_model);
this.player = player;
this.entityID = ThreadLocalRandom.current().nextInt(Integer.MAX_VALUE);
this.yaw = ThreadLocalRandom.current().nextInt(361) - 180;
Location relative = crop_location.clone().subtract(crop_location.clone().add(10 * Math.sin((Math.PI * yaw)/180), 10, - 10 * Math.cos((Math.PI * yaw)/180)));
this.vectorUp = new Vector(relative.getX() / 75, 0.1, relative.getZ() / 75);
CustomCrops.getProtocolManager().sendServerPacket(player, FakeEntityUtils.getSpawnPacket(entityID, crop_location, EntityType.ARMOR_STAND));
CustomCrops.getProtocolManager().sendServerPacket(player, FakeEntityUtils.getVanishArmorStandMetaPacket(entityID));
CustomCrops.getProtocolManager().sendServerPacket(player, FakeEntityUtils.getEquipPacket(entityID, CustomCrops.getInstance().getIntegrationManager().build(stand_model)));
}
@Override
public void run() {
timer++;
if (timer == 40) {
CustomCrops.getProtocolManager().sendServerPacket(player, FakeEntityUtils.getEquipPacket(entityID, fly));
} else if (timer > 40) {
CustomCrops.getProtocolManager().sendServerPacket(player, FakeEntityUtils.getTeleportPacket(entityID, cropLoc.add(vectorUp), yaw));
}
if (timer > 100) {
CustomCrops.getProtocolManager().sendServerPacket(player, FakeEntityUtils.getDestroyPacket(entityID));
cancel();
}
}
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object;
public class Function {
public void init() {
}
public void load() {
}
public void unload() {
}
public void disable() {
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.action.Action;
import net.momirealms.customcrops.api.object.requirement.Requirement;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;
public class InteractCrop {
private final boolean consume;
private final String id;
private final String returned;
private final Action[] actions;
private final Requirement[] requirements;
public InteractCrop(@Nullable String id, boolean consume, @Nullable String returned, @Nullable Action[] actions, @Nullable Requirement[] requirements) {
this.consume = consume;
this.id = id;
this.returned = returned;
this.actions = actions;
this.requirements = requirements;
}
public boolean isRightItem(String item) {
if (id == null || id.equals("*")) return true;
return item.equals(id);
}
@Nullable
public ItemStack getReturned() {
if (returned == null) return null;
return CustomCrops.getInstance().getIntegrationManager().build(returned);
}
public boolean isConsumed() {
return consume;
}
public Action[] getActions() {
return actions;
}
@Nullable
public Requirement[] getRequirements() {
return requirements;
}
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object;
import java.io.Serializable;
public enum ItemMode implements Serializable {
ARMOR_STAND,
TRIPWIRE,
ITEM_FRAME,
ITEM_DISPLAY,
NOTE_BLOCK,
CHORUS
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object;
public enum ItemType {
GLASS,
POT,
CROP,
SPRINKLER,
SCARECROW,
WATERING_CAN,
UNKNOWN
}

View File

@@ -0,0 +1,28 @@
package net.momirealms.customcrops.api.object;
import java.io.Serializable;
public class OfflineReplaceTask implements Serializable {
private final String id;
private final ItemType itemType;
private final ItemMode itemMode;
public OfflineReplaceTask(String id, ItemType itemType, ItemMode itemMode) {
this.id = id;
this.itemMode = itemMode;
this.itemType = itemType;
}
public String getId() {
return id;
}
public ItemMode getItemMode() {
return itemMode;
}
public ItemType getItemType() {
return itemType;
}
}

View File

@@ -0,0 +1,25 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object;
public record Pair<L, R>(L left, R right) {
public static <L, R> Pair<L, R> of(final L left, final R right) {
return new Pair<>(left, right);
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object;
public class Tuple<L, M, R> {
private L left;
private M mid;
private R right;
public Tuple(L left, M mid, R right) {
this.left = left;
this.mid = mid;
this.right = right;
}
public static <L, M, R> Tuple<L, M, R> of(final L left, final M mid, final R right) {
return new Tuple<>(left, mid, right);
}
public L getLeft() {
return left;
}
public void setLeft(L left) {
this.left = left;
}
public M getMid() {
return mid;
}
public void setMid(M mid) {
this.mid = mid;
}
public R getRight() {
return right;
}
public void setRight(R right) {
this.right = right;
}
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.action;
import net.momirealms.customcrops.api.object.ItemMode;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
public interface Action {
void doOn(@Nullable Player player, @Nullable SimpleLocation cropLoc, ItemMode itemMode);
}

View File

@@ -0,0 +1,99 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.action;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.event.CropBreakEvent;
import net.momirealms.customcrops.api.object.ItemMode;
import net.momirealms.customcrops.api.object.crop.CropConfig;
import net.momirealms.customcrops.api.object.crop.StageConfig;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.CompletableFuture;
public class BreakImpl implements Action {
private final boolean triggerAction;
private final String stageID;
public BreakImpl(boolean triggerAction, @Nullable String stageID) {
this.triggerAction = triggerAction;
this.stageID = stageID;
}
@Override
public void doOn(@Nullable Player player, @Nullable SimpleLocation cropLoc, ItemMode itemMode) {
if (cropLoc == null || stageID == null) return;
CropConfig cropConfig = CustomCrops.getInstance().getCropManager().getCropConfigByStage(stageID);
Location bLoc = cropLoc.getBukkitLocation();
if (bLoc == null || cropConfig == null) return;
if (player != null) {
CropBreakEvent cropBreakEvent = new CropBreakEvent(player, cropConfig.getKey(), stageID, bLoc);
Bukkit.getPluginManager().callEvent(cropBreakEvent);
if (cropBreakEvent.isCancelled()) {
return;
}
CustomCrops.getInstance().getPlatformInterface().removeAnyThingAt(bLoc);
CustomCrops.getInstance().getWorldDataManager().removeCropData(cropLoc);
doTriggerActions(player, cropLoc, itemMode);
} else {
CompletableFuture<Chunk> asyncGetChunk = bLoc.getWorld().getChunkAtAsync(bLoc.getBlockX() >> 4, bLoc.getBlockZ() >> 4);
if (itemMode == ItemMode.ITEM_FRAME || itemMode == ItemMode.ITEM_DISPLAY) {
CompletableFuture<Boolean> loadEntities = asyncGetChunk.thenApply((chunk) -> {
chunk.getEntities();
return chunk.isEntitiesLoaded();
});
loadEntities.whenComplete((result, throwable) ->
CustomCrops.getInstance().getScheduler().runTask(() -> {
CustomCrops.getInstance().getWorldDataManager().removeCropData(cropLoc);
if (CustomCrops.getInstance().getPlatformInterface().removeCustomItem(bLoc, itemMode)) {
doTriggerActions(null, cropLoc, itemMode);
}
}));
} else {
asyncGetChunk.whenComplete((result, throwable) ->
CustomCrops.getInstance().getScheduler().runTask(() -> {
CustomCrops.getInstance().getWorldDataManager().removeCropData(cropLoc);
if (CustomCrops.getInstance().getPlatformInterface().removeCustomItem(bLoc, itemMode)) {
doTriggerActions(null, cropLoc, itemMode);
}
}));
}
}
}
private void doTriggerActions(@Nullable Player player, @NotNull SimpleLocation crop_loc, ItemMode itemMode) {
if (triggerAction) {
StageConfig stageConfig = CustomCrops.getInstance().getCropManager().getStageConfig(stageID);
if (stageConfig != null) {
Action[] actions = stageConfig.getBreakActions();
if (actions != null) {
for (Action action : actions) {
action.doOn(player, crop_loc, itemMode);
}
}
}
}
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.action;
import net.momirealms.customcrops.api.object.ItemMode;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
public class ChainImpl implements Action {
private final Action[] actions;
private final double chance;
public ChainImpl(Action[] actions, double chance) {
this.actions = actions;
this.chance = chance;
}
@Override
public void doOn(@Nullable Player player, @Nullable SimpleLocation cropLoc, ItemMode itemMode) {
if (Math.random() < chance) {
for (Action action : actions) {
action.doOn(player, cropLoc, itemMode);
}
}
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.action;
import net.momirealms.customcrops.api.object.ItemMode;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
public record CommandActionImpl(String[] commands, double chance) implements Action {
@Override
public void doOn(@Nullable Player player, @Nullable SimpleLocation cropLoc, ItemMode itemMode) {
if (player == null || Math.random() > chance) return;
for (String command : commands) {
Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(),
command.replace("{player}", player.getName())
.replace("{x}", cropLoc == null ? "" : String.valueOf(cropLoc.getX()))
.replace("{y}", cropLoc == null ? "" : String.valueOf(cropLoc.getY()))
.replace("{z}", cropLoc == null ? "" : String.valueOf(cropLoc.getZ()))
.replace("{world}", player.getWorld().getName())
);
}
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.action;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.ItemMode;
import net.momirealms.customcrops.api.object.loot.Loot;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
public record DropItemImpl(Loot[] loots) implements Action {
@Override
public void doOn(@Nullable Player player, @Nullable SimpleLocation cropLoc, ItemMode itemMode) {
if (cropLoc == null) return;
if (player != null) {
for (Loot loot : loots) {
loot.drop(player, cropLoc.getBukkitLocation());
}
} else {
CustomCrops.getInstance().getScheduler().runTask(() -> {
for (Loot loot : loots) {
loot.drop(null, cropLoc.getBukkitLocation());
}
});
}
}
}

View File

@@ -0,0 +1,21 @@
package net.momirealms.customcrops.api.object.action;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.ItemMode;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
import net.momirealms.customcrops.integration.VaultHook;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
public record GiveMoneyImpl(double money, double chance) implements Action {
@Override
public void doOn(@Nullable Player player, @Nullable SimpleLocation cropLoc, ItemMode itemMode) {
if (player != null && Math.random() < chance) {
VaultHook vaultHook = CustomCrops.getInstance().getIntegrationManager().getVault();
if (vaultHook != null) {
vaultHook.getEconomy().depositPlayer(player, money);
}
}
}
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.action;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.ItemMode;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
import net.momirealms.customcrops.integration.JobInterface;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
public record JobXPImpl(double amount, double chance, @Nullable String job) implements Action {
@Override
public void doOn(@Nullable Player player, @Nullable SimpleLocation cropLoc, ItemMode itemMode) {
if (player == null || Math.random() > chance) return;
JobInterface jobInterface = CustomCrops.getInstance().getIntegrationManager().getJobInterface();
if (jobInterface == null) return;
jobInterface.addXp(player, amount, job);
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.action;
import net.momirealms.customcrops.api.object.ItemMode;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
import net.momirealms.customcrops.util.AdventureUtils;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
public record MessageActionImpl(String[] messages, double chance) implements Action {
@Override
public void doOn(@Nullable Player player, @Nullable SimpleLocation cropLoc, ItemMode itemMode) {
if (player == null || Math.random() > chance) return;
for (String message : messages) {
AdventureUtils.playerMessage(player,
message.replace("{player}", player.getName())
.replace("{world}", player.getWorld().getName())
.replace("{x}", cropLoc == null ? "" : String.valueOf(cropLoc.getX()))
.replace("{y}", cropLoc == null ? "" : String.valueOf(cropLoc.getY()))
.replace("{z}", cropLoc == null ? "" : String.valueOf(cropLoc.getZ()))
);
}
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.action;
import net.momirealms.customcrops.api.object.ItemMode;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
public class ParticleImpl implements Action {
private final Particle particle;
private final int amount;
private final double offset;
public ParticleImpl(Particle particle, int amount, double offset) {
this.particle = particle;
this.amount = amount;
this.offset = offset;
}
@Override
public void doOn(@Nullable Player player, @Nullable SimpleLocation cropLoc, ItemMode itemMode) {
if (cropLoc == null) return;
Location location = cropLoc.getBukkitLocation();
if (location == null) return;
location.getWorld().spawnParticle(particle, location.clone().add(0.5,0.5,0.5), amount, offset, offset, offset);
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.action;
import net.momirealms.customcrops.api.object.ItemMode;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffect;
import org.jetbrains.annotations.Nullable;
public record PotionEffectImpl(PotionEffect potionEffect, double chance) implements Action {
@Override
public void doOn(@Nullable Player player, @Nullable SimpleLocation cropLoc, ItemMode itemMode) {
if (player == null || Math.random() > chance) return;
player.addPotionEffect(potionEffect);
}
}

View File

@@ -0,0 +1,97 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.action;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.event.CropPlantEvent;
import net.momirealms.customcrops.api.object.ItemMode;
import net.momirealms.customcrops.api.object.basic.ConfigManager;
import net.momirealms.customcrops.api.object.basic.MessageManager;
import net.momirealms.customcrops.api.object.crop.CropConfig;
import net.momirealms.customcrops.api.object.crop.GrowingCrop;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
import net.momirealms.customcrops.util.AdventureUtils;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.CompletableFuture;
public class ReplantImpl implements Action {
private final int point;
private final String crop;
private final String model;
public ReplantImpl(int point, String model, String crop) {
this.point = point;
this.crop = crop;
this.model = model;
}
@Override
public void doOn(@Nullable Player player, @Nullable SimpleLocation cropLoc, ItemMode itemMode) {
if (cropLoc == null) return;
CropConfig cropConfig = CustomCrops.getInstance().getCropManager().getCropConfigByID(crop);
if (cropConfig != null) {
Location location = cropLoc.getBukkitLocation();
if (location == null) return;
ItemMode newCMode = cropConfig.getCropMode();
if (ConfigManager.enableLimitation && CustomCrops.getInstance().getWorldDataManager().getChunkCropAmount(cropLoc) >= ConfigManager.maxCropPerChunk) {
AdventureUtils.playerMessage(player, MessageManager.prefix + MessageManager.reachChunkLimit);
return;
}
if (player != null) {
CropPlantEvent cropPlantEvent = new CropPlantEvent(player, player.getInventory().getItemInMainHand(), location, crop, point, model);
Bukkit.getPluginManager().callEvent(cropPlantEvent);
if (cropPlantEvent.isCancelled()) {
return;
}
if (!CustomCrops.getInstance().getPlatformInterface().detectAnyThing(location)) {
CustomCrops.getInstance().getPlatformInterface().placeCustomItem(location, model, newCMode);
CustomCrops.getInstance().getWorldDataManager().addCropData(cropLoc, new GrowingCrop(crop, point), true);
}
} else {
CompletableFuture<Chunk> asyncGetChunk = location.getWorld().getChunkAtAsync(location.getBlockX() >> 4, location.getBlockZ() >> 4);
if (itemMode == ItemMode.ITEM_FRAME || itemMode == ItemMode.ITEM_DISPLAY) {
CompletableFuture<Boolean> loadEntities = asyncGetChunk.thenApply((chunk) -> {
chunk.getEntities();
return chunk.isEntitiesLoaded();
});
loadEntities.whenComplete((result, throwable) ->
CustomCrops.getInstance().getScheduler().runTask(() -> {
if (!CustomCrops.getInstance().getPlatformInterface().detectAnyThing(location)) {
CustomCrops.getInstance().getPlatformInterface().placeCustomItem(location, model, newCMode);
CustomCrops.getInstance().getWorldDataManager().addCropData(cropLoc, new GrowingCrop(crop, point), true);
}
}));
} else {
asyncGetChunk.whenComplete((result, throwable) ->
CustomCrops.getInstance().getScheduler().runTask(() -> {
if (!CustomCrops.getInstance().getPlatformInterface().detectAnyThing(location)) {
CustomCrops.getInstance().getPlatformInterface().placeCustomItem(location, model, newCMode);
CustomCrops.getInstance().getWorldDataManager().addCropData(cropLoc, new GrowingCrop(crop, point), true);
}
}));
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.action;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.ItemMode;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
import net.momirealms.customcrops.integration.SkillInterface;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
public record SkillXPImpl(double amount, double chance) implements Action {
@Override
public void doOn(@Nullable Player player, @Nullable SimpleLocation cropLoc, ItemMode itemMode) {
if (player == null || Math.random() > chance) return;
SkillInterface skillInterface = CustomCrops.getInstance().getIntegrationManager().getSkillInterface();
if (skillInterface == null) return;
skillInterface.addXp(player, amount);
}
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.action;
import net.kyori.adventure.key.Key;
import net.kyori.adventure.sound.Sound;
import net.momirealms.customcrops.api.object.ItemMode;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
import net.momirealms.customcrops.util.AdventureUtils;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
import java.util.Locale;
public record SoundActionImpl(String source, String sound, float volume, float pitch) implements Action {
@Override
public void doOn(@Nullable Player player, @Nullable SimpleLocation cropLoc, ItemMode itemMode) {
if (player == null) return;
AdventureUtils.playerSound(player, Sound.Source.valueOf(source.toUpperCase(Locale.ENGLISH)), Key.key(sound), volume, pitch);
}
}

View File

@@ -0,0 +1,16 @@
package net.momirealms.customcrops.api.object.action;
import net.momirealms.customcrops.api.object.ItemMode;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
public class SwingHandImpl implements Action {
@Override
public void doOn(@Nullable Player player, @Nullable SimpleLocation cropLoc, ItemMode itemMode) {
if (player != null) {
player.swingMainHand();
}
}
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.action;
import net.kyori.adventure.key.Key;
import net.kyori.adventure.sound.Sound;
import net.momirealms.customcrops.api.object.ItemMode;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
import net.momirealms.customcrops.util.AdventureUtils;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
public record VanillaXPImpl(int amount, boolean mending, double chance) implements Action {
@Override
public void doOn(@Nullable Player player, @Nullable SimpleLocation cropLoc, ItemMode itemMode) {
if (player == null || Math.random() > chance) return;
player.giveExp(amount, mending);
AdventureUtils.playerSound(player, Sound.Source.PLAYER, Key.key("minecraft:entity.experience_orb.pickup"), 1, 1);
}
}

View File

@@ -0,0 +1,94 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.action;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.ItemMode;
import net.momirealms.customcrops.api.object.crop.VariationCrop;
import net.momirealms.customcrops.api.object.fertilizer.Variation;
import net.momirealms.customcrops.api.object.pot.Pot;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.CompletableFuture;
public record VariationImpl(VariationCrop[] variationCrops) implements Action {
@Override
public void doOn(@Nullable Player player, @Nullable SimpleLocation cropLoc, ItemMode itemMode) {
if (cropLoc == null) return;
double bonus = 0;
Pot pot = CustomCrops.getInstance().getWorldDataManager().getPotData(cropLoc.add(0,-1,0));
if (pot != null && CustomCrops.getInstance().getFertilizerManager().getConfigByFertilizer(pot.getFertilizer()) instanceof Variation variation) {
bonus = variation.getChance();
}
for (VariationCrop variationCrop : variationCrops) {
if (Math.random() < variationCrop.getChance() + bonus) {
doVariation(cropLoc, itemMode, variationCrop);
break;
}
}
}
public boolean doOn(@Nullable SimpleLocation crop_loc, ItemMode itemMode) {
if (crop_loc == null) return false;
double bonus = 0;
Pot pot = CustomCrops.getInstance().getWorldDataManager().getPotData(crop_loc.add(0,-1,0));
if (pot != null && CustomCrops.getInstance().getFertilizerManager().getConfigByFertilizer(pot.getFertilizer()) instanceof Variation variation) {
bonus = variation.getChance();
}
for (VariationCrop variationCrop : variationCrops) {
if (Math.random() < variationCrop.getChance() + bonus) {
doVariation(crop_loc, itemMode, variationCrop);
return true;
}
}
return false;
}
private void doVariation(@NotNull SimpleLocation crop_loc, ItemMode itemMode, VariationCrop variationCrop) {
Location location = crop_loc.getBukkitLocation();
if (location == null) return;
CompletableFuture<Chunk> asyncGetChunk = location.getWorld().getChunkAtAsync(location.getBlockX() >> 4, location.getBlockZ() >> 4);
if (itemMode == ItemMode.ITEM_FRAME || itemMode == ItemMode.ITEM_DISPLAY) {
CompletableFuture<Boolean> loadEntities = asyncGetChunk.thenApply((chunk) -> {
chunk.getEntities();
return chunk.isEntitiesLoaded();
});
loadEntities.whenComplete((result, throwable) ->
CustomCrops.getInstance().getScheduler().callSyncMethod(() -> {
if (CustomCrops.getInstance().getPlatformInterface().removeCustomItem(location, itemMode)) {
CustomCrops.getInstance().getPlatformInterface().placeCustomItem(location, variationCrop.getId(), variationCrop.getCropMode());
}
return null;
}));
} else {
asyncGetChunk.whenComplete((result, throwable) ->
CustomCrops.getInstance().getScheduler().callSyncMethod(() -> {
if (CustomCrops.getInstance().getPlatformInterface().removeCustomItem(location, itemMode)) {
CustomCrops.getInstance().getPlatformInterface().placeCustomItem(location, variationCrop.getId(), variationCrop.getCropMode());
}
return null;
}));
}
}
}

View File

@@ -0,0 +1,166 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.basic;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.Function;
import net.momirealms.customcrops.util.AdventureUtils;
import net.momirealms.customcrops.util.ConfigUtils;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
public class ConfigManager extends Function {
public static String lang;
public static boolean enableBStats;
public static boolean checkUpdate;
public static boolean enableSkillBonus;
public static String bonusFormula;
public static int greenhouseRange;
public static boolean whiteListWorlds;
public static HashSet<String> worldList;
public static String worldFolderPath;
public static boolean debugScheduler;
public static boolean debugCorruption;
public static String greenhouseBlock;
public static String scarecrow;
public static boolean enableGreenhouse;
public static int pointGainInterval;
public static int corePoolSize;
public static double[] defaultRatio;
public static int maxPoolSize;
public static long keepAliveTime;
public static int seasonInterval;
public static boolean enableSeason;
public static boolean rsHook;
public static boolean enableScheduleSystem;
public static boolean syncSeason;
public static boolean autoSeasonChange;
public static String referenceWorld;
public static boolean enableLimitation;
public static int maxCropPerChunk;
public static int cacheSaveInterval;
public static int intervalConsume;
public static int intervalWork;
public static int fixRange;
public static boolean disableMoistureMechanic;
public static boolean preventTrampling;
public static boolean onlyInLoadedChunks;
public static boolean enableCorruptionFixer;
public static boolean debugWorld;
public static boolean updateDuringLoading;
private final HashMap<String, Integer> cropPerWorld;
private final CustomCrops plugin;
public ConfigManager(CustomCrops plugin) {
this.plugin = plugin;
this.cropPerWorld = new HashMap<>();
YamlConfiguration config = ConfigUtils.getConfig("config.yml");
onlyInLoadedChunks = config.getBoolean("mechanics.only-work-in-loaded-chunks", false);
}
@Override
public void load() {
this.loadConfig();
}
@Override
public void unload() {
this.cropPerWorld.clear();
}
private void loadConfig() {
if (new File(plugin.getDataFolder(), "config.yml").exists()) ConfigUtils.update("config.yml");
YamlConfiguration config = ConfigUtils.getConfig("config.yml");
enableBStats = config.getBoolean("metrics");
lang = config.getString("lang");
debugScheduler = config.getBoolean("debug.log-scheduler", false);
debugCorruption = config.getBoolean("debug.log-corruption-fixer", false);
debugWorld = config.getBoolean("debug.log-world-state", false);
loadWorlds(Objects.requireNonNull(config.getConfigurationSection("worlds")));
loadScheduleSystem(Objects.requireNonNull(config.getConfigurationSection("schedule-system")));
loadMechanic(Objects.requireNonNull(config.getConfigurationSection("mechanics")));
loadOtherSetting(Objects.requireNonNull(config.getConfigurationSection("other-settings")));
loadOptimization(Objects.requireNonNull(config.getConfigurationSection("optimization")));
}
private void loadOptimization(ConfigurationSection section) {
enableLimitation = section.getBoolean("limitation.growing-crop-amount.enable", true);
maxCropPerChunk = section.getInt("limitation.growing-crop-amount.default", 64);
updateDuringLoading = !ConfigManager.onlyInLoadedChunks && section.getBoolean("only-update-during-chunk-loading", false);
List<String> worldSettings = section.getStringList("limitation.growing-crop-amount.worlds");
for (String setting : worldSettings) {
String[] split = setting.split(":", 2);
try {
cropPerWorld.put(split[0], Integer.parseInt(split[1]));
} catch (NumberFormatException e) {
AdventureUtils.consoleMessage("<red>[CustomCrops] Wrong number format found at: optimization.limitation.growing-crop-amount.worlds in config.yml");
}
}
}
private void loadWorlds(ConfigurationSection section) {
worldFolderPath = section.getString("absolute-world-folder-path", "");
whiteListWorlds = section.getString("mode", "whitelist").equalsIgnoreCase("whitelist");
worldList = new HashSet<>(section.getStringList("list"));
}
private void loadScheduleSystem(ConfigurationSection section) {
enableScheduleSystem = section.getBoolean("enable", true);
pointGainInterval = section.getInt("point-gain-interval", 600);
corePoolSize = section.getInt("thread-pool-settings.corePoolSize", 2);
maxPoolSize = section.getInt("thread-pool-settings.maximumPoolSize", 4);
keepAliveTime = section.getInt("thread-pool-settings.keepAliveTime", 10);
cacheSaveInterval = section.getInt("cache-save-interval", 12000);
intervalConsume = section.getInt("consume-water-fertilizer-every-x-point", 2);
intervalWork = section.getInt("sprinkler-work-every-x-point", 2);
}
private void loadMechanic(ConfigurationSection section) {
defaultRatio = ConfigUtils.getQualityRatio(section.getString("default-quality-ratio", "17/2/1"));
enableSeason = section.getBoolean("season.enable", true);
syncSeason = section.getBoolean("season.sync-season.enable", false);
referenceWorld = section.getString("season.sync-season.reference");
autoSeasonChange = section.getBoolean("season.auto-season-change.enable");
seasonInterval = section.getInt("season.auto-season-change.duration", 28);
enableGreenhouse = section.getBoolean("season.greenhouse.enable", true);
greenhouseRange = section.getInt("season.greenhouse.range", 5);
greenhouseBlock = section.getString("season.greenhouse.block");
scarecrow = section.getString("scarecrow");
disableMoistureMechanic = section.getBoolean("vanilla-farmland.disable-moisture-mechanic", false);
preventTrampling = section.getBoolean("vanilla-farmland.prevent-trampling", false);
}
private void loadOtherSetting(ConfigurationSection section) {
enableSkillBonus = section.getBoolean("skill-bonus.enable", false);
bonusFormula = section.getString("skill-bonus.formula");
enableCorruptionFixer = section.getBoolean("enable-corruption-fixer", true);
fixRange = section.getInt("corrupt-fix-range", 4);
}
public int getCropLimit(String world) {
return Objects.requireNonNullElse(cropPerWorld.get(world), maxCropPerChunk);
}
}

View File

@@ -0,0 +1,90 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.basic;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.Function;
import net.momirealms.customcrops.util.ConfigUtils;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File;
public class MessageManager extends Function {
private CustomCrops plugin;
public static String prefix;
public static String reload;
public static String unavailableArgs;
public static String noConsole;
public static String notOnline;
public static String lackArgs;
public static String nonArgs;
public static String beforePlant;
public static String unsuitablePot;
public static String reachChunkLimit;
public static String spring;
public static String summer;
public static String autumn;
public static String winter;
public static String noPerm;
public static String noSeason;
public static String setSeason;
public static String setDate;
public static String worldNotExist;
public static String seasonNotExist;
public static String forceWork;
public static String forceConsume;
public static String forceGrow;
public MessageManager(CustomCrops plugin) {
this.plugin =plugin;
}
@Override
public void load() {
this.loadMessage();
}
private void loadMessage() {
YamlConfiguration config = ConfigUtils.getConfig("messages" + File.separator + "messages_" + ConfigManager.lang + ".yml");
prefix = config.getString("messages.prefix","<gradient:#ff206c:#fdee55>[CustomCrops] </gradient>");
reload = config.getString("messages.reload", "<white>Reloaded! Took <green>{time}ms.");
unavailableArgs = config.getString("messages.invalid-args", "<white>Invalid arguments.");
noConsole = config.getString("messages.no-console", "This command can only be executed by a player.");
notOnline = config.getString("messages.not-online", "<white>Player {player} is not online.");
lackArgs = config.getString("messages.lack-args", "<white>Arguments are insufficient.");
nonArgs = config.getString("messages.not-none-args", "<white>Not a none argument command.");
beforePlant = config.getString("messages.before-plant", "<white>This fertilizer can only be used before planting.");
unsuitablePot = config.getString("messages.unsuitable-pot", "<white>You can't plant the seed in this pot.");
reachChunkLimit = config.getString("messages.reach-crop-limit", "<white>The number of crops has reached the limitation.");
noPerm = config.getString("messages.no-perm", "<red>You don't have permission to do that.");
spring = config.getString("messages.spring", "Spring");
summer = config.getString("messages.summer", "Summer");
autumn = config.getString("messages.autumn", "Autumn");
winter = config.getString("messages.winter", "Winter");
noSeason = config.getString("messages.no-season", "SEASON DISABLED IN THIS WORLD");
setSeason = config.getString("messages.set-season", "<white>Successfully set {world}'s season to {season}.");
setDate = config.getString("messages.set-date", "<white>Successfully set {world}'s date to {date}.");
worldNotExist = config.getString("messages.world-not-exist", "<white>World {world} does not exist.");
seasonNotExist = config.getString("messages.season-not-exist", "<white>Season {season} does not exist.");
forceWork = config.getString("messages.force-sprinkler-work", "<white>Forced {world}'s sprinklers to work.");
forceConsume = config.getString("messages.force-consume", "<white>Forced {world}'s pots to reduce water amount and the remaining use of fertilizers.");
forceGrow = config.getString("messages.force-grow", "<white>Forced {world}'s crops to grow one point.");
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.condition;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
import java.util.List;
public class AndCondition implements Condition {
private final List<Condition> deathConditions;
public AndCondition(List<Condition> deathConditions) {
this.deathConditions = deathConditions;
}
@Override
public boolean isMet(SimpleLocation simpleLocation) {
for (Condition condition : deathConditions) {
if (!condition.isMet(simpleLocation)) {
return false;
}
}
return true;
}
}

View File

@@ -0,0 +1,25 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.condition;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
public interface Condition {
boolean isMet(SimpleLocation simpleLocation);
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.condition;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.CrowTask;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Player;
public class CrowAttack implements Condition {
private final double chance;
private final String fly_model;
private final String stand_model;
public CrowAttack(double chance, String fly_model, String stand_model) {
this.chance = chance;
this.fly_model = fly_model;
this.stand_model = stand_model;
}
@Override
public boolean isMet(SimpleLocation simpleLocation) {
if (Math.random() > chance) return false;
if (CustomCrops.getInstance().getWorldDataManager().hasScarecrow(simpleLocation)) return false;
Location location = simpleLocation.getBukkitLocation();
if (location == null) return false;
for (Player player : Bukkit.getOnlinePlayers()) {
SimpleLocation playerLoc = SimpleLocation.getByBukkitLocation(player.getLocation());
if (playerLoc.isNear(simpleLocation, 48)) {
new CrowTask(player, location, fly_model, stand_model).runTaskTimerAsynchronously(CustomCrops.getInstance(), 1, 1);
}
}
return true;
}
}

View File

@@ -0,0 +1,87 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.condition;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.ItemMode;
import net.momirealms.customcrops.api.object.ItemType;
import net.momirealms.customcrops.api.object.OfflineReplaceTask;
import net.momirealms.customcrops.api.object.basic.ConfigManager;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.CompletableFuture;
public class DeathCondition {
private final String dead_model;
private final Condition[] conditions;
public DeathCondition(@Nullable String dead_model, @NotNull Condition[] conditions) {
this.dead_model = dead_model;
this.conditions = conditions;
}
public boolean checkIfDead(SimpleLocation simpleLocation) {
for (Condition condition : conditions) {
if (condition.isMet(simpleLocation)) {
return true;
}
}
return false;
}
public void applyDeadModel(SimpleLocation simpleLocation, ItemMode itemMode) {
Location location = simpleLocation.getBukkitLocation();
if (location == null) return;
if (location.getWorld().isChunkLoaded(simpleLocation.getX() >> 4, simpleLocation.getZ() >> 4)) {
replaceDeadModels(location, itemMode);
return;
}
if (ConfigManager.updateDuringLoading) {
CustomCrops.getInstance().getWorldDataManager().addOfflineTask(simpleLocation, new OfflineReplaceTask(dead_model, ItemType.CROP, itemMode));
return;
}
CompletableFuture<Chunk> asyncGetChunk = location.getWorld().getChunkAtAsync(location.getBlockX() >> 4, location.getBlockZ() >> 4);
if (itemMode == ItemMode.ITEM_FRAME || itemMode == ItemMode.ITEM_DISPLAY) {
CompletableFuture<Boolean> loadEntities = asyncGetChunk.thenApply((chunk) -> {
chunk.getEntities();
return chunk.isEntitiesLoaded();
});
loadEntities.whenComplete((result, throwable) -> replaceDeadModels(location, itemMode));
} else {
asyncGetChunk.whenComplete((result, throwable) -> replaceDeadModels(location, itemMode));
}
}
private void replaceDeadModels(Location location, ItemMode itemMode) {
CustomCrops.getInstance().getScheduler().runTask(() -> {
if (CustomCrops.getInstance().getPlatformInterface().removeCustomItem(location, itemMode)) {
if (dead_model != null) {
CustomCrops.getInstance().getPlatformInterface().placeCustomItem(location, dead_model, itemMode);
}
}
});
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.condition;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
import java.util.List;
public class OrCondition implements Condition {
private final List<Condition> deathConditions;
public OrCondition(List<Condition> deathConditions) {
this.deathConditions = deathConditions;
}
@Override
public boolean isMet(SimpleLocation simpleLocation) {
for (Condition condition : deathConditions) {
if (condition.isMet(simpleLocation)) {
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.condition;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
public class Random implements Condition {
private final double chance;
public Random(double chance) {
this.chance = chance;
}
@Override
public boolean isMet(SimpleLocation simpleLocation) {
return Math.random() < chance;
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.condition;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.basic.ConfigManager;
import net.momirealms.customcrops.api.object.season.CCSeason;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
import net.momirealms.customcrops.api.object.world.WorldDataManager;
public class RightSeason implements Condition {
private final CCSeason[] seasons;
public RightSeason(CCSeason[] seasons) {
this.seasons = seasons;
}
@Override
public boolean isMet(SimpleLocation simpleLocation) {
String world = simpleLocation.getWorldName();
CCSeason current = CustomCrops.getInstance().getIntegrationManager().getSeasonInterface().getSeason(world);
for (CCSeason allowed : seasons) {
if (current == allowed) {
return true;
}
}
WorldDataManager worldDataManager = CustomCrops.getInstance().getWorldDataManager();
if (ConfigManager.enableGreenhouse) {
for (int i = 0; i < ConfigManager.greenhouseRange; i++) {
if (worldDataManager.isGreenhouse(simpleLocation.add(0, i, 0))) {
return true;
}
}
}
return false;
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.condition;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.pot.Pot;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
public class WaterLessThan implements Condition {
private final int amount;
public WaterLessThan(int amount) {
this.amount = amount;
}
@Override
public boolean isMet(SimpleLocation crop_loc) {
Pot pot = CustomCrops.getInstance().getWorldDataManager().getPotData(crop_loc.add(0,-1,0));
if (pot == null) return true;
return pot.getWater() < amount;
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.condition;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.pot.Pot;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
public class WaterMoreThan implements Condition {
private final int amount;
public WaterMoreThan(int amount) {
this.amount = amount;
}
@Override
public boolean isMet(SimpleLocation crop_loc) {
Pot pot = CustomCrops.getInstance().getWorldDataManager().getPotData(crop_loc.add(0,-1,0));
if (pot == null) return false;
return pot.getWater() > amount;
}
}

View File

@@ -0,0 +1,29 @@
package net.momirealms.customcrops.api.object.condition;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
import org.bukkit.World;
public class Weather implements Condition {
private final String[] weathers;
public Weather(String[] weathers) {
this.weathers = weathers;
}
@Override
public boolean isMet(SimpleLocation simpleLocation) {
World world = simpleLocation.getBukkitWorld();
if (world == null) return false;
String currentWeather;
if (world.isThundering()) currentWeather = "thunder";
else if (world.isClearWeather()) currentWeather = "clear";
else currentWeather = "rain";
for (String weather : weathers) {
if (weather.equals(currentWeather)) {
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.condition;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.basic.ConfigManager;
import net.momirealms.customcrops.api.object.season.CCSeason;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
import net.momirealms.customcrops.api.object.world.WorldDataManager;
public class WrongSeason implements Condition {
private final CCSeason[] seasons;
public WrongSeason(CCSeason[] seasons) {
this.seasons = seasons;
}
@Override
public boolean isMet(SimpleLocation simpleLocation) {
String world = simpleLocation.getWorldName();
CCSeason current = CustomCrops.getInstance().getIntegrationManager().getSeasonInterface().getSeason(world);
for (CCSeason bad : seasons) {
if (current == bad) {
WorldDataManager worldDataManager = CustomCrops.getInstance().getWorldDataManager();
if (ConfigManager.enableGreenhouse) {
for (int i = 0; i < ConfigManager.greenhouseRange; i++) {
if (worldDataManager.isGreenhouse(simpleLocation.add(0, i, 0))) {
return false;
}
}
}
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,130 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.crop;
import net.momirealms.customcrops.api.object.BoneMeal;
import net.momirealms.customcrops.api.object.ItemMode;
import net.momirealms.customcrops.api.object.action.Action;
import net.momirealms.customcrops.api.object.condition.Condition;
import net.momirealms.customcrops.api.object.condition.DeathCondition;
import net.momirealms.customcrops.api.object.requirement.Requirement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
public class CropConfig {
private final String key;
private final ItemMode itemMode;
private final String[] bottom_blocks;
private final int max_points;
private final HashMap<Integer, StageConfig> stageMap;
private final Requirement[] plantRequirements;
private final Requirement[] breakRequirements;
private final DeathCondition[] deathConditions;
private final Condition[] growConditions;
private final BoneMeal[] boneMeals;
private final Action[] plantActions;
private final boolean rotation;
public CropConfig(
String key,
ItemMode itemMode,
int max_points,
String[] bottom_blocks,
Requirement[] plantRequirements,
Requirement[] breakRequirements,
DeathCondition[] deathConditions,
Condition[] growConditions,
HashMap<Integer, StageConfig> stageMap,
BoneMeal[] boneMeals,
Action[] plantActions,
boolean rotation
) {
this.key = key;
this.itemMode = itemMode;
this.deathConditions = deathConditions;
this.plantRequirements = plantRequirements;
this.breakRequirements = breakRequirements;
this.max_points = max_points;
this.bottom_blocks = bottom_blocks;
this.stageMap = stageMap;
this.growConditions = growConditions;
this.boneMeals = boneMeals;
this.plantActions = plantActions;
this.rotation = rotation;
}
public String getKey() {
return key;
}
@NotNull
public ItemMode getCropMode() {
return itemMode;
}
@Nullable
public StageConfig getStageConfig(int stage) {
return stageMap.get(stage);
}
@NotNull
public String[] getPotWhitelist() {
return bottom_blocks;
}
public int getMaxPoints() {
return max_points;
}
@Nullable
public Requirement[] getPlantRequirements() {
return plantRequirements;
}
@Nullable
public Requirement[] getBreakRequirements() {
return breakRequirements;
}
@Nullable
public DeathCondition[] getDeathConditions() {
return deathConditions;
}
@Nullable
public Condition[] getGrowConditions() {
return growConditions;
}
@Nullable
public BoneMeal[] getBoneMeals() {
return boneMeals;
}
@Nullable
public Action[] getPlantActions() {
return plantActions;
}
public boolean isRotationEnabled() {
return rotation;
}
}

View File

@@ -0,0 +1,251 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.crop;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.Function;
import net.momirealms.customcrops.api.object.InteractCrop;
import net.momirealms.customcrops.api.object.ItemMode;
import net.momirealms.customcrops.api.object.condition.Condition;
import net.momirealms.customcrops.api.object.condition.DeathCondition;
import net.momirealms.customcrops.api.object.requirement.Requirement;
import net.momirealms.customcrops.customplugin.Platform;
import net.momirealms.customcrops.util.AdventureUtils;
import net.momirealms.customcrops.util.ConfigUtils;
import org.bukkit.Bukkit;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Item;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.ItemSpawnEvent;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
public class CropManager extends Function implements Listener {
private final CustomCrops plugin;
private final HashMap<String, String> stageToCrop;
private final HashMap<String, CropConfig> seedToCropConfig;
private final HashMap<String, CropConfig> cropConfigMap;
private final HashMap<String, StageConfig> stageConfigMap;
private final HashSet<String> deadCrops;
private boolean hasCheckedTripwire;
public CropManager(CustomCrops plugin) {
this.plugin = plugin;
this.stageToCrop = new HashMap<>();
this.cropConfigMap = new HashMap<>();
this.stageConfigMap = new HashMap<>();
this.seedToCropConfig = new HashMap<>();
this.deadCrops = new HashSet<>();
}
@Override
public void load() {
this.loadConfig();
Bukkit.getPluginManager().registerEvents(this, plugin);
}
@Override
public void unload() {
this.stageToCrop.clear();
this.cropConfigMap.clear();
this.stageConfigMap.clear();
this.deadCrops.clear();
this.seedToCropConfig.clear();
HandlerList.unregisterAll(this);
}
private void loadConfig() {
File crop_folder = new File(plugin.getDataFolder(), "contents" + File.separator + "crops");
if (!crop_folder.exists()) {
if (!crop_folder.mkdirs()) return;
ConfigUtils.getConfig("contents" + File.separator + "crops" + File.separator + "tomato.yml");
}
File[] files = crop_folder.listFiles();
if (files == null) return;
for (File file : files) {
YamlConfiguration config = YamlConfiguration.loadConfiguration(file);
for (String key : config.getKeys(false)) {
ConfigurationSection cropSec = config.getConfigurationSection(key);
if (cropSec == null) continue;
ItemMode itemMode = ItemMode.valueOf(cropSec.getString("type", "TripWire").toUpperCase(Locale.ENGLISH));
if (itemMode == ItemMode.TRIPWIRE && !hasCheckedTripwire) {
checkTripwire();
}
String[] bottomBlocks = cropSec.getStringList("pot-whitelist").toArray(new String[0]);
if (bottomBlocks.length == 0) {
AdventureUtils.consoleMessage("<red>[CustomCrops] pot-whitelist is not set for crop: " + key);
continue;
}
String seed = cropSec.getString("seed");
Requirement[] breakReq = ConfigUtils.getRequirementsWithMsg(cropSec.getConfigurationSection("requirements.break"));
Requirement[] plantReq = ConfigUtils.getRequirementsWithMsg(cropSec.getConfigurationSection("requirements.plant"));
int max = cropSec.getInt("max-points", 0);
ConfigurationSection pointSec = cropSec.getConfigurationSection("points");
if (pointSec == null || max == 0) {
AdventureUtils.consoleMessage("<red>[CustomCrops] Points are not set for crop: " + key);
continue;
}
HashMap<Integer, StageConfig> stageMap = new HashMap<>();
for (String point : pointSec.getKeys(false)) {
try {
int parsed = Integer.parseInt(point);
String stageModel = pointSec.getString(point + ".model");
StageConfig stageConfig = new StageConfig(
parsed,
stageModel,
ConfigUtils.getActions(pointSec.getConfigurationSection(point + ".events.break"), stageModel),
ConfigUtils.getActions(pointSec.getConfigurationSection(point + ".events.grow"), stageModel),
ConfigUtils.getInteractActions(pointSec.getConfigurationSection(point + ".events.interact-with-item"), stageModel),
pointSec.contains(point + ".events.interact-by-hand") ? new InteractCrop(
"AIR",
false,
null,
ConfigUtils.getActions(pointSec.getConfigurationSection(point + ".events.interact-by-hand"), stageModel),
ConfigUtils.getRequirementsWithMsg(pointSec.getConfigurationSection(point + ".events.interact-by-hand.requirements"))
) : null,
pointSec.getDouble(point + ".hologram-offset-correction", 0d)
);
stageMap.put(parsed, stageConfig);
if (stageModel != null) {
stageToCrop.put(stageModel, key);
stageConfigMap.put(stageModel, stageConfig);
}
}
catch (NumberFormatException e) {
AdventureUtils.consoleMessage("<red>[CustomCrops] Unexpected point value: " + point);
}
}
DeathCondition[] deathConditions = ConfigUtils.getDeathConditions(cropSec.getConfigurationSection("death-conditions"));
Condition[] growConditions = ConfigUtils.getConditions(cropSec.getConfigurationSection("grow-conditions"));
CropConfig cropConfig = new CropConfig(
key,
itemMode,
max,
bottomBlocks,
plantReq,
breakReq,
deathConditions,
growConditions,
stageMap,
ConfigUtils.getBoneMeals(cropSec.getConfigurationSection("custom-bone-meal")),
ConfigUtils.getActions(cropSec.getConfigurationSection("plant-actions"), null),
cropSec.getBoolean("random-rotation", false)
);
cropConfigMap.put(key, cropConfig);
if (seed != null) seedToCropConfig.put(seed, cropConfig);
}
}
AdventureUtils.consoleMessage("[CustomCrops] Loaded <green>" + cropConfigMap.size() + " <gray>crop(s)");
}
@Nullable
public StageConfig getStageConfig(String stage_id) {
return stageConfigMap.get(stage_id);
}
@Nullable
public CropConfig getCropConfigByID(String id) {
return this.cropConfigMap.get(id);
}
@Nullable
public CropConfig getCropConfigByStage(String stage_id) {
String key = getCropConfigID(stage_id);
if (key == null) return null;
return this.cropConfigMap.get(key);
}
@Nullable
public String getCropConfigID(String stage_id) {
return this.stageToCrop.get(stage_id);
}
public boolean isDeadCrop(String id) {
return deadCrops.contains(id);
}
public boolean containsStage(String stage_id) {
return stageToCrop.containsKey(stage_id);
}
// Prevent players from getting stage model
@EventHandler
public void onItemSpawn(ItemSpawnEvent event) {
if (event.isCancelled()) return;
Item item = event.getEntity();
String id = plugin.getPlatformInterface().getItemStackID(item.getItemStack());
if (containsStage(id) || isDeadCrop(id)) {
event.setCancelled(true);
}
}
public void registerDeadCrops(String id) {
this.deadCrops.add(id);
}
@Nullable
public CropConfig getCropConfigBySeed(String seed) {
return seedToCropConfig.get(seed);
}
private void checkTripwire() {
hasCheckedTripwire = true;
if (plugin.getPlatform() == Platform.ItemsAdder) {
Plugin iaP = Bukkit.getPluginManager().getPlugin("ItemsAdder");
if (iaP != null) {
FileConfiguration config = iaP.getConfig();
boolean disabled = config.getBoolean("blocks.disable-REAL_WIRE");
if (disabled) {
AdventureUtils.consoleMessage("<red>========================[CustomCrops]=========================");
AdventureUtils.consoleMessage("<red> Detected that one of your crops is using TRIPWIRE type");
AdventureUtils.consoleMessage("<red> If you want to use tripwire for custom crops, please set");
AdventureUtils.consoleMessage("<red>\"blocks.disable-REAL_WIRE: false\" in /ItemsAdder/config.yml");
AdventureUtils.consoleMessage("<red> Change this setting requires a server restart");
AdventureUtils.consoleMessage("<red> If you have problems with which one to use, read the wiki.");
AdventureUtils.consoleMessage("<red>==============================================================");
}
}
} else if (plugin.getPlatform() == Platform.Oraxen) {
Plugin oxP = Bukkit.getPluginManager().getPlugin("Oraxen");
if (oxP != null) {
YamlConfiguration config = YamlConfiguration.loadConfiguration(new File(oxP.getDataFolder(), "mechanics.yml"));
boolean disabled = !config.getBoolean("stringblock.enabled");
if (disabled) {
AdventureUtils.consoleMessage("<red>========================[CustomCrops]=========================");
AdventureUtils.consoleMessage("<red> Detected that one of your crops is using TRIPWIRE type");
AdventureUtils.consoleMessage("<red> If you want to use tripwire for custom crops, please set");
AdventureUtils.consoleMessage("<red> \"stringblock.enabled: true\" in /Oraxen/mechanics.yml");
AdventureUtils.consoleMessage("<red> If you have problems with which one to use, read the wiki.");
AdventureUtils.consoleMessage("<red>==============================================================");
}
}
}
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.crop;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.CCGrowingCrop;
import java.io.Serial;
import java.io.Serializable;
public class GrowingCrop implements Serializable, CCGrowingCrop {
@Serial
private static final long serialVersionUID = 2828962866548871991L;
private int points;
private final String crop;
public GrowingCrop(String crop, int points) {
this.points = points;
this.crop = crop;
}
public int getPoints() {
return points;
}
public void setPoints(int points) {
this.points = points;
}
public String getKey() {
return crop;
}
public CropConfig getConfig() {
return CustomCrops.getInstance().getCropManager().getCropConfigByID(crop);
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.crop;
import net.momirealms.customcrops.api.object.InteractCrop;
import net.momirealms.customcrops.api.object.action.Action;
import org.jetbrains.annotations.Nullable;
public class StageConfig {
private final int point;
private final String model;
private final Action[] breakActions;
private final InteractCrop[] interactWithItem;
private final Action[] growActions;
private final InteractCrop interactByHand;
private final double offsetCorrection;
public StageConfig(int point, @Nullable String model, @Nullable Action[] breakActions, @Nullable Action[] growActions, @Nullable InteractCrop[] interactWithItem, @Nullable InteractCrop interactByHand, double offsetCorrection) {
this.point = point;
this.breakActions = breakActions;
this.interactWithItem = interactWithItem;
this.growActions = growActions;
this.interactByHand = interactByHand;
this.model = model;
this.offsetCorrection = offsetCorrection;
}
@Nullable
public Action[] getBreakActions() {
return breakActions;
}
@Nullable
public InteractCrop[] getInteractCropWithItem() {
return interactWithItem;
}
@Nullable
public Action[] getGrowActions() {
return growActions;
}
@Nullable
public InteractCrop getInteractByHand() {
return interactByHand;
}
@Nullable
public String getModel() {
return model;
}
public double getOffsetCorrection() {
return offsetCorrection;
}
public int getPoint() {
return point;
}
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.crop;
import net.momirealms.customcrops.api.object.ItemMode;
public class VariationCrop {
private final String id;
private final ItemMode itemMode;
private final double chance;
public VariationCrop(String id, ItemMode itemMode, double chance) {
this.id = id;
this.itemMode = itemMode;
this.chance = chance;
}
public String getId() {
return id;
}
public ItemMode getCropMode() {
return itemMode;
}
public double getChance() {
return chance;
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.fertilizer;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.CCFertilizer;
import java.io.Serializable;
public class Fertilizer implements Serializable, CCFertilizer {
private final String key;
private int times;
public Fertilizer(String key, int times) {
this.key = key;
this.times = times;
}
public Fertilizer(FertilizerConfig fertilizerConfig) {
this.key = fertilizerConfig.getKey();
this.times = fertilizerConfig.getTimes();
}
/*
If fertilizer is used up
*/
public boolean reduceTimes() {
times--;
return times <= 0;
}
public String getKey() {
return key;
}
public FertilizerConfig getConfig() {
return CustomCrops.getInstance().getFertilizerManager().getConfigByFertilizer(this);
}
public int getLeftTimes() {
return times;
}
public void setTimes(int times) {
this.times = times;
}
}

View File

@@ -0,0 +1,108 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.fertilizer;
import net.kyori.adventure.sound.Sound;
import net.momirealms.customcrops.api.object.requirement.Requirement;
import org.bukkit.Particle;
import org.jetbrains.annotations.Nullable;
public abstract class FertilizerConfig {
private final int times;
private final double chance;
private final String key;
private final FertilizerType fertilizerType;
private final String[] pot_whitelist;
private final boolean beforePlant;
private final Particle particle;
private final Sound sound;
private final String icon;
private final Requirement[] requirements;
public FertilizerConfig(
String key,
FertilizerType fertilizerType,
int times,
double chance,
@Nullable String[] pot_whitelist,
boolean beforePlant,
@Nullable Particle particle,
@Nullable Sound sound,
@Nullable String icon,
Requirement[] requirements
) {
this.times = times;
this.chance = chance;
this.key = key;
this.fertilizerType = fertilizerType;
this.pot_whitelist = pot_whitelist;
this.beforePlant = beforePlant;
this.particle = particle;
this.sound = sound;
this.icon = icon;
this.requirements = requirements;
}
public int getTimes() {
return times;
}
public double getChance() {
return chance;
}
public boolean canTakeEffect() {
return Math.random() < chance;
}
public String getKey() {
return key;
}
public FertilizerType getFertilizerType() {
return fertilizerType;
}
@Nullable
public String[] getPotWhitelist() {
return pot_whitelist;
}
public boolean isBeforePlant() {
return beforePlant;
}
@Nullable
public Particle getParticle() {
return particle;
}
@Nullable
public Sound getSound() {
return sound;
}
public String getIcon() {
return icon;
}
public Requirement[] getRequirements() {
return requirements;
}
}

View File

@@ -0,0 +1,137 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.fertilizer;
import net.kyori.adventure.key.Key;
import net.kyori.adventure.sound.Sound;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.Function;
import net.momirealms.customcrops.api.object.Pair;
import net.momirealms.customcrops.api.object.requirement.Requirement;
import net.momirealms.customcrops.util.AdventureUtils;
import net.momirealms.customcrops.util.ConfigUtils;
import org.bukkit.Particle;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.intellij.lang.annotations.Subst;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
public class FertilizerManager extends Function {
private final CustomCrops plugin;
private final HashMap<String, FertilizerConfig> fertilizerConfigMap;
private final HashMap<String, String> itemToKey;
public FertilizerManager(CustomCrops plugin) {
this.plugin = plugin;
this.fertilizerConfigMap = new HashMap<>();
this.itemToKey = new HashMap<>();
}
@Override
public void load() {
this.loadConfig();
}
@Override
public void unload() {
this.fertilizerConfigMap.clear();
this.itemToKey.clear();
}
@Nullable
public FertilizerConfig getConfigByFertilizer(@Nullable Fertilizer fertilizer) {
if (fertilizer == null) return null;
return fertilizerConfigMap.get(fertilizer.getKey());
}
@Nullable
public FertilizerConfig getConfigByKey(String key) {
return fertilizerConfigMap.get(key);
}
@Nullable
public FertilizerConfig getConfigByItemID(String id) {
String key = itemToKey.get(id);
if (key == null) return null;
return getConfigByKey(key);
}
private void loadConfig() {
File can_folder = new File(plugin.getDataFolder(), "contents" + File.separator + "fertilizers");
if (!can_folder.exists()) {
if (!can_folder.mkdirs()) return;
ConfigUtils.getConfig("contents" + File.separator + "fertilizers" + File.separator + "speed-grow.yml");
ConfigUtils.getConfig("contents" + File.separator + "fertilizers" + File.separator + "quality.yml");
ConfigUtils.getConfig("contents" + File.separator + "fertilizers" + File.separator + "soil-retain.yml");
ConfigUtils.getConfig("contents" + File.separator + "fertilizers" + File.separator + "yield-increase.yml");
ConfigUtils.getConfig("contents" + File.separator + "fertilizers" + File.separator + "variation.yml");
}
File[] files = can_folder.listFiles();
if (files == null) return;
for (File file : files) {
YamlConfiguration config = YamlConfiguration.loadConfiguration(file);
for (String key : config.getKeys(false)) {
ConfigurationSection fertilizerSec = config.getConfigurationSection(key);
if (fertilizerSec == null) continue;
FertilizerConfig fertilizerConfig;
FertilizerType fertilizerType = FertilizerType.valueOf(fertilizerSec.getString("type", "SPEED_GROW").toUpperCase(Locale.ENGLISH));
String[] pot_whitelist = fertilizerSec.contains("pot-whitelist") ? fertilizerSec.getStringList("pot-whitelist").toArray(new String[0]) : null;
boolean beforePlant = fertilizerSec.getBoolean("before-plant", false);
int times = fertilizerSec.getInt("times", 14);
Particle particle = fertilizerSec.contains("particle") ? Particle.valueOf(fertilizerSec.getString("particle")) : null;
@Subst("namespace:key") String soundKey = fertilizerSec.getString("sound", "minecraft:item.hoe.till");
Sound sound = fertilizerSec.contains("sound") ? Sound.sound(Key.key(soundKey), Sound.Source.PLAYER, 1, 1) : null;
String icon = fertilizerSec.getString("icon");
Requirement[] requirements = ConfigUtils.getRequirementsWithMsg(fertilizerSec.getConfigurationSection("requirements"));
switch (fertilizerType) {
case SPEED_GROW -> fertilizerConfig = new SpeedGrow(key, fertilizerType, times, getChancePair(fertilizerSec), pot_whitelist, beforePlant, particle, sound, icon, requirements);
case YIELD_INCREASE -> fertilizerConfig = new YieldIncrease(key, fertilizerType, times, fertilizerSec.getDouble("chance"), getChancePair(fertilizerSec), pot_whitelist, beforePlant, particle, sound, icon, requirements);
case VARIATION -> fertilizerConfig = new Variation(key, fertilizerType, times, fertilizerSec.getDouble("chance"), pot_whitelist, beforePlant, particle, sound, icon, requirements);
case QUALITY -> fertilizerConfig = new Quality(key, fertilizerType, times, fertilizerSec.getDouble("chance"), ConfigUtils.getQualityRatio(fertilizerSec.getString("ratio", "2/2/1")), pot_whitelist, beforePlant, particle, sound, icon, requirements);
case SOIL_RETAIN -> fertilizerConfig = new SoilRetain(key, fertilizerType, times, fertilizerSec.getDouble("chance"), pot_whitelist, beforePlant, particle, sound, icon, requirements);
default -> fertilizerConfig = null;
}
String item = fertilizerSec.getString("item");
if (fertilizerConfig != null && item != null) {
fertilizerConfigMap.put(key, fertilizerConfig);
itemToKey.put(item, key);
}
else
AdventureUtils.consoleMessage("<red>[CustomCrops] Invalid fertilizer: " + key);
}
}
AdventureUtils.consoleMessage("[CustomCrops] Loaded <green>" + fertilizerConfigMap.size() + " <gray>fertilizer(s)");
}
public ArrayList<Pair<Double, Integer>> getChancePair(ConfigurationSection fertilizerSec) {
ArrayList<Pair<Double, Integer>> pairs = new ArrayList<>();
ConfigurationSection effectSec = fertilizerSec.getConfigurationSection("chance");
if (effectSec == null) return new ArrayList<>();
for (String point : effectSec.getKeys(false)) {
Pair<Double, Integer> pair = new Pair<>(effectSec.getDouble(point), Integer.parseInt(point));
pairs.add(pair);
}
return pairs;
}
}

View File

@@ -0,0 +1,26 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.fertilizer;
public enum FertilizerType {
SPEED_GROW,
QUALITY,
SOIL_RETAIN,
VARIATION,
YIELD_INCREASE
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.fertilizer;
import net.kyori.adventure.sound.Sound;
import net.momirealms.customcrops.api.object.basic.ConfigManager;
import net.momirealms.customcrops.api.object.requirement.Requirement;
import net.momirealms.customcrops.util.AdventureUtils;
import org.bukkit.Particle;
import org.jetbrains.annotations.Nullable;
public class Quality extends FertilizerConfig {
private final double[] ratio;
public Quality(
String key,
FertilizerType fertilizerType,
int times,
double chance,
double[] ratio,
@Nullable String[] pot_whitelist,
boolean beforePlant,
@Nullable Particle particle,
@Nullable Sound sound,
@Nullable String icon,
Requirement[] requirements
) {
super(key, fertilizerType, times, chance, pot_whitelist, beforePlant, particle, sound, icon, requirements);
this.ratio = ratio;
if (this.ratio.length != ConfigManager.defaultRatio.length) {
AdventureUtils.consoleMessage("<red>[CustomCrops] Wrong format found at fertilizer: " + key + ". You should make sure that all the quality ratio are in the same format. For example when you set default-ratio to x/x/x/x/x in config.yml. You should set ratio to x/x/x/x/x in fertilizers to work");
}
}
public double[] getRatio() {
return ratio;
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.fertilizer;
import net.kyori.adventure.sound.Sound;
import net.momirealms.customcrops.api.object.requirement.Requirement;
import org.bukkit.Particle;
import org.jetbrains.annotations.Nullable;
public class SoilRetain extends FertilizerConfig {
public SoilRetain(
String key,
FertilizerType fertilizerType,
int times,
double chance,
@Nullable String[] pot_whitelist,
boolean beforePlant,
@Nullable Particle particle,
@Nullable Sound sound,
String icon,
Requirement[] requirements
) {
super(key, fertilizerType, times, chance, pot_whitelist, beforePlant, particle, sound, icon, requirements);
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.fertilizer;
import net.kyori.adventure.sound.Sound;
import net.momirealms.customcrops.api.object.Pair;
import net.momirealms.customcrops.api.object.requirement.Requirement;
import org.bukkit.Particle;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class SpeedGrow extends FertilizerConfig {
private final List<Pair<Double, Integer>> pairs;
public SpeedGrow(
String key,
FertilizerType fertilizerType,
int times,
List<Pair<Double, Integer>> pairs,
@Nullable String[] pot_whitelist,
boolean beforePlant,
@Nullable Particle particle,
@Nullable Sound sound,
String icon,
Requirement[] requirements
) {
super(key, fertilizerType, times, 1, pot_whitelist, beforePlant, particle, sound, icon, requirements);
this.pairs = pairs;
}
public int getPointBonus() {
for (Pair<Double, Integer> pair : pairs) {
if (Math.random() < pair.left()) {
return pair.right();
}
}
return 0;
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.fertilizer;
import net.kyori.adventure.sound.Sound;
import net.momirealms.customcrops.api.object.requirement.Requirement;
import org.bukkit.Particle;
import org.jetbrains.annotations.Nullable;
public class Variation extends FertilizerConfig {
public Variation(
String key,
FertilizerType fertilizerType,
int times,
double chance,
@Nullable String[] pot_whitelist,
boolean beforePlant,
@Nullable Particle particle,
@Nullable Sound sound,
String icon,
Requirement[] requirements
) {
super(key, fertilizerType, times, chance, pot_whitelist, beforePlant, particle, sound, icon, requirements);
}
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.fertilizer;
import net.kyori.adventure.sound.Sound;
import net.momirealms.customcrops.api.object.Pair;
import net.momirealms.customcrops.api.object.requirement.Requirement;
import org.bukkit.Particle;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class YieldIncrease extends FertilizerConfig {
private final List<Pair<Double, Integer>> pairs;
public YieldIncrease(
String key,
FertilizerType fertilizerType,
int times,
double chance,
List<Pair<Double, Integer>> pairs,
@Nullable String[] pot_whitelist,
boolean beforePlant,
@Nullable Particle particle,
@Nullable Sound sound,
String icon,
Requirement[] requirements
) {
super(key, fertilizerType, times, chance, pot_whitelist, beforePlant, particle, sound, icon, requirements);
this.pairs = pairs;
}
public int getAmountBonus() {
for (Pair<Double, Integer> pair : pairs) {
if (Math.random() < pair.left()) {
return pair.right();
}
}
return 0;
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.fill;
import net.kyori.adventure.sound.Sound;
import org.bukkit.Particle;
import org.jetbrains.annotations.Nullable;
public abstract class AbstractFillMethod {
protected int amount;
protected Particle particle;
protected Sound sound;
protected AbstractFillMethod(int amount, Particle particle, Sound sound) {
this.amount = amount;
this.particle = particle;
this.sound = sound;
}
public int getAmount() {
return amount;
}
@Nullable
public Particle getParticle() {
return particle;
}
public Sound getSound() {
return sound;
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.fill;
import net.kyori.adventure.sound.Sound;
import net.momirealms.customcrops.CustomCrops;
import org.bukkit.Particle;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;
public class PassiveFillMethod extends AbstractFillMethod {
private final String used;
private final String returned;
public PassiveFillMethod(String used, @Nullable String returned, int amount, @Nullable Particle particle, @Nullable Sound sound) {
super(amount, particle, sound);
this.used = used;
this.returned = returned;
}
public boolean isRightItem(String item_id) {
return used.equals(item_id);
}
@Nullable
public ItemStack getReturnedItemStack() {
if (returned == null) return null;
return CustomCrops.getInstance().getIntegrationManager().build(returned);
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.fill;
import net.kyori.adventure.sound.Sound;
import org.bukkit.Particle;
public class PositiveFillMethod extends AbstractFillMethod {
private final String id;
public PositiveFillMethod(String id, int amount, Particle particle, Sound sound) {
super(amount, particle, sound);
this.id = id;
}
public String getId() {
return id;
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.hologram;
public abstract class AbstractHologram {
protected final String content;
private final double offset;
private final HologramManager.Mode mode;
private final int duration;
private TextDisplayMeta textDisplayMeta;
public AbstractHologram(String content, double offset, HologramManager.Mode mode, int duration, TextDisplayMeta textDisplayMeta) {
this.content = content;
this.offset = offset;
this.mode = mode;
this.duration = duration;
this.textDisplayMeta = textDisplayMeta;
}
public String getContent() {
return content;
}
public double getOffset() {
return offset;
}
public HologramManager.Mode getMode() {
return mode;
}
public int getDuration() {
return duration;
}
public TextDisplayMeta getTextDisplayMeta() {
return textDisplayMeta;
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.hologram;
import net.momirealms.customcrops.api.object.CCFertilizer;
import net.momirealms.customcrops.api.object.fertilizer.Fertilizer;
import net.momirealms.customcrops.api.object.fertilizer.FertilizerConfig;
import org.jetbrains.annotations.NotNull;
public class FertilizerHologram extends AbstractHologram {
public FertilizerHologram(@NotNull String content, double offset, HologramManager.Mode mode, int duration, TextDisplayMeta textDisplayMeta) {
super(content, offset, mode, duration, textDisplayMeta);
}
public String getContent(CCFertilizer CCFertilizer) {
Fertilizer fertilizer = (Fertilizer) CCFertilizer;
FertilizerConfig fertilizerConfig = fertilizer.getConfig();
return content.replace("{icon}", String.valueOf(fertilizerConfig.getIcon()))
.replace("{left_times}", String.valueOf(fertilizer.getLeftTimes()))
.replace("{max_times}", String.valueOf(fertilizerConfig.getTimes()));
}
}

View File

@@ -0,0 +1,168 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.hologram;
import net.kyori.adventure.text.Component;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.Function;
import net.momirealms.customcrops.api.object.Tuple;
import net.momirealms.customcrops.util.FakeEntityUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
import java.util.ArrayList;
import java.util.Map;
import java.util.UUID;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ThreadLocalRandom;
public class HologramManager extends Function implements Listener {
private final ConcurrentHashMap<UUID, HologramCache> hologramMap;
private final CustomCrops plugin;
private ScheduledFuture<?> scheduledFuture;
public HologramManager(CustomCrops plugin) {
this.plugin = plugin;
this.hologramMap = new ConcurrentHashMap<>();
}
@Override
public void load() {
Bukkit.getPluginManager().registerEvents(this, plugin);
scheduledFuture = plugin.getScheduler().runTaskTimerAsync(() -> {
ArrayList<UUID> removed = new ArrayList<>(4);
long current = System.currentTimeMillis();
for (Map.Entry<UUID, HologramCache> entry : hologramMap.entrySet()) {
Player player = Bukkit.getPlayer(entry.getKey());
if (player == null || !player.isOnline()) {
removed.add(entry.getKey());
} else {
entry.getValue().removeOutDated(current, player);
}
}
for (UUID uuid : removed) {
hologramMap.remove(uuid);
}
}, 500, 500);
}
@Override
public void unload() {
HandlerList.unregisterAll(this);
for (Map.Entry<UUID, HologramCache> entry : hologramMap.entrySet()) {
Player player = Bukkit.getPlayer(entry.getKey());
if (player != null && player.isOnline()) {
entry.getValue().removeAll(player);
}
}
if (scheduledFuture != null) scheduledFuture.cancel(false);
this.hologramMap.clear();
}
@EventHandler
public void onQuit(PlayerQuitEvent event) {
this.hologramMap.remove(event.getPlayer().getUniqueId());
}
public void showHologram(Player player, Location location, Component component, int millis, Mode mode, TextDisplayMeta textDisplayMeta) {
HologramCache hologramCache = hologramMap.get(player.getUniqueId());
if (hologramCache != null) {
hologramCache.showHologram(player, location, component, millis, mode, textDisplayMeta);
} else {
hologramCache = new HologramCache();
hologramCache.showHologram(player, location, component, millis, mode, textDisplayMeta);
hologramMap.put(player.getUniqueId(), hologramCache);
}
}
public enum Mode {
ARMOR_STAND,
TEXT_DISPLAY
}
@SuppressWarnings("unchecked")
public static class HologramCache {
private final Vector<Tuple<Location, Integer, Long>> tupleList;
private Tuple<Location, Integer, Long>[] tuples;
public HologramCache() {
this.tupleList = new Vector<>();
this.tuples = new Tuple[0];
}
public int push(Location new_loc, int time) {
for (Tuple<Location, Integer, Long> tuple : tuples) {
if (new_loc.equals(tuple.getLeft())) {
tuple.setRight(System.currentTimeMillis() + time);
return tuple.getMid();
}
}
return 0;
}
public void removeOutDated(long current, Player player) {
for (Tuple<Location, Integer, Long> tuple : tuples) {
if (tuple.getRight() < current) {
tupleList.remove(tuple);
this.tuples = tupleList.toArray(new Tuple[0]);
CustomCrops.getProtocolManager().sendServerPacket(player, FakeEntityUtils.getDestroyPacket(tuple.getMid()));
}
}
}
public void showHologram(Player player, Location location, Component component, int millis, Mode mode, TextDisplayMeta textDisplayMeta) {
int entity_id = push(location, millis);
if (entity_id == 0) {
int random = ThreadLocalRandom.current().nextInt(Integer.MAX_VALUE);
tupleList.add(Tuple.of(location, random, System.currentTimeMillis() + millis));
this.tuples = tupleList.toArray(new Tuple[0]);
if (mode == Mode.ARMOR_STAND) {
CustomCrops.getProtocolManager().sendServerPacket(player, FakeEntityUtils.getSpawnPacket(random, location, EntityType.ARMOR_STAND));
CustomCrops.getProtocolManager().sendServerPacket(player, FakeEntityUtils.getVanishArmorStandMetaPacket(random, component));
} else if (mode == Mode.TEXT_DISPLAY) {
CustomCrops.getProtocolManager().sendServerPacket(player, FakeEntityUtils.getSpawnPacket(random, location.clone().add(0,1,0), EntityType.TEXT_DISPLAY));
CustomCrops.getProtocolManager().sendServerPacket(player, FakeEntityUtils.getTextDisplayMetaPacket(random, component, textDisplayMeta));
}
} else {
if (mode == Mode.ARMOR_STAND) {
CustomCrops.getProtocolManager().sendServerPacket(player, FakeEntityUtils.getVanishArmorStandMetaPacket(entity_id, component));
} else if (mode == Mode.TEXT_DISPLAY) {
CustomCrops.getProtocolManager().sendServerPacket(player, FakeEntityUtils.getTextDisplayMetaPacket(entity_id, component, textDisplayMeta));
}
}
}
public void removeAll(Player player) {
for (Tuple<Location, Integer, Long> tuple : tuples) {
CustomCrops.getProtocolManager().sendServerPacket(player, FakeEntityUtils.getDestroyPacket(tuple.getMid()));
}
this.tupleList.clear();
this.tuples = null;
}
}
}

View File

@@ -0,0 +1,6 @@
package net.momirealms.customcrops.api.object.hologram;
public record TextDisplayMeta(boolean hasShadow, boolean isSeeThrough, boolean useDefaultBackground,
int backgroundColor, byte opacity) {
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.hologram;
import org.jetbrains.annotations.NotNull;
public class WaterAmountHologram extends AbstractHologram {
private final String bar_left;
private final String bar_full;
private final String bar_empty;
private final String bar_right;
public WaterAmountHologram(@NotNull String content, double offset, HologramManager.Mode mode, int duration,
String bar_left, String bar_full, String bar_empty, String bar_right, TextDisplayMeta textDisplayMeta) {
super(content, offset, mode, duration, textDisplayMeta);
this.bar_left = bar_left;
this.bar_full = bar_full;
this.bar_empty = bar_empty;
this.bar_right = bar_right;
}
public String getContent(int current, int storage) {
return super.content.replace("{current}", String.valueOf(current))
.replace("{storage}", String.valueOf(storage))
.replace("{water_bar}", getWaterBar(current, storage));
}
private String getWaterBar(int current, int storage) {
return bar_left +
String.valueOf(bar_full).repeat(current) +
String.valueOf(bar_empty).repeat(Math.max(storage - current, 0)) +
bar_right;
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.loot;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.basic.ConfigManager;
import net.momirealms.customcrops.integration.SkillInterface;
import net.objecthunter.exp4j.Expression;
import net.objecthunter.exp4j.ExpressionBuilder;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.ThreadLocalRandom;
public abstract class Loot {
public int min;
public int max;
public Loot(int min, int max) {
this.min = min;
this.max = max;
}
public void drop(@Nullable Player player, Location location) {
//empty
}
public int getMin() {
return min;
}
public int getMax() {
return max;
}
public int getAmount(@Nullable Player player) {
int random = ThreadLocalRandom.current().nextInt(getMin(), getMax() + 1);
if (ConfigManager.enableSkillBonus && player != null) {
SkillInterface skillInterface = CustomCrops.getInstance().getIntegrationManager().getSkillInterface();
if (skillInterface != null) {
int level = skillInterface.getLevel(player);
Expression expression = new ExpressionBuilder(ConfigManager.bonusFormula)
.variables("base", "level")
.build()
.setVariable("base", random)
.setVariable("level", level);
random = (int) expression.evaluate();
}
}
return random;
}
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.loot;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.fertilizer.YieldIncrease;
import net.momirealms.customcrops.api.object.pot.Pot;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
public class OtherLoot extends Loot {
private final String itemID;
private final double chance;
public OtherLoot(int min, int max, String itemID, double chance) {
super(min, max);
this.itemID = itemID;
this.chance = chance;
}
public String getItemID() {
return itemID;
}
public double getChance() {
return chance;
}
public void drop(Player player, Location location) {
if (Math.random() < getChance()) {
int random = getAmount(player);
Pot pot = CustomCrops.getInstance().getWorldDataManager().getPotData(SimpleLocation.getByBukkitLocation(location).add(0,-1,0));
if (pot != null && pot.getFertilizer() != null && pot.getFertilizer().getConfig() instanceof YieldIncrease increase) {
random += increase.getAmountBonus();
}
ItemStack drop = CustomCrops.getInstance().getIntegrationManager().build(getItemID(), player);
if (drop.getType() == Material.AIR) return;
drop.setAmount(random);
location.getWorld().dropItemNaturally(location, drop);
}
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.loot;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.basic.ConfigManager;
import net.momirealms.customcrops.api.object.fertilizer.FertilizerConfig;
import net.momirealms.customcrops.api.object.fertilizer.Quality;
import net.momirealms.customcrops.api.object.fertilizer.YieldIncrease;
import net.momirealms.customcrops.api.object.pot.Pot;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
public class QualityLoot extends Loot {
private final String[] qualityLoots;
public QualityLoot(int min, int max, String... qualityLoots) {
super(min, max);
this.qualityLoots = qualityLoots;
}
@Override
public void drop(Player player, Location location) {
SimpleLocation simpleLocation = SimpleLocation.getByBukkitLocation(location);
Pot pot = CustomCrops.getInstance().getWorldDataManager().getPotData(simpleLocation.add(0,-1,0));
int amount = getAmount(player);
double[] qualityRatio = ConfigManager.defaultRatio;
if (pot != null) {
FertilizerConfig fertilizerConfig = CustomCrops.getInstance().getFertilizerManager().getConfigByFertilizer(pot.getFertilizer());
if (fertilizerConfig instanceof Quality quality && quality.canTakeEffect()) {
qualityRatio = quality.getRatio();
} else if (fertilizerConfig instanceof YieldIncrease increase) {
amount += increase.getAmountBonus();
}
}
for (int i = 0; i < amount; i++) {
double random = Math.random();
for (int j = 0; j < qualityRatio.length; j++) {
if (random < qualityRatio[j]) {
dropItem(location, qualityLoots[j], player);
break;
}
}
}
}
private void dropItem(Location location, String id, Player player) {
ItemStack drop = CustomCrops.getInstance().getIntegrationManager().build(id, player);
if (drop.getType() == Material.AIR) return;
location.getWorld().dropItemNaturally(location, drop);
}
}

View File

@@ -0,0 +1,238 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.migrate;
import net.momirealms.customcrops.api.object.Function;
import net.momirealms.customcrops.api.object.crop.GrowingCrop;
import net.momirealms.customcrops.api.object.fertilizer.Fertilizer;
import net.momirealms.customcrops.api.object.pot.Pot;
import net.momirealms.customcrops.api.object.sprinkler.Sprinkler;
import net.momirealms.customcrops.api.object.world.CCChunk;
import net.momirealms.customcrops.api.object.world.ChunkCoordinate;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
import net.momirealms.customcrops.util.ConfigUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.*;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class MigrateWorld extends Function {
private final String worldName;
private final ConcurrentHashMap<ChunkCoordinate, CCChunk> chunkMap;
public MigrateWorld(String world) {
this.worldName = world;
this.chunkMap = new ConcurrentHashMap<>(64);
}
@Override
@SuppressWarnings("ResultOfMethodCallIgnored")
public void init() {
File chunks_folder = ConfigUtils.getFile(worldName, "chunks");
if (!chunks_folder.exists()) chunks_folder.mkdirs();
File[] data_files = chunks_folder.listFiles();
if (data_files == null) return;
for (File file : data_files) {
ChunkCoordinate chunkCoordinate = ChunkCoordinate.getByString(file.getName().substring(0, file.getName().length() - 7));
try (FileInputStream fis = new FileInputStream(file); ObjectInputStream ois = new ObjectInputStream(fis)) {
CCChunk chunk = (CCChunk) ois.readObject();
if (chunk.isUseless()) {
file.delete();
continue;
}
if (chunkCoordinate != null) chunkMap.put(chunkCoordinate, chunk);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
@Override
@SuppressWarnings("ResultOfMethodCallIgnored")
public void disable() {
File chunks_folder = ConfigUtils.getFile(worldName, "chunks");
if (!chunks_folder.exists()) chunks_folder.mkdirs();
for (Map.Entry<ChunkCoordinate, CCChunk> entry : chunkMap.entrySet()) {
ChunkCoordinate chunkCoordinate = entry.getKey();
CCChunk chunk = entry.getValue();
String fileName = chunkCoordinate.getFileName() + ".ccdata";
File file = new File(chunks_folder, fileName);
if (chunk.isUseless() && file.exists()) {
file.delete();
continue;
}
try (FileOutputStream fos = new FileOutputStream(file); ObjectOutputStream oos = new ObjectOutputStream(fos)) {
oos.writeObject(chunk);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public String getWorldName() {
return worldName;
}
public void removePotData(SimpleLocation simpleLocation) {
CCChunk chunk = chunkMap.get(simpleLocation.getChunkCoordinate());
if (chunk == null) return;
chunk.removePotData(simpleLocation);
}
public void removeCropData(SimpleLocation simpleLocation) {
CCChunk chunk = chunkMap.get(simpleLocation.getChunkCoordinate());
if (chunk == null) return;
chunk.removeCropData(simpleLocation);
}
public void addCropData(SimpleLocation simpleLocation, GrowingCrop growingCrop) {
CCChunk chunk = chunkMap.get(simpleLocation.getChunkCoordinate());
if (chunk != null) {
chunk.addCropData(simpleLocation, growingCrop);
return;
}
chunk = createNewChunk(simpleLocation);
chunk.addCropData(simpleLocation, growingCrop);
}
public GrowingCrop getCropData(SimpleLocation simpleLocation) {
CCChunk chunk = chunkMap.get(simpleLocation.getChunkCoordinate());
if (chunk != null) {
return chunk.getCropData(simpleLocation);
}
return null;
}
public int getChunkCropAmount(SimpleLocation simpleLocation) {
CCChunk chunk = chunkMap.get(simpleLocation.getChunkCoordinate());
if (chunk == null) return 0;
return chunk.getCropAmount();
}
public void removeGreenhouse(SimpleLocation simpleLocation) {
CCChunk chunk = chunkMap.get(simpleLocation.getChunkCoordinate());
if (chunk == null) return;
chunk.removeGreenhouse(simpleLocation);
}
public void addGreenhouse(SimpleLocation simpleLocation) {
CCChunk chunk = chunkMap.get(simpleLocation.getChunkCoordinate());
if (chunk != null) {
chunk.addGreenhouse(simpleLocation);
return;
}
chunk = createNewChunk(simpleLocation);
chunk.addGreenhouse(simpleLocation);
}
public boolean isGreenhouse(SimpleLocation simpleLocation) {
CCChunk chunk = chunkMap.get(simpleLocation.getChunkCoordinate());
if (chunk == null) return false;
return chunk.isGreenhouse(simpleLocation);
}
public void removeScarecrow(SimpleLocation simpleLocation) {
CCChunk chunk = chunkMap.get(simpleLocation.getChunkCoordinate());
if (chunk == null) return;
chunk.removeScarecrow(simpleLocation);
}
public void addScarecrow(SimpleLocation simpleLocation) {
CCChunk chunk = chunkMap.get(simpleLocation.getChunkCoordinate());
if (chunk != null) {
chunk.addScarecrow(simpleLocation);
return;
}
chunk = createNewChunk(simpleLocation);
chunk.addScarecrow(simpleLocation);
}
public boolean hasScarecrow(SimpleLocation simpleLocation) {
CCChunk chunk = chunkMap.get(simpleLocation.getChunkCoordinate());
if (chunk == null) return false;
return chunk.hasScarecrow();
}
public void removeSprinklerData(SimpleLocation simpleLocation) {
CCChunk chunk = chunkMap.get(simpleLocation.getChunkCoordinate());
if (chunk == null) return;
chunk.removeSprinklerData(simpleLocation);
}
public void addSprinklerData(SimpleLocation simpleLocation, Sprinkler sprinkler) {
CCChunk chunk = chunkMap.get(simpleLocation.getChunkCoordinate());
if (chunk != null) {
chunk.addSprinklerData(simpleLocation, sprinkler);
return;
}
chunk = createNewChunk(simpleLocation);
chunk.addSprinklerData(simpleLocation, sprinkler);
}
@Nullable
public Sprinkler getSprinklerData(SimpleLocation simpleLocation) {
CCChunk chunk = chunkMap.get(simpleLocation.getChunkCoordinate());
if (chunk == null) return null;
return chunk.getSprinklerData(simpleLocation);
}
public void addWaterToPot(SimpleLocation simpleLocation, int amount, @NotNull String pot_id) {
CCChunk chunk = chunkMap.get(simpleLocation.getChunkCoordinate());
if (chunk != null) {
chunk.addWaterToPot(simpleLocation, amount, pot_id);
return;
}
chunk = createNewChunk(simpleLocation);
chunk.addWaterToPot(simpleLocation, amount, pot_id);
}
public void addFertilizerToPot(SimpleLocation simpleLocation, Fertilizer fertilizer, @NotNull String pot_id) {
CCChunk chunk = chunkMap.get(simpleLocation.getChunkCoordinate());
if (chunk != null) {
chunk.addFertilizerToPot(simpleLocation, fertilizer, pot_id);
return;
}
chunk = createNewChunk(simpleLocation);
chunk.addFertilizerToPot(simpleLocation, fertilizer, pot_id);
}
public Pot getPotData(SimpleLocation simpleLocation) {
CCChunk chunk = chunkMap.get(simpleLocation.getChunkCoordinate());
if (chunk == null) return null;
return chunk.getPotData(simpleLocation);
}
public void addPotData(SimpleLocation simpleLocation, Pot pot) {
CCChunk chunk = chunkMap.get(simpleLocation.getChunkCoordinate());
if (chunk != null) {
chunk.addPotData(simpleLocation, pot);
return;
}
chunk = createNewChunk(simpleLocation);
chunk.addPotData(simpleLocation, pot);
}
public CCChunk createNewChunk(SimpleLocation simpleLocation) {
CCChunk newChunk = new CCChunk();
chunkMap.put(simpleLocation.getChunkCoordinate(), newChunk);
return newChunk;
}
}

View File

@@ -0,0 +1,111 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.pot;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.CCFertilizer;
import net.momirealms.customcrops.api.object.CCPot;
import net.momirealms.customcrops.api.object.fertilizer.Fertilizer;
import org.jetbrains.annotations.NotNull;
import java.io.Serial;
import java.io.Serializable;
public class Pot implements Serializable, CCPot {
@Serial
private static final long serialVersionUID = -6598493908660891824L;
private Fertilizer fertilizer;
private int water;
private final String key;
public Pot(String key, Fertilizer fertilizer, int water) {
this.key = key;
this.fertilizer = fertilizer;
this.water = water;
}
public Fertilizer getFertilizer() {
return fertilizer;
}
@Override
public void setFertilizer(CCFertilizer fertilizer) {
setFertilizer((Fertilizer) fertilizer);
}
public void setFertilizer(Fertilizer fertilizer) {
this.fertilizer = fertilizer;
}
public int getWater() {
return water;
}
/*
whether to change block model
*/
public boolean addWater(int amount) {
if (water == 0) {
this.water = Math.min(getConfig().getMaxStorage(), amount);
return true;
} else {
this.water = Math.min(getConfig().getMaxStorage(), water + amount);
return false;
}
}
public void setWater(int amount) {
this.water = amount;
}
/*
whether to change block model
*/
public boolean reduceWater() {
if (water == 0) return false;
water--;
water = Math.max(0, water);
return water == 0;
}
/*
whether to change block model
*/
public boolean reduceFertilizer() {
if (this.fertilizer != null && fertilizer.reduceTimes()) {
this.fertilizer = null;
return true;
}
return false;
}
public boolean isWet() {
return water != 0;
}
@NotNull
public String getKey() {
return key;
}
public PotConfig getConfig() {
return CustomCrops.getInstance().getPotManager().getPotConfig(key);
}
}

View File

@@ -0,0 +1,117 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.pot;
import net.momirealms.customcrops.api.object.CCFertilizer;
import net.momirealms.customcrops.api.object.Pair;
import net.momirealms.customcrops.api.object.fertilizer.Fertilizer;
import net.momirealms.customcrops.api.object.fertilizer.FertilizerConfig;
import net.momirealms.customcrops.api.object.fertilizer.FertilizerType;
import net.momirealms.customcrops.api.object.fill.PassiveFillMethod;
import net.momirealms.customcrops.api.object.hologram.FertilizerHologram;
import net.momirealms.customcrops.api.object.hologram.WaterAmountHologram;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
public class PotConfig {
private final String key;
private final HashMap<FertilizerType, Pair<String, String>> fertilizerConvertMap;
private final int max_storage;
private final Pair<String, String> pot;
private final boolean enableFertilized;
private final PassiveFillMethod[] passiveFillMethods;
private final FertilizerHologram fertilizerHologram;
private final WaterAmountHologram waterAmountHologram;
private final String potInfoItem;
public PotConfig(String key, int max_storage, String dry_pot, String wet_pot, boolean enableFertilized,
@Nullable PassiveFillMethod[] passiveFillMethods,
@Nullable FertilizerHologram fertilizerHologram,
@Nullable WaterAmountHologram waterAmountHologram,
String potInfoItem) {
this.key = key;
this.max_storage = max_storage;
this.pot = Pair.of(dry_pot, wet_pot);
this.enableFertilized = enableFertilized;
this.fertilizerConvertMap = new HashMap<>();
this.passiveFillMethods = passiveFillMethods;
this.fertilizerHologram = fertilizerHologram;
this.waterAmountHologram = waterAmountHologram;
this.potInfoItem = potInfoItem;
}
public void registerFertilizedPot(FertilizerType fertilizerType, String dry_pot, String wet_pot) {
fertilizerConvertMap.put(fertilizerType, Pair.of(dry_pot, wet_pot));
}
public String getWetPot(@Nullable CCFertilizer CCFertilizer) {
if (!enableFertilized || !(CCFertilizer instanceof Fertilizer fertilizer)) return pot.right();
FertilizerConfig fertilizerConfig = fertilizer.getConfig();
if (fertilizerConfig == null) return pot.right();
FertilizerType fertilizerType = fertilizerConfig.getFertilizerType();
Pair<String, String> pair = fertilizerConvertMap.get(fertilizerType);
if (pair == null) return pot.right();
else return pair.right();
}
public String getDryPot(@Nullable CCFertilizer CCFertilizer) {
if (!enableFertilized || !(CCFertilizer instanceof Fertilizer fertilizer)) return pot.left();
FertilizerConfig fertilizerConfig = fertilizer.getConfig();
if (fertilizerConfig == null) return pot.left();
FertilizerType fertilizerType = fertilizerConfig.getFertilizerType();
Pair<String, String> pair = fertilizerConvertMap.get(fertilizerType);
if (pair == null) return pot.left();
else return pair.left();
}
public int getMaxStorage() {
return max_storage;
}
@Nullable
public PassiveFillMethod[] getPassiveFillMethods() {
return passiveFillMethods;
}
@Nullable
public FertilizerHologram getFertilizerHologram() {
return fertilizerHologram;
}
@Nullable
public WaterAmountHologram getWaterAmountHologram() {
return waterAmountHologram;
}
@Nullable
public String getPotInfoItem() {
return potInfoItem;
}
@NotNull
public String getKey() {
return key;
}
public boolean enableFertilizedLooks() {
return enableFertilized;
}
}

View File

@@ -0,0 +1,185 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.pot;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.Function;
import net.momirealms.customcrops.api.object.basic.ConfigManager;
import net.momirealms.customcrops.api.object.fertilizer.FertilizerType;
import net.momirealms.customcrops.api.object.hologram.FertilizerHologram;
import net.momirealms.customcrops.api.object.hologram.HologramManager;
import net.momirealms.customcrops.api.object.hologram.TextDisplayMeta;
import net.momirealms.customcrops.api.object.hologram.WaterAmountHologram;
import net.momirealms.customcrops.util.AdventureUtils;
import net.momirealms.customcrops.util.ConfigUtils;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.HashMap;
import java.util.Locale;
public class PotManager extends Function {
private final CustomCrops plugin;
private final HashMap<String, PotConfig> potConfigMap;
private final HashMap<String, String> blockToPotKey;
public static boolean enableFarmLand;
public static boolean enableVanillaBlock;
public PotManager(CustomCrops plugin) {
this.plugin = plugin;
this.potConfigMap = new HashMap<>();
this.blockToPotKey = new HashMap<>();
}
@Override
public void load() {
loadConfig();
}
@Override
public void unload() {
this.potConfigMap.clear();
this.blockToPotKey.clear();
enableFarmLand = false;
enableVanillaBlock = false;
}
private void loadConfig() {
File pot_folder = new File(plugin.getDataFolder(), "contents" + File.separator + "pots");
if (!pot_folder.exists()) {
if (!pot_folder.mkdirs()) return;
ConfigUtils.getConfig("contents" + File.separator + "pots" + File.separator + "default.yml");
}
File[] files = pot_folder.listFiles();
if (files == null) return;
for (File file : files) {
YamlConfiguration config = YamlConfiguration.loadConfiguration(file);
for (String key : config.getKeys(false)) {
ConfigurationSection section = config.getConfigurationSection(key);
if (section == null) continue;
boolean enableFertilized = section.getBoolean("fertilized-pots.enable", false);
String base_dry = section.getString("base.dry");
String base_wet = section.getString("base.wet");
if (base_wet == null || base_dry == null) {
AdventureUtils.consoleMessage("<red>[CustomCrops] base.dry/base.wet is not correctly set for pot: " + key);
continue;
}
if (ConfigUtils.isVanillaItem(base_wet) || ConfigUtils.isVanillaItem(base_dry)) enableVanillaBlock = true;
blockToPotKey.put(base_wet, key);
blockToPotKey.put(base_dry, key);
PotConfig potConfig = new PotConfig(
key,
section.getInt("max-water-storage"),
base_dry,
base_wet,
enableFertilized,
ConfigUtils.getPassiveFillMethods(section.getConfigurationSection("fill-method")),
section.getBoolean("hologram.fertilizer.enable", false) ? new FertilizerHologram(
section.getString("hologram.fertilizer.content", ""),
section.getDouble("hologram.fertilizer.vertical-offset"),
HologramManager.Mode.valueOf(section.getString("hologram.type", "ARMOR_STAND").toUpperCase(Locale.ENGLISH)),
section.getInt("hologram.duration"),
new TextDisplayMeta(
section.getBoolean("hologram.text-display-options.has-shadow", false),
section.getBoolean("hologram.text-display-options.is-see-through", false),
section.getBoolean("hologram.text-display-options.use-default-background-color", false),
ConfigUtils.rgbToDecimal(section.getString("hologram.text-display-options.background-color", "0,0,0,128")),
(byte) section.getInt("hologram.text-display-options.text-opacity")
)
) : null,
section.getBoolean("hologram.water.enable", false) ? new WaterAmountHologram(
section.getString("hologram.water.content", ""),
section.getDouble("hologram.water.vertical-offset"),
HologramManager.Mode.valueOf(section.getString("hologram.type", "ARMOR_STAND").toUpperCase(Locale.ENGLISH)),
section.getInt("hologram.duration"),
section.getString("hologram.water.water-bar.left"),
section.getString("hologram.water.water-bar.full"),
section.getString("hologram.water.water-bar.empty"),
section.getString("hologram.water.water-bar.right"),
new TextDisplayMeta(
section.getBoolean("hologram.text-display-options.has-shadow", false),
section.getBoolean("hologram.text-display-options.is-see-through", false),
section.getBoolean("hologram.text-display-options.use-default-background-color", false),
ConfigUtils.rgbToDecimal(section.getString("hologram.text-display-options.background-color", "0,0,0,128")),
(byte) section.getInt("hologram.text-display-options.text-opacity")
)
) : null,
section.getString("hologram.require-item")
);
if (enableFertilized) {
ConfigurationSection fertilizedSec = section.getConfigurationSection("fertilized-pots");
if (fertilizedSec == null) continue;
for (String type : fertilizedSec.getKeys(false)) {
if (type.equals("enable")) continue;
String dry = fertilizedSec.getString(type + ".dry");
String wet = fertilizedSec.getString(type + ".wet");
blockToPotKey.put(dry, key);
blockToPotKey.put(wet, key);
switch (type) {
case "quality" -> potConfig.registerFertilizedPot(FertilizerType.QUALITY, dry, wet);
case "yield-increase" -> potConfig.registerFertilizedPot(FertilizerType.YIELD_INCREASE, dry, wet);
case "variation" -> potConfig.registerFertilizedPot(FertilizerType.VARIATION, dry, wet);
case "soil-retain" -> potConfig.registerFertilizedPot(FertilizerType.SOIL_RETAIN, dry, wet);
case "speed-grow" -> potConfig.registerFertilizedPot(FertilizerType.SPEED_GROW, dry, wet);
}
}
}
if (base_dry.equals("FARMLAND") || base_wet.equals("FARMLAND")) {
enableFarmLand = true;
if (!ConfigManager.disableMoistureMechanic && (potConfig.getPassiveFillMethods() != null || potConfig.getWaterAmountHologram() != null)) {
AdventureUtils.consoleMessage("<red>[CustomCrops] Since you are using vanilla farmland, vanilla moisture would");
AdventureUtils.consoleMessage("<red>[CustomCrops] conflict with CustomCrops' water system. It's advised to disable");
AdventureUtils.consoleMessage("<red>[CustomCrops] moisture mechanic in config.yml or delete fill-method and");
AdventureUtils.consoleMessage("<red>[CustomCrops] disable the water info hologram in pot configuration.");
}
}
potConfigMap.put(key, potConfig);
}
}
AdventureUtils.consoleMessage("[CustomCrops] Loaded <green>" + potConfigMap.size() + " <gray>pot(s)");
}
public boolean containsPotBlock(String id) {
return blockToPotKey.containsKey(id);
}
@Nullable
public PotConfig getPotConfig(String key) {
return potConfigMap.get(key);
}
@Nullable
public String getPotKeyByBlockID(String id) {
return blockToPotKey.get(id);
}
@Nullable
public PotConfig getPotConfigByBlockID(String id) {
String key = blockToPotKey.get(id);
if (key == null) return null;
return potConfigMap.get(key);
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.requirement;
import net.momirealms.customcrops.api.object.action.Action;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
import net.momirealms.customcrops.util.AdventureUtils;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
public abstract class AbstractRequirement {
protected String[] msg;
protected Action[] actions;
protected AbstractRequirement(@Nullable String[] msg, @Nullable Action[] actions) {
this.msg = msg;
this.actions = actions;
}
public void notMetActions(CurrentState currentState) {
Player player = currentState.getPlayer();
if (msg != null && player != null) {
for (String str : msg) {
AdventureUtils.playerMessage(player, str);
}
}
if (actions != null) {
for (Action action : actions) {
action.doOn(player, SimpleLocation.getByBukkitLocation(currentState.getLocation()), null);
}
}
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.requirement;
import net.momirealms.biomeapi.BiomeAPI;
import net.momirealms.customcrops.api.object.action.Action;
import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
public class BiomeImpl extends AbstractRequirement implements Requirement {
private final HashSet<String> biomes;
public BiomeImpl(@Nullable String[] msg, @Nullable Action[] actions, HashSet<String> biomes) {
super(msg, actions);
this.biomes = biomes;
}
@Override
public boolean isConditionMet(CurrentState currentState) {
String currentBiome = BiomeAPI.getBiome(currentState.getLocation());
if (biomes.contains(currentBiome)) {
return true;
}
notMetActions(currentState);
return false;
}
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.requirement;
import org.bukkit.Location;
import org.bukkit.entity.Player;
public class CurrentState {
private final Location location;
private final Player player;
public CurrentState(Location location, Player player) {
this.location = location;
this.player = player;
}
public Location getLocation() {
return location;
}
public Player getPlayer() {
return player;
}
}

View File

@@ -0,0 +1,82 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.requirement;
import net.momirealms.customcrops.api.object.action.Action;
import net.momirealms.customcrops.api.object.requirement.papi.*;
import org.bukkit.configuration.MemorySection;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class CustomPapi extends AbstractRequirement implements Requirement {
private final List<PapiRequirement> papiRequirement;
public CustomPapi(String[] msg, @Nullable Action[] actions, Map<String, Object> expressions){
super(msg, actions);
papiRequirement = getRequirements(expressions);
}
@Override
public boolean isConditionMet(CurrentState currentState) {
Player player = currentState.getPlayer();
if (currentState.getPlayer() == null) return true;
for (PapiRequirement requirement : papiRequirement) {
if (!requirement.isMet(player)) {
notMetActions(currentState);
return false;
}
}
return true;
}
private List<PapiRequirement> getRequirements(Map<String, Object> map) {
List<PapiRequirement> papiRequirements = new ArrayList<>();
map.keySet().forEach(key -> {
if (key.startsWith("&&")) {
if (map.get(key) instanceof MemorySection map2) {
papiRequirements.add(new ExpressionAnd(getRequirements(map2.getValues(false))));
}
} else if (key.startsWith("||")) {
if (map.get(key) instanceof MemorySection map2) {
papiRequirements.add(new ExpressionOr(getRequirements(map2.getValues(false))));
}
} else {
if (map.get(key) instanceof MemorySection map2) {
String type = map2.getString("type");
String papi = map2.getString("papi");
String value = map2.getString("value");
if (value == null || papi == null || type == null) return;
switch (type){
case "==" -> papiRequirements.add(new PapiEquals(papi, value));
case "!=" -> papiRequirements.add(new PapiNotEquals(papi, value));
case ">=" -> papiRequirements.add(new PapiNoLess(papi, value));
case "<=" -> papiRequirements.add(new PapiNoLarger(papi, value));
case "<" -> papiRequirements.add(new PapiSmaller(papi, value));
case ">" -> papiRequirements.add(new PapiGreater(papi, value));
}
}
}
});
return papiRequirements;
}
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.requirement;
import net.momirealms.customcrops.api.object.action.Action;
import org.jetbrains.annotations.Nullable;
import java.util.Calendar;
import java.util.HashSet;
public class DateImpl extends AbstractRequirement implements Requirement {
private final HashSet<String> dates;
public DateImpl(String[] msg, @Nullable Action[] actions, HashSet<String> dates) {
super(msg, actions);
this.dates = dates;
}
@Override
public boolean isConditionMet(CurrentState currentState) {
Calendar calendar = Calendar.getInstance();
String current = (calendar.get(Calendar.MONTH) + 1) + "/" + calendar.get(Calendar.DATE);
if (dates.contains(current)) {
return true;
}
notMetActions(currentState);
return false;
}
}

View File

@@ -0,0 +1,23 @@
package net.momirealms.customcrops.api.object.requirement;
import net.momirealms.customcrops.api.object.action.Action;
import org.jetbrains.annotations.Nullable;
public class EntityAmountInChunkImpl extends AbstractRequirement implements Requirement {
private final int amount;
public EntityAmountInChunkImpl(@Nullable String[] msg, @Nullable Action[] actions, int amount) {
super(msg, actions);
this.amount = amount;
}
@Override
public boolean isConditionMet(CurrentState currentState) {
if (currentState.getLocation().getChunk().getEntities().length <= amount) {
return true;
}
notMetActions(currentState);
return false;
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.requirement;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.action.Action;
import net.momirealms.customcrops.integration.JobInterface;
import org.jetbrains.annotations.Nullable;
public class JobLevelImpl extends AbstractRequirement implements Requirement {
private final int level;
private final String jobName;
public JobLevelImpl(@Nullable String[] msg, @Nullable Action[] actions, int level, String jobName) {
super(msg, actions);
this.level = level;
this.jobName = jobName;
}
@Override
public boolean isConditionMet(CurrentState currentState) {
JobInterface jobInterface = CustomCrops.getInstance().getIntegrationManager().getJobInterface();
if (jobInterface == null || currentState.getPlayer() == null) return true;
if (jobInterface.getLevel(currentState.getPlayer(), jobName) >= level) {
return true;
}
notMetActions(currentState);
return false;
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.requirement;
import net.momirealms.customcrops.api.object.action.Action;
import org.jetbrains.annotations.Nullable;
public class PermissionImpl extends AbstractRequirement implements Requirement {
private final String permission;
public PermissionImpl(@Nullable String[] msg, @Nullable Action[] actions, String permission) {
super(msg, actions);
this.permission = permission;
}
public String getPermission() {
return this.permission;
}
@Override
public boolean isConditionMet(CurrentState currentState) {
if (currentState.getPlayer() == null || currentState.getPlayer().hasPermission(permission)) {
return true;
}
notMetActions(currentState);
return false;
}
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.requirement;
public interface Requirement {
boolean isConditionMet(CurrentState currentState);
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.requirement;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.action.Action;
import net.momirealms.customcrops.api.object.basic.ConfigManager;
import net.momirealms.customcrops.api.object.season.CCSeason;
import net.momirealms.customcrops.api.object.world.SimpleLocation;
import net.momirealms.customcrops.api.object.world.WorldDataManager;
import net.momirealms.customcrops.integration.SeasonInterface;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class SeasonImpl extends AbstractRequirement implements Requirement {
private final List<CCSeason> seasons;
public SeasonImpl(@Nullable String[] msg, @Nullable Action[] actions, List<CCSeason> seasons) {
super(msg, actions);
this.seasons = seasons;
}
@Override
public boolean isConditionMet(CurrentState currentState) {
SeasonInterface seasonInterface = CustomCrops.getInstance().getIntegrationManager().getSeasonInterface();
CCSeason currentSeason = seasonInterface.getSeason(currentState.getLocation().getWorld().getName());
if (seasons.contains(currentSeason)) {
return true;
}
SimpleLocation simpleLocation = SimpleLocation.getByBukkitLocation(currentState.getLocation());
WorldDataManager worldDataManager = CustomCrops.getInstance().getWorldDataManager();
if (ConfigManager.enableGreenhouse) {
for (int i = 0; i < ConfigManager.greenhouseRange; i++) {
if (worldDataManager.isGreenhouse(simpleLocation.add(0, i, 0))) {
return true;
}
}
}
notMetActions(currentState);
return false;
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.requirement;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.action.Action;
import net.momirealms.customcrops.integration.SkillInterface;
import org.jetbrains.annotations.Nullable;
public class SkillLevelImpl extends AbstractRequirement implements Requirement {
private final int level;
public SkillLevelImpl(@Nullable String[] msg, @Nullable Action[] actions, int level) {
super(msg, actions);
this.level = level;
}
@Override
public boolean isConditionMet(CurrentState currentState) {
SkillInterface skillInterface = CustomCrops.getInstance().getIntegrationManager().getSkillInterface();
if (skillInterface == null || currentState.getPlayer() == null) return true;
if (skillInterface.getLevel(currentState.getPlayer()) >= level) {
return true;
}
notMetActions(currentState);
return false;
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.requirement;
import net.momirealms.customcrops.api.object.action.Action;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class TimeImpl extends AbstractRequirement implements Requirement {
private final List<String> times;
public TimeImpl(@Nullable String[] msg, @Nullable Action[] actions, List<String> times) {
super(msg, actions);
this.times = times;
}
@Override
public boolean isConditionMet(CurrentState currentState) {
long time = currentState.getLocation().getWorld().getTime();
for (String range : times) {
String[] timeMinMax = range.split("~");
if (time > Long.parseLong(timeMinMax[0]) && time < Long.parseLong(timeMinMax[1])) {
return true;
}
}
notMetActions(currentState);
return false;
}
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.requirement;
import net.momirealms.customcrops.api.object.action.Action;
import org.bukkit.World;
import org.jetbrains.annotations.Nullable;
public class WeatherImpl extends AbstractRequirement implements Requirement {
private final String[] weathers;
public WeatherImpl(@Nullable String[] msg, @Nullable Action[] actions, String[] weathers) {
super(msg, actions);
this.weathers = weathers;
}
@Override
public boolean isConditionMet(CurrentState currentState) {
World world = currentState.getLocation().getWorld();
String currentWeather;
if (world.isThundering()) currentWeather = "thunder";
else if (world.isClearWeather()) currentWeather = "clear";
else currentWeather = "rain";
for (String weather : weathers) {
if (weather.equals(currentWeather)) {
return true;
}
}
notMetActions(currentState);
return false;
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.requirement;
import net.momirealms.customcrops.api.object.action.Action;
import org.bukkit.World;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class WorldImpl extends AbstractRequirement implements Requirement {
private final List<String> worlds;
public WorldImpl(@Nullable String[] msg, @Nullable Action[] actions, List<String> worlds) {
super(msg, actions);
this.worlds = worlds;
}
@Override
public boolean isConditionMet(CurrentState currentState) {
World world = currentState.getLocation().getWorld();
if (worlds.contains(world.getName())) {
return true;
}
notMetActions(currentState);
return false;
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.requirement;
import net.momirealms.customcrops.api.object.action.Action;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class YPosImpl extends AbstractRequirement implements Requirement {
private final List<String> yPos;
public YPosImpl(@Nullable String[] msg, @Nullable Action[] actions, List<String> yPos) {
super(msg, actions);
this.yPos = yPos;
}
@Override
public boolean isConditionMet(CurrentState currentState) {
int y = (int) currentState.getLocation().getY();
for (String range : yPos) {
String[] yMinMax = range.split("~");
if (y > Integer.parseInt(yMinMax[0]) && y < Integer.parseInt(yMinMax[1])) {
return true;
}
}
notMetActions(currentState);
return false;
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.requirement.papi;
import org.bukkit.entity.Player;
import java.util.List;
public record ExpressionAnd(List<PapiRequirement> requirements) implements PapiRequirement{
@Override
public boolean isMet(Player player) {
for (PapiRequirement requirement : requirements) {
if (!requirement.isMet(player)) return false;
}
return true;
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.requirement.papi;
import org.bukkit.entity.Player;
import java.util.List;
public record ExpressionOr(List<PapiRequirement> requirements) implements PapiRequirement{
@Override
public boolean isMet(Player player) {
for (PapiRequirement requirement : requirements) {
if (requirement.isMet(player)) return true;
}
return false;
}
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.requirement.papi;
import me.clip.placeholderapi.PlaceholderAPI;
import org.bukkit.entity.Player;
import java.util.Objects;
public record PapiEquals(String papi, String requirement) implements PapiRequirement{
@Override
public boolean isMet(Player player) {
String value = PlaceholderAPI.setPlaceholders(player, papi);
return Objects.equals(value, PlaceholderAPI.setPlaceholders(player, requirement));
}
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.requirement.papi;
import me.clip.placeholderapi.PlaceholderAPI;
import org.bukkit.entity.Player;
public record PapiGreater(String papi, String requirement) implements PapiRequirement{
@Override
public boolean isMet(Player player) {
double value = Double.parseDouble(PlaceholderAPI.setPlaceholders(player, papi));
return value > Double.parseDouble(PlaceholderAPI.setPlaceholders(player, requirement));
}
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.requirement.papi;
import me.clip.placeholderapi.PlaceholderAPI;
import org.bukkit.entity.Player;
public record PapiNoLarger(String papi, String requirement) implements PapiRequirement{
@Override
public boolean isMet(Player player) {
double value = Double.parseDouble(PlaceholderAPI.setPlaceholders(player, papi));
return value <= Double.parseDouble(PlaceholderAPI.setPlaceholders(player, requirement));
}
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.requirement.papi;
import me.clip.placeholderapi.PlaceholderAPI;
import org.bukkit.entity.Player;
public record PapiNoLess(String papi, String requirement) implements PapiRequirement{
@Override
public boolean isMet(Player player) {
double value = Double.parseDouble(PlaceholderAPI.setPlaceholders(player, papi));
return value >= Double.parseDouble(PlaceholderAPI.setPlaceholders(player, requirement));
}
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.requirement.papi;
import me.clip.placeholderapi.PlaceholderAPI;
import org.bukkit.entity.Player;
import java.util.Objects;
public record PapiNotEquals(String papi, String requirement) implements PapiRequirement{
@Override
public boolean isMet(Player player) {
String value = PlaceholderAPI.setPlaceholders(player, papi);
return !Objects.equals(value, PlaceholderAPI.setPlaceholders(player, requirement));
}
}

View File

@@ -0,0 +1,24 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.requirement.papi;
import org.bukkit.entity.Player;
public interface PapiRequirement {
boolean isMet(Player player);
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.requirement.papi;
import me.clip.placeholderapi.PlaceholderAPI;
import org.bukkit.entity.Player;
public record PapiSmaller(String papi, String requirement) implements PapiRequirement{
@Override
public boolean isMet(Player player) {
double value = Double.parseDouble(PlaceholderAPI.setPlaceholders(player, papi));
return value < Double.parseDouble(PlaceholderAPI.setPlaceholders(player, requirement));
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.scheduler;
import net.momirealms.customcrops.CustomCrops;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
public class BukkitSchedulerImpl implements SchedulerPlatform {
private final CustomCrops plugin;
public BukkitSchedulerImpl(CustomCrops plugin) {
this.plugin = plugin;
}
@Override
public <T> Future<T> callSyncMethod(@NotNull Callable<T> task) {
return Bukkit.getScheduler().callSyncMethod(plugin, task);
}
@Override
public void runTask(Runnable runnable) {
Bukkit.getScheduler().runTask(plugin, runnable);
}
@Override
public void runTask(Runnable runnable, Location location) {
runTask(runnable);
}
}

View File

@@ -0,0 +1,33 @@
//package net.momirealms.customcrops.api.object.scheduler;
//
//import net.momirealms.customcrops.CustomCrops;
//import org.bukkit.Bukkit;
//import org.bukkit.Location;
//import org.jetbrains.annotations.NotNull;
//
//import java.util.concurrent.Callable;
//import java.util.concurrent.Future;
//
//public class FoliaSchedulerImpl implements SchedulerPlatform {
//
// private final CustomCrops plugin;
//
// public FoliaSchedulerImpl(CustomCrops plugin) {
// this.plugin = plugin;
// }
//
// @Override
// public <T> Future<T> callSyncMethod(@NotNull Callable<T> task) {
// return null;
// }
//
// @Override
// public void runTask(Runnable runnable) {
// Bukkit.getGlobalRegionScheduler().execute(plugin, runnable);
// }
//
// @Override
// public void runTask(Runnable runnable, Location location) {
// Bukkit.getRegionScheduler().execute(plugin, location, runnable);
// }
//}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.scheduler;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.Function;
import net.momirealms.customcrops.api.object.basic.ConfigManager;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.*;
public class Scheduler extends Function {
private final ScheduledThreadPoolExecutor schedule;
private final SchedulerPlatform schedulerPlatform;
public Scheduler(CustomCrops plugin) {
this.schedulerPlatform = new BukkitSchedulerImpl(plugin);
this.schedule = new ScheduledThreadPoolExecutor(1);
this.schedule.setMaximumPoolSize(2);
this.schedule.setKeepAliveTime(ConfigManager.keepAliveTime, TimeUnit.SECONDS);
this.schedule.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
}
@Override
public void disable() {
this.schedule.shutdown();
}
public ScheduledFuture<?> runTaskAsyncLater(Runnable runnable, long delay) {
return this.schedule.schedule(runnable, delay, TimeUnit.MILLISECONDS);
}
public void runTaskAsync(Runnable runnable) {
this.schedule.execute(runnable);
}
public void runTask(Runnable runnable) {
this.schedulerPlatform.runTask(runnable);
}
public <T> Future<T> callSyncMethod(@NotNull Callable<T> task) {
return this.schedulerPlatform.callSyncMethod(task);
}
public ScheduledFuture<?> runTaskTimerAsync(Runnable runnable, long delay, long interval) {
return this.schedule.scheduleAtFixedRate(runnable, delay, interval, TimeUnit.MILLISECONDS);
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.scheduler;
import org.bukkit.Location;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
public interface SchedulerPlatform {
<T> Future<T> callSyncMethod(@NotNull Callable<T> task);
void runTask(Runnable runnable);
void runTask(Runnable runnable, Location location);
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.season;
import net.momirealms.customcrops.api.object.CCWorldSeason;
import net.momirealms.customcrops.api.object.basic.MessageManager;
public enum CCSeason implements CCWorldSeason {
SPRING(MessageManager.spring),
SUMMER(MessageManager.summer),
AUTUMN(MessageManager.autumn),
WINTER(MessageManager.winter),
UNKNOWN(MessageManager.noSeason);
private final String display;
CCSeason(String display) {
this.display = display;
}
public String getDisplay() {
return display;
}
public String getSeason() {
return this.name();
}
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.season;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.event.SeasonChangeEvent;
import net.momirealms.customcrops.api.object.basic.ConfigManager;
import org.bukkit.Bukkit;
import java.util.Objects;
public class SeasonData {
private CCSeason ccSeason;
private int date;
private final String world;
public SeasonData(String world, CCSeason ccSeason, int date) {
this.world = world;
this.ccSeason = ccSeason;
this.date = date;
}
public SeasonData(String world) {
this.world = world;
this.ccSeason = CCSeason.SPRING;
this.date = 1;
}
public CCSeason getSeason() {
return ccSeason;
}
public int getDate() {
return date;
}
public void addDate() {
this.date++;
if (date > ConfigManager.seasonInterval) {
this.date = 1;
this.ccSeason = getNextSeason(ccSeason);
CustomCrops.getInstance().getScheduler().runTask(this::callEvent);
}
}
public CCSeason getNextSeason(CCSeason ccSeason) {
return switch (ccSeason) {
case AUTUMN -> CCSeason.WINTER;
case WINTER -> CCSeason.SPRING;
case SPRING -> CCSeason.SUMMER;
case SUMMER -> CCSeason.AUTUMN;
default -> CCSeason.UNKNOWN;
};
}
public void changeSeason(CCSeason ccSeason) {
if (ccSeason != this.ccSeason) {
this.ccSeason = ccSeason;
callEvent();
}
}
public String getWorld() {
return world;
}
public void setDate(int date) {
this.date = date;
}
private void callEvent() {
SeasonChangeEvent seasonChangeEvent = new SeasonChangeEvent(Objects.requireNonNull(Bukkit.getWorld(world)), ccSeason);
Bukkit.getPluginManager().callEvent(seasonChangeEvent);
}
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customcrops.api.object.season;
import net.momirealms.customcrops.CustomCrops;
import net.momirealms.customcrops.api.object.Function;
import net.momirealms.customcrops.api.object.basic.ConfigManager;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.ConcurrentHashMap;
public class SeasonManager extends Function {
private final CustomCrops plugin;
private final ConcurrentHashMap<String, SeasonData> seasonMap;
public SeasonManager(CustomCrops plugin) {
this.plugin = plugin;
this.seasonMap = new ConcurrentHashMap<>(4);
}
@Override
public void disable() {
this.seasonMap.clear();
}
@Nullable
public SeasonData getSeasonData(String world) {
return seasonMap.get(world);
}
public void loadSeasonData(SeasonData seasonData) {
seasonMap.put(seasonData.getWorld(), seasonData);
}
@Nullable
public SeasonData unloadSeasonData(String world) {
return seasonMap.remove(world);
}
public CCSeason getSeason(String world) {
SeasonData seasonData = seasonMap.get(ConfigManager.syncSeason ? ConfigManager.referenceWorld : world);
if (seasonData == null) {
return CCSeason.UNKNOWN;
}
return seasonData.getSeason();
}
public void addDate(String world) {
SeasonData seasonData = seasonMap.get(world);
if (seasonData != null) seasonData.addDate();
}
public int getDate(String world) {
SeasonData seasonData = seasonMap.get(ConfigManager.syncSeason ? ConfigManager.referenceWorld : world);
if (seasonData == null) return -1;
return seasonData.getDate();
}
}

Some files were not shown because too many files have changed in this diff Show More