From 420960b1ff2ec6e4a58c8b4268c140eb4d9d17c6 Mon Sep 17 00:00:00 2001 From: XiaoMoMi <972454774@qq.com> Date: Sat, 17 Jun 2023 18:45:18 +0800 Subject: [PATCH] 3.2.5.0-beta --- build.gradle | 2 +- .../api/customplugin/PlatformManager.java | 16 +++- .../api/event/SeasonChangeEvent.java | 33 ++++++++ .../api/object/crop/CropConfig.java | 9 ++- .../api/object/crop/CropManager.java | 3 +- .../api/object/season/SeasonData.java | 16 +++- .../customcrops/api/object/world/CCWorld.java | 77 +++++++++++-------- .../api/object/world/SlimeWorldListener.java | 17 ++++ .../api/object/world/WorldDataManager.java | 3 +- .../customcrops/api/util/RotationUtils.java | 7 +- 10 files changed, 144 insertions(+), 39 deletions(-) create mode 100644 src/main/java/net/momirealms/customcrops/api/event/SeasonChangeEvent.java diff --git a/build.gradle b/build.gradle index 913b000..a8ff6a5 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ plugins { } group = 'net.momirealms' -version = '3.2.4.0' +version = '3.2.5.0-beta' repositories { mavenCentral() 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 125f72f..2216b2f 100644 --- a/src/main/java/net/momirealms/customcrops/api/customplugin/PlatformManager.java +++ b/src/main/java/net/momirealms/customcrops/api/customplugin/PlatformManager.java @@ -45,11 +45,14 @@ import net.momirealms.customcrops.api.object.sprinkler.SprinklerConfig; import net.momirealms.customcrops.api.object.wateringcan.WateringCanConfig; import net.momirealms.customcrops.api.object.world.SimpleLocation; import net.momirealms.customcrops.api.util.AdventureUtils; +import net.momirealms.customcrops.api.util.RotationUtils; 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.ItemDisplay; +import org.bukkit.entity.ItemFrame; import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; import org.bukkit.event.Event; @@ -745,7 +748,18 @@ public class PlatformManager extends Function { if (player.getGameMode() != GameMode.CREATIVE) item_in_hand.setAmount(item_in_hand.getAmount() - 1); player.swingMainHand(); - CustomCrops.getInstance().getPlatformInterface().placeCustomItem(crop_loc, cropPlantEvent.getCropModel(), cropConfig.getCropMode()); + switch (cropConfig.getCropMode()) { + case ITEM_DISPLAY -> { + ItemDisplay itemDisplay = CustomCrops.getInstance().getPlatformInterface().placeItemDisplay(crop_loc, cropPlantEvent.getCropModel()); + if (itemDisplay != null && cropConfig.isRotationEnabled()) itemDisplay.setRotation(RotationUtils.getRandomFloatRotation(), 0); + } + case ITEM_FRAME -> { + ItemFrame itemFrame = CustomCrops.getInstance().getPlatformInterface().placeItemFrame(crop_loc, cropPlantEvent.getCropModel()); + if (itemFrame != null && cropConfig.isRotationEnabled()) itemFrame.setRotation(RotationUtils.getRandomRotation()); + } + case TRIPWIRE -> CustomCrops.getInstance().getPlatformInterface().placeTripWire(crop_loc, cropPlantEvent.getCropModel()); + } + plugin.getWorldDataManager().addCropData(SimpleLocation.getByBukkitLocation(crop_loc), new GrowingCrop(cropConfig.getKey(), cropPlantEvent.getPoint()), true); return true; } diff --git a/src/main/java/net/momirealms/customcrops/api/event/SeasonChangeEvent.java b/src/main/java/net/momirealms/customcrops/api/event/SeasonChangeEvent.java new file mode 100644 index 0000000..091ac0b --- /dev/null +++ b/src/main/java/net/momirealms/customcrops/api/event/SeasonChangeEvent.java @@ -0,0 +1,33 @@ +package net.momirealms.customcrops.api.event; + +import net.momirealms.customcrops.api.object.season.CCSeason; +import org.bukkit.World; +import org.bukkit.event.HandlerList; +import org.bukkit.event.world.WorldEvent; +import org.jetbrains.annotations.NotNull; + +public class SeasonChangeEvent extends WorldEvent { + + private static final HandlerList handlers = new HandlerList(); + private final CCSeason ccSeason; + + public SeasonChangeEvent(@NotNull World world, CCSeason ccSeason) { + super(world); + this.ccSeason = ccSeason; + } + + @NotNull + public static HandlerList getHandlerList() { + return handlers; + } + + @NotNull + @Override + public HandlerList getHandlers() { + return getHandlerList(); + } + + public CCSeason getCcSeason() { + return ccSeason; + } +} diff --git a/src/main/java/net/momirealms/customcrops/api/object/crop/CropConfig.java b/src/main/java/net/momirealms/customcrops/api/object/crop/CropConfig.java index a2ef7b8..3b2f768 100644 --- a/src/main/java/net/momirealms/customcrops/api/object/crop/CropConfig.java +++ b/src/main/java/net/momirealms/customcrops/api/object/crop/CropConfig.java @@ -41,6 +41,7 @@ public class CropConfig { private final Condition[] growConditions; private final BoneMeal[] boneMeals; private final Action[] plantActions; + private final boolean rotation; public CropConfig(String key, ItemMode itemMode, @@ -52,7 +53,8 @@ public class CropConfig { Condition[] growConditions, HashMap stageMap, BoneMeal[] boneMeals, - Action[] plantActions + Action[] plantActions, + boolean rotation ) { this.key = key; this.itemMode = itemMode; @@ -65,6 +67,7 @@ public class CropConfig { this.growConditions = growConditions; this.boneMeals = boneMeals; this.plantActions = plantActions; + this.rotation = rotation; } public String getKey() { @@ -119,4 +122,8 @@ public class CropConfig { public Action[] getPlantActions() { return plantActions; } + + public boolean isRotationEnabled() { + return rotation; + } } 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 fdd1590..a84a39a 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 @@ -155,7 +155,8 @@ public class CropManager extends Function implements Listener { growConditions, stageMap, ConfigUtils.getBoneMeals(cropSec.getConfigurationSection("custom-bone-meal")), - ConfigUtils.getActions(cropSec.getConfigurationSection("plant-actions"), null) + ConfigUtils.getActions(cropSec.getConfigurationSection("plant-actions"), null), + cropSec.getBoolean("random-rotation", false) ); cropConfigMap.put(key, cropConfig); if (seed != null) seedToCropConfig.put(seed, cropConfig); diff --git a/src/main/java/net/momirealms/customcrops/api/object/season/SeasonData.java b/src/main/java/net/momirealms/customcrops/api/object/season/SeasonData.java index a1fbaed..f2c1d18 100644 --- a/src/main/java/net/momirealms/customcrops/api/object/season/SeasonData.java +++ b/src/main/java/net/momirealms/customcrops/api/object/season/SeasonData.java @@ -17,7 +17,12 @@ 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 { @@ -50,6 +55,7 @@ public class SeasonData { if (date > ConfigManager.seasonInterval) { this.date = 1; this.ccSeason = getNextSeason(ccSeason); + CustomCrops.getInstance().getScheduler().runTask(this::callEvent); } } @@ -64,7 +70,10 @@ public class SeasonData { } public void changeSeason(CCSeason ccSeason) { - this.ccSeason = ccSeason; + if (ccSeason != this.ccSeason) { + this.ccSeason = ccSeason; + callEvent(); + } } public String getWorld() { @@ -74,4 +83,9 @@ public class SeasonData { 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); + } } 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 333a80b..4d0d7b9 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 @@ -42,11 +42,14 @@ import net.momirealms.customcrops.api.object.sprinkler.SprinklerConfig; import net.momirealms.customcrops.api.util.AdventureUtils; import net.momirealms.customcrops.api.util.ConfigUtils; import net.momirealms.customcrops.api.util.FakeEntityUtils; +import net.momirealms.customcrops.api.util.RotationUtils; import net.momirealms.customcrops.helper.Log; import org.bukkit.*; import org.bukkit.block.Block; import org.bukkit.block.data.type.Farmland; import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.ItemDisplay; +import org.bukkit.entity.ItemFrame; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -54,10 +57,7 @@ import org.jetbrains.annotations.Nullable; import java.io.*; import java.lang.ref.Reference; import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.*; public class CCWorld extends Function { @@ -72,7 +72,8 @@ public class CCWorld extends Function { private int cacheTimer; private int workCounter; private int consumeCounter; - private final HashSet plantInPoint; + private final Set plantInPoint; + private Set loadInPoint; private final ConcurrentHashMap corruptedPot; private final File chunksFolder; private final File dateFile; @@ -91,12 +92,14 @@ public class CCWorld extends Function { this.schedule.setMaximumPoolSize(ConfigManager.maxPoolSize); this.schedule.setKeepAliveTime(ConfigManager.keepAliveTime, TimeUnit.SECONDS); this.schedule.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy()); - this.plantInPoint = new HashSet<>(128); + this.plantInPoint = Collections.synchronizedSet(new HashSet<>(128)); + this.loadInPoint = Collections.synchronizedSet(new HashSet<>(32)); this.corruptedPot = new ConcurrentHashMap<>(128); this.cacheTimer = ConfigManager.cacheSaveInterval; } @Override + @SuppressWarnings("ResultOfMethodCallIgnored") public void init() { loadDateData(); loadCorruptedPots(); @@ -241,8 +244,7 @@ public class CCWorld extends Function { long time = current.getTime(); this.tryDayCycleTask(time, day); this.timerTask(); - } - else { + } else { AdventureUtils.consoleMessage("[CustomCrops] World: " + worldName + " unloaded unexpectedly. Shutdown the schedule."); this.schedule.shutdown(); } @@ -278,31 +280,28 @@ public class CCWorld extends Function { } public void onReachPoint() { + if (ConfigManager.debugScheduler) Log.info("== Grow point =="); if (ConfigManager.enableScheduleSystem) { - if (ConfigManager.debugScheduler) Log.info("== Grow point =="); + // clear the locations where crops are planted in a point interval plantInPoint.clear(); - int size = schedule.getQueue().size(); - if (size != 0) { - schedule.getQueue().clear(); - if (ConfigManager.debugScheduler) Log.info("== Clear queue =="); - } + // clear the chunk coordinates that has grown in a point interval + loadInPoint = Collections.synchronizedSet(new HashSet<>(chunkMap.keySet())); + // clear the queue if there exists unhandled tasks + schedule.getQueue().clear(); + // arrange crop grow check task for (CCChunk chunk : chunkMap.values()) { chunk.scheduleGrowTask(this, -1); } - if (workCounter > 0) { - workCounter--; - } - if (consumeCounter > 0) { - consumeCounter--; - } + workCounter--; + consumeCounter--; if (consumeCounter == 0) { - consumeCounter = ConfigManager.intervalConsume; if (ConfigManager.debugScheduler) Log.info("== Consume time =="); + consumeCounter = ConfigManager.intervalConsume; scheduleConsumeTask(-1); } if (workCounter == 0) { - workCounter = ConfigManager.intervalWork; if (ConfigManager.debugScheduler) Log.info("== Work time =="); + workCounter = ConfigManager.intervalWork; scheduleSprinklerWork(-1); } } @@ -342,6 +341,9 @@ public class CCWorld extends Function { delete = true; } else { chunkMap.put(chunkCoordinate, chunk); + if (!loadInPoint.contains(chunkCoordinate)) { + chunk.scheduleGrowTask(this, -1); + } } } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); @@ -561,7 +563,6 @@ public class CCWorld extends Function { addWaterToPot(simpleLocation, amount, potKey); } } else if (ConfigManager.enableCorruptionFixer && blockID.equals("NOTE_BLOCK")) { - // Only ItemsAdder can go to this step Pot pot = getPotData(simpleLocation); if (pot != null) { // mark it as corrupted @@ -577,11 +578,11 @@ public class CCWorld extends Function { } } corruptedPot.put(simpleLocation, potKey); - if (ConfigManager.debugCorruption) AdventureUtils.consoleMessage("[CustomCrops] Trying to fix corrupted pot found at: " + simpleLocation); + if (ConfigManager.debugCorruption) AdventureUtils.consoleMessage("[CustomCrops] Corrupted pot found at: " + simpleLocation); // only custom blocks would corrupt // so it's not necessary to check if the pot is a vanilla block - String replacer = pot.isWet() ? pot.getConfig().getWetPot(pot.getFertilizer()) : pot.getConfig().getDryPot(pot.getFertilizer()); - plugin.getPlatformInterface().placeNoteBlock(location, replacer); + // String replacer = pot.isWet() ? pot.getConfig().getWetPot(pot.getFertilizer()) : pot.getConfig().getDryPot(pot.getFertilizer()); + // plugin.getPlatformInterface().placeNoteBlock(location, replacer); } } } @@ -684,7 +685,7 @@ public class CCWorld extends Function { if (finalNextModel == null || location == null) return; CompletableFuture asyncGetChunk = location.getWorld().getChunkAtAsync(location.getBlockX() >> 4, location.getBlockZ() >> 4); - if (itemMode == ItemMode.ITEM_FRAME || itemMode == ItemMode.ITEM_DISPLAY) { + if (itemMode == ItemMode.ITEM_FRAME) { CompletableFuture loadEntities = asyncGetChunk.thenApply((chunk) -> { chunk.getEntities(); return chunk.isEntitiesLoaded(); @@ -692,17 +693,31 @@ public class CCWorld extends Function { loadEntities.whenComplete((result, throwable) -> plugin.getScheduler().runTask(() -> { if (plugin.getPlatformInterface().removeCustomItem(location, itemMode)) { - plugin.getPlatformInterface().placeCustomItem(location, finalNextModel, itemMode); + ItemFrame itemFrame = plugin.getPlatformInterface().placeItemFrame(location, finalNextModel); + if (itemFrame != null && cropConfig.isRotationEnabled()) itemFrame.setRotation(RotationUtils.getRandomRotation()); } else { removeCropData(simpleLocation); } })); - } - else { + } else if (itemMode == ItemMode.ITEM_DISPLAY) { + CompletableFuture loadEntities = asyncGetChunk.thenApply((chunk) -> { + chunk.getEntities(); + return chunk.isEntitiesLoaded(); + }); + loadEntities.whenComplete((result, throwable) -> + plugin.getScheduler().runTask(() -> { + if (plugin.getPlatformInterface().removeCustomItem(location, itemMode)) { + ItemDisplay itemDisplay = plugin.getPlatformInterface().placeItemDisplay(location, finalNextModel); + if (itemDisplay != null && cropConfig.isRotationEnabled()) itemDisplay.setRotation(RotationUtils.getRandomFloatRotation(), 0); + } else { + removeCropData(simpleLocation); + } + })); + } else { asyncGetChunk.whenComplete((result, throwable) -> plugin.getScheduler().runTask(() -> { if (plugin.getPlatformInterface().removeCustomItem(location, itemMode)) { - plugin.getPlatformInterface().placeCustomItem(location, finalNextModel, itemMode); + plugin.getPlatformInterface().placeTripWire(location, finalNextModel); } else { removeCropData(simpleLocation); } diff --git a/src/main/java/net/momirealms/customcrops/api/object/world/SlimeWorldListener.java b/src/main/java/net/momirealms/customcrops/api/object/world/SlimeWorldListener.java index 7746d03..39fe752 100644 --- a/src/main/java/net/momirealms/customcrops/api/object/world/SlimeWorldListener.java +++ b/src/main/java/net/momirealms/customcrops/api/object/world/SlimeWorldListener.java @@ -1,3 +1,20 @@ +/* + * 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.api.object.world; import com.infernalsuite.aswm.api.events.LoadSlimeWorldEvent; 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 ed56e86..6ddde9c 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 @@ -232,8 +232,7 @@ public class WorldDataManager extends Function { Sprinkler sprinkler = getSprinklerData(simpleLocation); if (sprinkler != null) { sprinkler.setWater(Math.min(add + sprinkler.getWater(), sprinklerConfig.getStorage())); - } - else { + } else { Sprinkler newSprinkler = new Sprinkler(sprinklerConfig.getKey(), Math.min(add, sprinklerConfig.getStorage())); addSprinklerData(simpleLocation, newSprinkler); } diff --git a/src/main/java/net/momirealms/customcrops/api/util/RotationUtils.java b/src/main/java/net/momirealms/customcrops/api/util/RotationUtils.java index dde2bdd..3ab73c0 100644 --- a/src/main/java/net/momirealms/customcrops/api/util/RotationUtils.java +++ b/src/main/java/net/momirealms/customcrops/api/util/RotationUtils.java @@ -24,8 +24,13 @@ import java.util.Random; public class RotationUtils { private static final Rotation[] rotations4 = {Rotation.NONE, Rotation.FLIPPED, Rotation.CLOCKWISE, Rotation.COUNTER_CLOCKWISE}; + private static final float[] rotationsF = {0f, 90f, 180f, -90f}; public static Rotation getRandomRotation() { - return rotations4[new Random().nextInt(rotations4.length-1)]; + return rotations4[new Random().nextInt(4)]; + } + + public static float getRandomFloatRotation() { + return rotationsF[new Random().nextInt(4)]; } }