diff --git a/build.gradle b/build.gradle index 60c8ea2..26f9d88 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ plugins { } group = 'net.momirealms' -version = '3.0.0-beta2' +version = '3.0.0' repositories { mavenCentral() diff --git a/src/main/java/net/momirealms/customcrops/CustomCrops.java b/src/main/java/net/momirealms/customcrops/CustomCrops.java index 572c4a8..b3917f5 100644 --- a/src/main/java/net/momirealms/customcrops/CustomCrops.java +++ b/src/main/java/net/momirealms/customcrops/CustomCrops.java @@ -85,6 +85,7 @@ public final class CustomCrops extends JavaPlugin { @Override public void onEnable() { adventure = BukkitAudiences.create(this); + protocolManager = ProtocolLibrary.getProtocolManager(); this.versionHelper = new VersionHelper(this); if (versionHelper.isSpigot()) { AdventureUtils.consoleMessage("========================[CustomCrops]========================="); @@ -96,10 +97,9 @@ public final class CustomCrops extends JavaPlugin { return; } - protocolManager = ProtocolLibrary.getProtocolManager(); - AdventureUtils.consoleMessage("[CustomCrops] Running on " + Bukkit.getVersion()); + if (!this.loadPlatform()) return; this.registerCommands(); - this.loadPlatform(); + AdventureUtils.consoleMessage("[CustomCrops] Running on " + Bukkit.getVersion()); ProtectionLib.hook(); this.scheduler = new Scheduler(this); @@ -191,7 +191,7 @@ public final class CustomCrops extends JavaPlugin { } } - private void loadPlatform() { + private boolean loadPlatform() { PluginManager pluginManager = Bukkit.getPluginManager(); if (pluginManager.isPluginEnabled("ItemsAdder")) { this.platform = Platform.ItemsAdder; @@ -202,11 +202,17 @@ public final class CustomCrops extends JavaPlugin { this.platformInterface = new OraxenPluginImpl(); } if (this.platform == null) { + AdventureUtils.consoleMessage("========================[CustomCrops]========================="); + AdventureUtils.consoleMessage(" Please install ItemsAdder or Oraxen as dependency."); + AdventureUtils.consoleMessage(" ItemsAdder Link: https://www.spigotmc.org/resources/73355/"); + AdventureUtils.consoleMessage(" Oraxen link: https://www.spigotmc.org/resources/72448/"); + AdventureUtils.consoleMessage("=============================================================="); Bukkit.getPluginManager().disablePlugin(this); - AdventureUtils.consoleMessage("[CustomCrops] Please install ItemsAdder/Oraxen"); + return false; } else { - AdventureUtils.consoleMessage("[CustomCrops] Platform: " + platform.name()); + AdventureUtils.consoleMessage("[CustomCrops] Platform: " + platform.name()); + return true; } } diff --git a/src/main/java/net/momirealms/customcrops/api/customplugin/PlatformInterface.java b/src/main/java/net/momirealms/customcrops/api/customplugin/PlatformInterface.java index ddc4c89..b5ede58 100644 --- a/src/main/java/net/momirealms/customcrops/api/customplugin/PlatformInterface.java +++ b/src/main/java/net/momirealms/customcrops/api/customplugin/PlatformInterface.java @@ -17,12 +17,15 @@ package net.momirealms.customcrops.api.customplugin; +import io.th0rgal.oraxen.api.OraxenFurniture; +import io.th0rgal.oraxen.mechanics.provided.gameplay.furniture.FurnitureMechanic; import net.momirealms.customcrops.CustomCrops; import net.momirealms.customcrops.api.object.ItemMode; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.entity.Entity; +import org.bukkit.entity.Interaction; import org.bukkit.entity.ItemDisplay; import org.bukkit.entity.ItemFrame; import org.bukkit.inventory.ItemStack; @@ -138,7 +141,7 @@ public interface PlatformInterface { @Nullable default ItemDisplay getItemDisplayAt(Location location) { - Collection itemDisplays = location.clone().add(0.5,0.5,0.5).getNearbyEntitiesByType(ItemDisplay.class, 0.5, 0.5, 0.5); + Collection itemDisplays = location.clone().add(0.5,0,0.5).getNearbyEntitiesByType(ItemDisplay.class, 0.5, 0.5, 0.5); int i = itemDisplays.size(); int j = 1; for (ItemDisplay itemDisplay : itemDisplays) { @@ -155,15 +158,21 @@ public interface PlatformInterface { ItemFrame itemFrame = getItemFrameAt(location); if (itemFrame != null) { itemFrame.remove(); + if (CustomCrops.getInstance().getVersionHelper().isVersionNewerThan1_19_R3()) removeInteractions(location); return true; } return false; } + default void removeInteractions(Location location) { + location.clone().add(0.5,0.5,0.5).getNearbyEntitiesByType(Interaction.class, 0.5, 0.5, 0.5).forEach(Entity::remove); + } + default boolean removeItemDisplay(Location location) { ItemDisplay itemDisplay = getItemDisplayAt(location); if (itemDisplay != null) { itemDisplay.remove(); + removeInteractions(location); return true; } return false; @@ -177,7 +186,7 @@ public interface PlatformInterface { } default boolean detectItemDisplay(Location location) { - Collection entities = location.clone().add(0.5,0.5,0.5).getNearbyEntitiesByType(ItemDisplay.class, 0.5, 0.5, 0.5); + Collection entities = location.clone().add(0.5,0,0.5).getNearbyEntitiesByType(ItemDisplay.class, 0.5, 0.5, 0.5); return entities.size() != 0; } diff --git a/src/main/java/net/momirealms/customcrops/api/customplugin/PlatformManager.java b/src/main/java/net/momirealms/customcrops/api/customplugin/PlatformManager.java index 54c20cf..3583a0f 100644 --- a/src/main/java/net/momirealms/customcrops/api/customplugin/PlatformManager.java +++ b/src/main/java/net/momirealms/customcrops/api/customplugin/PlatformManager.java @@ -48,6 +48,7 @@ import net.momirealms.customcrops.api.util.AdventureUtils; import net.momirealms.protectionlib.ProtectionLib; import org.bukkit.*; import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; @@ -58,6 +59,8 @@ import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.Nullable; +import java.util.Arrays; +import java.util.HashSet; import java.util.List; import java.util.Objects; @@ -65,6 +68,7 @@ public class PlatformManager extends Function { private final CustomCrops plugin; private final Handler handler; + private static final HashSet REPLACEABLE = new HashSet<>(Arrays.asList(Material.SNOW, Material.VINE, Material.GRASS, Material.TALL_GRASS, Material.SEAGRASS, Material.FERN, Material.LARGE_FERN, Material.AIR)); public PlatformManager(CustomCrops plugin) { this.plugin = plugin; @@ -134,13 +138,13 @@ public class PlatformManager extends Function { Block block = event.getClickedBlock(); String id = plugin.getPlatformInterface().getBlockID(block); assert block != null; - onInteractSomething(event.getPlayer(), block.getLocation(), id, event); + onInteractSomething(event.getPlayer(), block.getLocation(), id, event.getBlockFace(), event); } } public void onInteractFurniture(Player player, Entity entity, String id, Cancellable event) { if (event.isCancelled()) return; - onInteractSomething(player, entity.getLocation().getBlock().getLocation(), id, event); + onInteractSomething(player, entity.getLocation().getBlock().getLocation(), id, null, event); } public void onInteractAir(Player player) { @@ -190,7 +194,7 @@ public class PlatformManager extends Function { } } - void onInteractSomething(Player player, Location location, String id, Cancellable event) { + void onInteractSomething(Player player, Location location, String id, @Nullable BlockFace blockFace, Cancellable event) { ItemStack item_in_hand = player.getInventory().getItemInMainHand(); String item_in_hand_id = plugin.getPlatformInterface().getItemStackID(item_in_hand); @@ -202,7 +206,7 @@ public class PlatformManager extends Function { } if (ProtectionLib.canPlace(player, location)) { - if (onInteractWithSprinkler(player, location, item_in_hand, item_in_hand_id)) { + if (onInteractWithSprinkler(player, location, item_in_hand, item_in_hand_id, blockFace)) { return; } @@ -402,14 +406,13 @@ public class PlatformManager extends Function { } } - public boolean onInteractWithSprinkler(Player player, Location location, ItemStack item_in_hand, String item_in_hand_id) { + public boolean onInteractWithSprinkler(Player player, Location location, ItemStack item_in_hand, String item_in_hand_id, @Nullable BlockFace blockFace) { SprinklerConfig sprinklerConfig = plugin.getSprinklerManager().getConfigByItemID(item_in_hand_id); if (sprinklerConfig == null) { return false; } - // Prevent player from placing sprinkler on furniture - if (location.getBlock().getType() == Material.AIR) { + if (blockFace != BlockFace.UP || REPLACEABLE.contains(location.getBlock().getType())) { return true; } @@ -902,20 +905,22 @@ public class PlatformManager extends Function { int add = 0; - if (id != null && location != null) { - for (PositiveFillMethod positiveFillMethod : wateringCanConfig.getPositiveFillMethods()) { - if (positiveFillMethod.getId().equals(id)) { - add = positiveFillMethod.getAmount(); - if (positiveFillMethod.getSound() != null) { - AdventureUtils.playerSound(player, positiveFillMethod.getSound()); + outer: { + if (id != null && location != null) { + for (PositiveFillMethod positiveFillMethod : wateringCanConfig.getPositiveFillMethods()) { + if (positiveFillMethod.getId().equals(id)) { + add = positiveFillMethod.getAmount(); + if (positiveFillMethod.getSound() != null) { + AdventureUtils.playerSound(player, positiveFillMethod.getSound()); + } + if (positiveFillMethod.getParticle() != null) { + location.getWorld().spawnParticle(positiveFillMethod.getParticle(), location.clone().add(0.5,1.1, 0.5),5,0.1,0.1,0.1); + } + break outer; } - if (positiveFillMethod.getParticle() != null) { - location.getWorld().spawnParticle(positiveFillMethod.getParticle(), location.clone().add(0.5,1.1, 0.5),5,0.1,0.1,0.1); - } - break; } } - } else { + List lineOfSight = player.getLineOfSight(null, 5); List blockIds = lineOfSight.stream().map(block -> plugin.getPlatformInterface().getBlockID(block)).toList(); diff --git a/src/main/java/net/momirealms/customcrops/api/object/CrowTask.java b/src/main/java/net/momirealms/customcrops/api/object/CrowTask.java index 09f96f0..06e5e39 100644 --- a/src/main/java/net/momirealms/customcrops/api/object/CrowTask.java +++ b/src/main/java/net/momirealms/customcrops/api/object/CrowTask.java @@ -23,59 +23,48 @@ 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.ScheduledFuture; import java.util.concurrent.ThreadLocalRandom; -public class CrowTask implements Runnable { +public class CrowTask extends BukkitRunnable { private int timer; private final int entityID; - private final Vector vectorDown; private final Vector vectorUp; private final Location from; private final Player player; private final float yaw; private final ItemStack fly; - private final ItemStack stand; - private ScheduledFuture scheduledFuture; public CrowTask(Player player, Location crop, String fly_model, String stand_model) { this.timer = 0; this.fly = CustomCrops.getInstance().getIntegrationManager().build(fly_model); - this.stand = CustomCrops.getInstance().getIntegrationManager().build(stand_model); + ItemStack stand = CustomCrops.getInstance().getIntegrationManager().build(stand_model); this.player = player; this.entityID = ThreadLocalRandom.current().nextInt(Integer.MAX_VALUE); this.yaw = ThreadLocalRandom.current().nextInt(361) - 180; this.from = crop.clone().add(10 * Math.sin((Math.PI * yaw)/180), 10, - 10 * Math.cos((Math.PI * yaw)/180)); Location relative = crop.clone().subtract(from); - this.vectorDown = new Vector(relative.getX() / 100, -0.1, relative.getZ() / 100); - this.vectorUp = new Vector(relative.getX() / 100, 0.1, relative.getZ() / 100); - CustomCrops.getProtocolManager().sendServerPacket(player, FakeEntityUtils.getSpawnPacket(entityID, from, EntityType.ARMOR_STAND)); + this.vectorUp = new Vector(relative.getX() / 50, 0.1, relative.getZ() / 50); + CustomCrops.getProtocolManager().sendServerPacket(player, FakeEntityUtils.getSpawnPacket(entityID, crop, EntityType.ARMOR_STAND)); CustomCrops.getProtocolManager().sendServerPacket(player, FakeEntityUtils.getVanishArmorStandMetaPacket(entityID)); - CustomCrops.getProtocolManager().sendServerPacket(player, FakeEntityUtils.getEquipPacket(entityID, fly)); + CustomCrops.getProtocolManager().sendServerPacket(player, FakeEntityUtils.getEquipPacket(entityID, stand)); } @Override public void run() { timer++; - if (timer < 100) { - CustomCrops.getProtocolManager().sendServerPacket(player, FakeEntityUtils.getTeleportPacket(entityID, from.add(vectorDown), yaw)); - } else if (timer == 100){ - CustomCrops.getProtocolManager().sendServerPacket(player, FakeEntityUtils.getEquipPacket(entityID, stand)); - } else if (timer == 150) { + if (timer == 30) { CustomCrops.getProtocolManager().sendServerPacket(player, FakeEntityUtils.getEquipPacket(entityID, fly)); - } else if (timer > 150) { + } else if (timer > 30) { CustomCrops.getProtocolManager().sendServerPacket(player, FakeEntityUtils.getTeleportPacket(entityID, from.add(vectorUp), yaw)); } - if (timer > 300) { + if (timer > 100) { CustomCrops.getProtocolManager().sendServerPacket(player, FakeEntityUtils.getDestroyPacket(entityID)); - if (scheduledFuture != null) scheduledFuture.cancel(false); + cancel(); } } - - public void setScheduledFuture(ScheduledFuture scheduledFuture) { - this.scheduledFuture = scheduledFuture; - } } \ No newline at end of file diff --git a/src/main/java/net/momirealms/customcrops/api/object/action/BreakImpl.java b/src/main/java/net/momirealms/customcrops/api/object/action/BreakImpl.java index 408cef4..f5b3774 100644 --- a/src/main/java/net/momirealms/customcrops/api/object/action/BreakImpl.java +++ b/src/main/java/net/momirealms/customcrops/api/object/action/BreakImpl.java @@ -37,10 +37,9 @@ public class BreakImpl implements Action { @Override public void doOn(@Nullable Player player, @Nullable SimpleLocation crop_loc, ItemMode itemMode) { if (crop_loc == null) return; - CustomCrops.getInstance().getScheduler().callSyncMethod(() -> { + CustomCrops.getInstance().getScheduler().runTask(() -> { CustomCrops.getInstance().getPlatformInterface().removeCustomItem(crop_loc.getBukkitLocation(), itemMode); CustomCrops.getInstance().getWorldDataManager().removeCropData(crop_loc); - return null; }); if (triggerAction && stage_id != null) { StageConfig stageConfig = CustomCrops.getInstance().getCropManager().getStageConfig(stage_id); diff --git a/src/main/java/net/momirealms/customcrops/api/object/basic/ConfigManager.java b/src/main/java/net/momirealms/customcrops/api/object/basic/ConfigManager.java index a0838a6..28ce79e 100644 --- a/src/main/java/net/momirealms/customcrops/api/object/basic/ConfigManager.java +++ b/src/main/java/net/momirealms/customcrops/api/object/basic/ConfigManager.java @@ -23,6 +23,7 @@ import net.momirealms.customcrops.api.util.ConfigUtils; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; +import java.io.File; import java.util.HashSet; import java.util.Objects; @@ -69,7 +70,7 @@ public class ConfigManager extends Function { } private void loadConfig() { - ConfigUtils.update("config.yml"); + 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"); diff --git a/src/main/java/net/momirealms/customcrops/api/object/condition/Condition.java b/src/main/java/net/momirealms/customcrops/api/object/condition/Condition.java index e9c21a1..80ad9ab 100644 --- a/src/main/java/net/momirealms/customcrops/api/object/condition/Condition.java +++ b/src/main/java/net/momirealms/customcrops/api/object/condition/Condition.java @@ -22,8 +22,4 @@ import net.momirealms.customcrops.api.object.world.SimpleLocation; public interface Condition { boolean isMet(SimpleLocation simpleLocation); - - default int getDelay() { - return 0; - } } diff --git a/src/main/java/net/momirealms/customcrops/api/object/condition/CrowAttack.java b/src/main/java/net/momirealms/customcrops/api/object/condition/CrowAttack.java index 830ecb8..75d6db7 100644 --- a/src/main/java/net/momirealms/customcrops/api/object/condition/CrowAttack.java +++ b/src/main/java/net/momirealms/customcrops/api/object/condition/CrowAttack.java @@ -24,8 +24,6 @@ import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.entity.Player; -import java.util.concurrent.ScheduledFuture; - public class CrowAttack implements Condition { private final double chance; @@ -42,20 +40,16 @@ public class CrowAttack implements Condition { public boolean isMet(SimpleLocation simpleLocation) { if (Math.random() > chance) return false; Location location = simpleLocation.getBukkitLocation(); - if (location == null || CustomCrops.getInstance().getWorldDataManager().hasScarecrow(simpleLocation)) return false; + if (location == null || CustomCrops.getInstance().getWorldDataManager().hasScarecrow(simpleLocation)) return true; for (Player player : Bukkit.getOnlinePlayers()) { SimpleLocation playerLoc = SimpleLocation.getByBukkitLocation(player.getLocation()); if (playerLoc.isNear(simpleLocation, 48)) { - CrowTask crowTask = new CrowTask(player, location.clone().add(0.4,0,0.4), fly_model, stand_model); - ScheduledFuture scheduledFuture = CustomCrops.getInstance().getScheduler().runTaskTimerAsync(crowTask, 50, 50); - crowTask.setScheduledFuture(scheduledFuture); + CustomCrops.getInstance().getScheduler().callSyncMethod(() -> { + new CrowTask(player, location, fly_model, stand_model).runTaskTimerAsynchronously(CustomCrops.getInstance(), 1, 1); + return null; + }); } } return true; } - - @Override - public int getDelay() { - return 7000; - } } \ No newline at end of file diff --git a/src/main/java/net/momirealms/customcrops/api/object/condition/DeathCondition.java b/src/main/java/net/momirealms/customcrops/api/object/condition/DeathCondition.java index 9eb55e8..23b1989 100644 --- a/src/main/java/net/momirealms/customcrops/api/object/condition/DeathCondition.java +++ b/src/main/java/net/momirealms/customcrops/api/object/condition/DeathCondition.java @@ -34,13 +34,13 @@ public class DeathCondition { this.conditions = conditions; } - public int checkIfDead(SimpleLocation simpleLocation) { + public boolean checkIfDead(SimpleLocation simpleLocation) { for (Condition condition : conditions) { if (condition.isMet(simpleLocation)) { - return condition.getDelay(); + return true; } } - return -1; + return false; } public void applyDeadModel(SimpleLocation simpleLocation, ItemMode itemMode) { diff --git a/src/main/java/net/momirealms/customcrops/api/object/crop/CropManager.java b/src/main/java/net/momirealms/customcrops/api/object/crop/CropManager.java index 092c630..9d4f82b 100644 --- a/src/main/java/net/momirealms/customcrops/api/object/crop/CropManager.java +++ b/src/main/java/net/momirealms/customcrops/api/object/crop/CropManager.java @@ -18,6 +18,7 @@ package net.momirealms.customcrops.api.object.crop; import net.momirealms.customcrops.CustomCrops; +import net.momirealms.customcrops.api.customplugin.Platform; import net.momirealms.customcrops.api.object.Function; import net.momirealms.customcrops.api.object.ItemMode; import net.momirealms.customcrops.api.object.condition.Condition; @@ -27,12 +28,14 @@ import net.momirealms.customcrops.api.util.AdventureUtils; import net.momirealms.customcrops.api.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; @@ -47,6 +50,7 @@ public class CropManager extends Function implements Listener { private final HashMap cropConfigMap; private final HashMap stageConfigMap; private final HashSet deadCrops; + private boolean hasCheckedTripwire; public CropManager(CustomCrops plugin) { this.plugin = plugin; @@ -77,7 +81,7 @@ public class CropManager extends Function implements Listener { File crop_folder = new File(plugin.getDataFolder(), "contents" + File.separator + "crops"); if (!crop_folder.exists()) { if (!crop_folder.mkdirs()) return; - plugin.saveResource("contents" + File.separator + "crops" + File.separator + "tomato.yml", false); + ConfigUtils.getConfig("contents" + File.separator + "crops" + File.separator + "tomato.yml"); } File[] files = crop_folder.listFiles(); if (files == null) return; @@ -87,6 +91,9 @@ public class CropManager extends Function implements Listener { ConfigurationSection cropSec = config.getConfigurationSection(key); if (cropSec == null) continue; ItemMode itemMode = ItemMode.valueOf(cropSec.getString("type", "TripWire").toUpperCase()); + if (itemMode == ItemMode.TRIPWIRE && !hasCheckedTripwire) { + checkTripwire(); + } String[] bottomBlocks = cropSec.getStringList("pot-whitelist").toArray(new String[0]); if (bottomBlocks.length == 0) { AdventureUtils.consoleMessage("[CustomCrops] pot-whitelist is not set for crop: " + key); @@ -185,7 +192,7 @@ public class CropManager extends Function implements Listener { if (event.isCancelled()) return; Item item = event.getEntity(); String id = plugin.getPlatformInterface().getItemStackID(item.getItemStack()); - if (containsStage(id)) { + if (containsStage(id) || isDeadCrop(id)) { event.setCancelled(true); } } @@ -198,4 +205,38 @@ public class CropManager extends Function implements Listener { 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("========================[CustomCrops]========================="); + AdventureUtils.consoleMessage(" Detected that one of your crops is using TRIPWIRE type"); + AdventureUtils.consoleMessage(" If you want to use tripwire for custom crops, please set"); + AdventureUtils.consoleMessage("\"blocks.disable-REAL_WIRE: false\" in /ItemsAdder/config.yml"); + AdventureUtils.consoleMessage(" Change this setting requires a server restart"); + AdventureUtils.consoleMessage(" If you have problems with which one to use, read the wiki."); + AdventureUtils.consoleMessage("=============================================================="); + } + } + } 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("========================[CustomCrops]========================="); + AdventureUtils.consoleMessage(" Detected that one of your crops is using TRIPWIRE type"); + AdventureUtils.consoleMessage(" If you want to use tripwire for custom crops, please set"); + AdventureUtils.consoleMessage(" \"stringblock.enabled: true\" in /Oraxen/mechanics.yml"); + AdventureUtils.consoleMessage(" If you have problems with which one to use, read the wiki."); + AdventureUtils.consoleMessage("=============================================================="); + } + } + } + } } diff --git a/src/main/java/net/momirealms/customcrops/api/object/fertilizer/FertilizerManager.java b/src/main/java/net/momirealms/customcrops/api/object/fertilizer/FertilizerManager.java index faa25bd..67e018e 100644 --- a/src/main/java/net/momirealms/customcrops/api/object/fertilizer/FertilizerManager.java +++ b/src/main/java/net/momirealms/customcrops/api/object/fertilizer/FertilizerManager.java @@ -79,11 +79,11 @@ public class FertilizerManager extends Function { File can_folder = new File(plugin.getDataFolder(), "contents" + File.separator + "fertilizers"); if (!can_folder.exists()) { if (!can_folder.mkdirs()) return; - plugin.saveResource("contents" + File.separator + "fertilizers" + File.separator + "speed-grow.yml", false); - plugin.saveResource("contents" + File.separator + "fertilizers" + File.separator + "quality.yml", false); - plugin.saveResource("contents" + File.separator + "fertilizers" + File.separator + "soil-retain.yml", false); - plugin.saveResource("contents" + File.separator + "fertilizers" + File.separator + "yield-increase.yml", false); - plugin.saveResource("contents" + File.separator + "fertilizers" + File.separator + "variation.yml", false); + 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; diff --git a/src/main/java/net/momirealms/customcrops/api/object/pot/PotManager.java b/src/main/java/net/momirealms/customcrops/api/object/pot/PotManager.java index b2d5d14..8dfc411 100644 --- a/src/main/java/net/momirealms/customcrops/api/object/pot/PotManager.java +++ b/src/main/java/net/momirealms/customcrops/api/object/pot/PotManager.java @@ -61,7 +61,7 @@ public class PotManager extends Function { File pot_folder = new File(plugin.getDataFolder(), "contents" + File.separator + "pots"); if (!pot_folder.exists()) { if (!pot_folder.mkdirs()) return; - plugin.saveResource("contents" + File.separator + "pots" + File.separator + "default.yml", false); + ConfigUtils.getConfig("contents" + File.separator + "pots" + File.separator + "default.yml"); } File[] files = pot_folder.listFiles(); if (files == null) return; diff --git a/src/main/java/net/momirealms/customcrops/api/object/scheduler/Scheduler.java b/src/main/java/net/momirealms/customcrops/api/object/scheduler/Scheduler.java index 4d5ab4e..e8fc49f 100644 --- a/src/main/java/net/momirealms/customcrops/api/object/scheduler/Scheduler.java +++ b/src/main/java/net/momirealms/customcrops/api/object/scheduler/Scheduler.java @@ -34,7 +34,7 @@ public class Scheduler extends Function { this.schedule = new ScheduledThreadPoolExecutor(1); this.schedule.setMaximumPoolSize(2); this.schedule.setKeepAliveTime(ConfigManager.keepAliveTime, TimeUnit.SECONDS); - this.schedule.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy()); + this.schedule.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy()); } @Override diff --git a/src/main/java/net/momirealms/customcrops/api/object/sprinkler/SprinklerManager.java b/src/main/java/net/momirealms/customcrops/api/object/sprinkler/SprinklerManager.java index 6086cce..b74acc8 100644 --- a/src/main/java/net/momirealms/customcrops/api/object/sprinkler/SprinklerManager.java +++ b/src/main/java/net/momirealms/customcrops/api/object/sprinkler/SprinklerManager.java @@ -72,7 +72,7 @@ public class SprinklerManager extends Function implements Listener { File sprinkler_folder = new File(plugin.getDataFolder(), "contents" + File.separator + "sprinklers"); if (!sprinkler_folder.exists()) { if (!sprinkler_folder.mkdirs()) return; - plugin.saveResource("contents" + File.separator + "sprinklers" + File.separator + "default.yml", false); + ConfigUtils.getConfig("contents" + File.separator + "sprinklers" + File.separator + "default.yml"); } File[] files = sprinkler_folder.listFiles(); if (files == null) return; diff --git a/src/main/java/net/momirealms/customcrops/api/object/wateringcan/WateringCanManager.java b/src/main/java/net/momirealms/customcrops/api/object/wateringcan/WateringCanManager.java index 9928c64..e04e161 100644 --- a/src/main/java/net/momirealms/customcrops/api/object/wateringcan/WateringCanManager.java +++ b/src/main/java/net/momirealms/customcrops/api/object/wateringcan/WateringCanManager.java @@ -67,7 +67,7 @@ public class WateringCanManager extends Function { File can_folder = new File(plugin.getDataFolder(), "contents" + File.separator + "watering-cans"); if (!can_folder.exists()) { if (!can_folder.mkdirs()) return; - plugin.saveResource("contents" + File.separator + "watering-cans" + File.separator + "default.yml", false); + ConfigUtils.getConfig("contents" + File.separator + "watering-cans" + File.separator + "default.yml"); } File[] files = can_folder.listFiles(); if (files == null) return; diff --git a/src/main/java/net/momirealms/customcrops/api/object/world/CCWorld.java b/src/main/java/net/momirealms/customcrops/api/object/world/CCWorld.java index 98a7052..8e7337b 100644 --- a/src/main/java/net/momirealms/customcrops/api/object/world/CCWorld.java +++ b/src/main/java/net/momirealms/customcrops/api/object/world/CCWorld.java @@ -18,6 +18,7 @@ package net.momirealms.customcrops.api.object.world; import net.momirealms.customcrops.CustomCrops; +import net.momirealms.customcrops.api.object.CrowTask; import net.momirealms.customcrops.api.object.Function; import net.momirealms.customcrops.api.object.ItemMode; import net.momirealms.customcrops.api.object.action.Action; @@ -71,7 +72,8 @@ public class CCWorld extends Function { private final GenericObjectPool consumeTaskPool; private long lastWorkDay; private long lastConsumeDay; - private ScheduledFuture scheduledTimerTask; + private ScheduledFuture timerTask; + private int timer; public CCWorld(World world) { this.world = new WeakReference<>(world); @@ -90,6 +92,7 @@ public class CCWorld extends Function { this.consumeTaskPool = new GenericObjectPool<>(new ConsumeTaskFactory(), new GenericObjectPoolConfig<>()); this.consumeTaskPool.setMaxTotal(10); this.consumeTaskPool.setMinIdle(1); + this.timer = 10; } @Override @@ -124,7 +127,6 @@ public class CCWorld extends Function { } this.lastConsumeDay = dataFile.getLong("last-consume-day", 0); this.lastWorkDay = dataFile.getLong("last-work-day", 0); - this.arrangeTask(); } @Override @@ -169,60 +171,55 @@ public class CCWorld extends Function { } public void load() { - if (this.scheduledTimerTask == null) { - this.scheduledTimerTask = this.schedule.scheduleAtFixedRate(() -> { - for (CCChunk chunk : chunkMap.values()) { - chunk.scheduleGrowTask(this); + timer = ConfigManager.pointGainInterval; + if (this.timerTask == null) { + this.timerTask = CustomCrops.getInstance().getScheduler().runTaskTimerAsync(() -> { + if (ConfigManager.debug) Log.info("Task queue size: " + schedule.getQueue().size()); + World current = world.get(); + if (current != null) { + long fullTime = current.getFullTime(); + long day = fullTime / 24000; + long time = current.getTime(); + if (time < 60 && day != lastConsumeDay) { + lastConsumeDay = day; + if (ConfigManager.enableSeason && !ConfigManager.rsHook && ConfigManager.autoSeasonChange) { + CustomCrops.getInstance().getSeasonManager().addDate(worldName); + } + if (ConfigManager.enableScheduleSystem) { + scheduleConsumeTask(); + } + } + else if (time > 1970 && time < 2030 && lastWorkDay != day) { + lastWorkDay = day; + if (ConfigManager.enableScheduleSystem) { + scheduleSprinklerWork(); + } + } + timer--; + if (timer <= 0) { + if (ConfigManager.debug) Log.info("== Grow point =="); + timer = ConfigManager.pointGainInterval; + for (CCChunk chunk : chunkMap.values()) { + chunk.scheduleGrowTask(this); + } + } } - }, ThreadLocalRandom.current().nextInt(20), ConfigManager.pointGainInterval, TimeUnit.SECONDS); + else { + this.schedule.shutdown(); + } + }, 1000, 1000L); } } public void unload() { - if (this.scheduledTimerTask != null) { - this.scheduledTimerTask.cancel(false); - this.scheduledTimerTask = null; + if (this.timerTask != null) { + this.timerTask.cancel(false); + this.timerTask = null; } } - /** - * Some season plugin would change the length of a day - * So a flag is needed to ensure that all the function would only work once - */ - private void arrangeTask() { - this.schedule.scheduleAtFixedRate(() -> { - World current = world.get(); - if (current != null) { - long fullTime = current.getFullTime(); - long day = fullTime / 24000; - long time = current.getTime(); - if (time < 100 && day != lastConsumeDay) { - lastConsumeDay = day; - if (ConfigManager.enableSeason && !ConfigManager.rsHook && ConfigManager.autoSeasonChange) { - CustomCrops.getInstance().getSeasonManager().addDate(worldName); - } - if (ConfigManager.enableScheduleSystem) { - scheduleConsumeTask(); - } - } - else if (time > 1950 && time < 2050 && lastWorkDay != day) { - lastWorkDay = day; - if (ConfigManager.enableScheduleSystem) { - scheduleSprinklerWork(); - } - } - } - else { - this.schedule.shutdown(); - } - }, 2, 2, TimeUnit.SECONDS); - } - private void closePool() { this.schedule.shutdown(); - //this.cropTaskPool.close(); - //this.sprinklerTaskPool.close(); - //this.consumeTaskPool.close(); } public void pushCropTask(SimpleLocation simpleLocation, int delay) { @@ -426,18 +423,9 @@ public class CCWorld extends Function { DeathCondition[] deathConditions = cropConfig.getDeathConditions(); if (deathConditions != null) { for (DeathCondition deathCondition : deathConditions) { - int delay = deathCondition.checkIfDead(simpleLocation); - if (delay != -1) { - if (delay == 0) { - removeCropData(simpleLocation); - deathCondition.applyDeadModel(simpleLocation, itemMode); - } else { - SimpleLocation copied = simpleLocation.copy(); - schedule.schedule(() -> { - removeCropData(copied); - deathCondition.applyDeadModel(copied, itemMode); - }, delay, TimeUnit.MILLISECONDS); - } + if (deathCondition.checkIfDead(simpleLocation)) { + removeCropData(simpleLocation); + deathCondition.applyDeadModel(simpleLocation, itemMode); return; } } @@ -504,7 +492,6 @@ public class CCWorld extends Function { } growingCrop.setPoints(current + points); - if (ConfigManager.debug) Log.info(simpleLocation.toString() + ":" + growingCrop.getPoints()); if (growingCrop.getPoints() >= cropConfig.getMaxPoints()) { removeCropData(simpleLocation); } @@ -518,23 +505,32 @@ public class CCWorld extends Function { chunk.getEntities(); return chunk.isEntitiesLoaded(); }); - loadEntities.whenComplete((result, throwable) -> - CustomCrops.getInstance().getScheduler().callSyncMethod(() -> { + loadEntities.whenComplete((result, throwable) -> { + CustomCrops.getInstance().getScheduler().callSyncMethod(() -> { + try { if (CustomCrops.getInstance().getPlatformInterface().removeCustomItem(location, itemMode)) { CustomCrops.getInstance().getPlatformInterface().placeCustomItem(location, finalNextModel, itemMode); } else { removeCropData(simpleLocation); } - return null; - })); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + }); + }); } else { asyncGetChunk.whenComplete((result, throwable) -> CustomCrops.getInstance().getScheduler().callSyncMethod(() -> { - if (CustomCrops.getInstance().getPlatformInterface().removeCustomItem(location, itemMode)) { - CustomCrops.getInstance().getPlatformInterface().placeCustomItem(location, finalNextModel, itemMode); - } else { - removeCropData(simpleLocation); + try { + if (CustomCrops.getInstance().getPlatformInterface().removeCustomItem(location, itemMode)) { + CustomCrops.getInstance().getPlatformInterface().placeCustomItem(location, finalNextModel, itemMode); + } else { + removeCropData(simpleLocation); + } + } catch (Exception e) { + e.printStackTrace(); } return null; })); diff --git a/src/main/java/net/momirealms/customcrops/api/object/world/WorldDataManager.java b/src/main/java/net/momirealms/customcrops/api/object/world/WorldDataManager.java index 6c54cbe..5e9e898 100644 --- a/src/main/java/net/momirealms/customcrops/api/object/world/WorldDataManager.java +++ b/src/main/java/net/momirealms/customcrops/api/object/world/WorldDataManager.java @@ -246,4 +246,5 @@ public class WorldDataManager extends Function { public CCWorld getWorld(String world) { return worldMap.get(world); } + } diff --git a/src/main/java/net/momirealms/customcrops/api/util/ConfigUtils.java b/src/main/java/net/momirealms/customcrops/api/util/ConfigUtils.java index fdf22c9..15af91b 100644 --- a/src/main/java/net/momirealms/customcrops/api/util/ConfigUtils.java +++ b/src/main/java/net/momirealms/customcrops/api/util/ConfigUtils.java @@ -26,6 +26,7 @@ import dev.dejvokep.boostedyaml.settings.updater.UpdaterSettings; import net.kyori.adventure.key.Key; import net.kyori.adventure.sound.Sound; import net.momirealms.customcrops.CustomCrops; +import net.momirealms.customcrops.api.customplugin.Platform; import net.momirealms.customcrops.api.object.BoneMeal; import net.momirealms.customcrops.api.object.InteractWithItem; import net.momirealms.customcrops.api.object.ItemMode; @@ -52,8 +53,8 @@ import org.intellij.lang.annotations.Subst; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.io.File; -import java.io.IOException; +import java.io.*; +import java.nio.charset.StandardCharsets; import java.util.*; import java.util.stream.Collectors; @@ -61,15 +62,41 @@ public class ConfigUtils { /** * Get a config by name - * @param configName config's name + * @param config_path config's path * @return yaml */ - public static YamlConfiguration getConfig(String configName) { - File file = new File(CustomCrops.getInstance().getDataFolder(), configName); - if (!file.exists()) CustomCrops.getInstance().saveResource(configName, false); + public static YamlConfiguration getConfig(String config_path) { + File file = new File(CustomCrops.getInstance().getDataFolder(), config_path); + if (!file.exists()) { + CustomCrops.getInstance().saveResource(config_path, false); + if (CustomCrops.getInstance().getPlatform() == Platform.Oraxen) { + File generated = new File(CustomCrops.getInstance().getDataFolder(), config_path); + if (generated.exists() && generated.getName().endsWith(".yml")) { + removeNamespace(generated); + } + } + } return YamlConfiguration.loadConfiguration(file); } + public static void removeNamespace(File file) { + String line; + StringBuilder sb = new StringBuilder(); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))) { + while ((line = reader.readLine()) != null) { + sb.append(line).append(System.lineSeparator()); + } + } catch (IOException e) { + e.printStackTrace(); + } + try (BufferedWriter writer = new BufferedWriter( + new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8))) { + writer.write(sb.toString().replace(" customcrops:", " ").replace("CHORUS", "TRIPWIRE").replace("", "")); + } catch (IOException e) { + e.printStackTrace(); + } + } + /** * Update config * @param fileName config diff --git a/src/main/java/net/momirealms/customcrops/api/util/FakeEntityUtils.java b/src/main/java/net/momirealms/customcrops/api/util/FakeEntityUtils.java index 312a9aa..cd2b9d5 100644 --- a/src/main/java/net/momirealms/customcrops/api/util/FakeEntityUtils.java +++ b/src/main/java/net/momirealms/customcrops/api/util/FakeEntityUtils.java @@ -50,11 +50,9 @@ public class FakeEntityUtils { public static WrappedDataWatcher createInvisibleDataWatcher() { WrappedDataWatcher wrappedDataWatcher = new WrappedDataWatcher(); - WrappedDataWatcher.Serializer serializer1 = WrappedDataWatcher.Registry.get(Boolean.class); - WrappedDataWatcher.Serializer serializer2 = WrappedDataWatcher.Registry.get(Byte.class); - wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(3, serializer1), false); + //wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(3, WrappedDataWatcher.Registry.get(Boolean.class)), false); byte flag = 0x20; - wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(0, serializer2), flag); + wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(0, WrappedDataWatcher.Registry.get(Byte.class)), flag); return wrappedDataWatcher; } diff --git a/src/main/java/net/momirealms/customcrops/command/CustomCropsCommand.java b/src/main/java/net/momirealms/customcrops/command/CustomCropsCommand.java index 6470c2c..f19eb8b 100644 --- a/src/main/java/net/momirealms/customcrops/command/CustomCropsCommand.java +++ b/src/main/java/net/momirealms/customcrops/command/CustomCropsCommand.java @@ -29,5 +29,6 @@ public class CustomCropsCommand extends AbstractMainCommand { regSubCommand(SetDateCommand.INSTANCE); regSubCommand(ForceCommand.INSTANCE); regSubCommand(MigrateCommand.INSTANCE); +// regSubCommand(PerformanceTest.INSTANCE); } } diff --git a/src/main/java/net/momirealms/customcrops/command/subcmd/PerformanceTest.java b/src/main/java/net/momirealms/customcrops/command/subcmd/PerformanceTest.java new file mode 100644 index 0000000..6e43778 --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/command/subcmd/PerformanceTest.java @@ -0,0 +1,41 @@ +//package net.momirealms.customcrops.command.subcmd; +// +//import net.momirealms.customcrops.CustomCrops; +//import net.momirealms.customcrops.api.object.crop.GrowingCrop; +//import net.momirealms.customcrops.api.object.world.SimpleLocation; +//import net.momirealms.customcrops.api.object.world.WorldDataManager; +//import net.momirealms.customcrops.command.AbstractSubCommand; +//import org.bukkit.command.CommandSender; +//import org.bukkit.entity.Player; +// +//import java.util.List; +// +//public class PerformanceTest extends AbstractSubCommand { +// +// public static final PerformanceTest INSTANCE = new PerformanceTest(); +// +// public PerformanceTest() { +// super("test"); +// } +// +// @Override +// public boolean onCommand(CommandSender sender, List args) { +// int radius = Integer.parseInt(args.get(0)); +// WorldDataManager worldDataManager = CustomCrops.getInstance().getWorldDataManager(); +// if (sender instanceof Player player) { +// SimpleLocation simpleLocation = SimpleLocation.getByBukkitLocation(player.getLocation()); +// CustomCrops.getInstance().getScheduler().runTaskAsync(() -> { +// SimpleLocation simpleLocation1 = simpleLocation.add(-radius, 0, -radius); +// for (int i = 0; i < radius * 2; i++) { +// for (int j = 0; j < radius * 2; j++) { +// for (int y = 0; y < 10; y++) { +// SimpleLocation temp = simpleLocation1.add(i, y, j); +// worldDataManager.addCropData(temp, new GrowingCrop("tomato", 0)); +// } +// } +// } +// }); +// } +// return true; +// } +//} diff --git a/src/main/java/net/momirealms/customcrops/integration/ProtectionInterface.java b/src/main/java/net/momirealms/customcrops/integration/ProtectionInterface.java deleted file mode 100644 index 5b6ba37..0000000 --- a/src/main/java/net/momirealms/customcrops/integration/ProtectionInterface.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) <2022> - * - * 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 . - */ - -package net.momirealms.customcrops.integration; - -public interface ProtectionInterface { -} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index da8f40e..616651b 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -4,6 +4,8 @@ config-version: '25' metrics: true # Language: english / spanish / chinese / turkish lang: english +# debug +debug: false worlds: # This is designed for servers that using a separate folder for worlds diff --git a/src/main/resources/contents/crops/tomato.yml b/src/main/resources/contents/crops/tomato.yml index 76ed111..22e96e2 100644 --- a/src/main/resources/contents/crops/tomato.yml +++ b/src/main/resources/contents/crops/tomato.yml @@ -5,7 +5,7 @@ tomato: # Otherwise some unexpected problems would occur # TRIPWIRE / ITEM_FRAME / ITEM_DISPLAY (1.19.4+) # 农作物模式,请确保和你的资源包配置等一致,否则会出现bug - type: ITEM_FRAME + type: TRIPWIRE # The crop can only be planted on certain pots # Pot are stored in /CustomCrops/contents/pots diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 3c08173..aafc553 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -49,6 +49,8 @@ permissions : customcrops.about: true customcrops.setdate: true customcrops.setseason: true + customcrops.force: true + customcrops.migrate: true customcrops.reload: default: op customcrops.help: @@ -58,4 +60,8 @@ permissions : customcrops.setdate: default: op customcrops.setseason: + default: op + customcrops.force: + default: op + customcrops.migrate: default: op \ No newline at end of file