From e04f7875878835d4e4c071aa9b94b3ec6f257016 Mon Sep 17 00:00:00 2001 From: XiaoMoMi <70987828+Xiao-MoMi@users.noreply.github.com> Date: Sun, 8 Sep 2024 16:17:11 +0800 Subject: [PATCH] deep clone a compound --- .../customcrops/api/core/TickMode.java | 35 ++++++ .../customcrops/api/core/block/CropBlock.java | 8 +- .../customcrops/api/core/block/PotBlock.java | 108 ++++++++---------- .../api/core/block/SprinklerBlock.java | 8 +- .../api/core/world/WorldSetting.java | 66 +++++------ .../customcrops/api/util/TagUtils.java | 21 +++- .../adaptor/asp_r1/SlimeWorldAdaptorR1.java | 3 +- gradle.properties | 8 +- .../adaptor/BukkitWorldAdaptor.java | 3 +- .../bukkit/world/BukkitWorldManager.java | 13 +-- 10 files changed, 162 insertions(+), 111 deletions(-) create mode 100644 api/src/main/java/net/momirealms/customcrops/api/core/TickMode.java diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/TickMode.java b/api/src/main/java/net/momirealms/customcrops/api/core/TickMode.java new file mode 100644 index 0000000..67caaaa --- /dev/null +++ b/api/src/main/java/net/momirealms/customcrops/api/core/TickMode.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) <2024> + * + * 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.core; + +public enum TickMode { + + RANDOM_TICK(1), + SCHEDULED_TICK(2), + ALL(0); + + private final int mode; + + TickMode(int mode) { + this.mode = mode; + } + + public int mode() { + return mode; + } +} diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/block/CropBlock.java b/api/src/main/java/net/momirealms/customcrops/api/core/block/CropBlock.java index 8ae1568..f2d618f 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/block/CropBlock.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/block/CropBlock.java @@ -60,14 +60,18 @@ public class CropBlock extends AbstractCustomCropsBlock { @Override public void scheduledTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location, boolean offlineTick) { - if (!world.setting().randomTickCrop() && canTick(state, world.setting().tickCropInterval())) { + // ignore random tick + if (world.setting().tickCropMode() == 1) return; + if (canTick(state, world.setting().tickCropInterval())) { tickCrop(state, world, location, offlineTick); } } @Override public void randomTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location, boolean offlineTick) { - if (world.setting().randomTickCrop() && canTick(state, world.setting().tickCropInterval())) { + // ignore scheduled tick + if (world.setting().tickCropMode() == 2) return; + if (canTick(state, world.setting().tickCropInterval())) { tickCrop(state, world, location, offlineTick); } } diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/block/PotBlock.java b/api/src/main/java/net/momirealms/customcrops/api/core/block/PotBlock.java index fc17028..7144d12 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/block/PotBlock.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/block/PotBlock.java @@ -44,6 +44,7 @@ import net.momirealms.customcrops.api.requirement.RequirementManager; import net.momirealms.customcrops.api.util.EventUtils; import net.momirealms.customcrops.api.util.LocationUtils; import net.momirealms.customcrops.api.util.PlayerUtils; +import net.momirealms.sparrow.heart.SparrowHeart; import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.Material; @@ -70,14 +71,18 @@ public class PotBlock extends AbstractCustomCropsBlock { @Override public void scheduledTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location, boolean offlineTick) { - if (!world.setting().randomTickPot() && canTick(state, world.setting().tickPotInterval())) { + // ignore random tick + if (world.setting().tickPotMode() == 1) return; + if (canTick(state, world.setting().tickPotInterval())) { tickPot(state, world, location, offlineTick); } } @Override public void randomTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location, boolean offlineTick) { - if (world.setting().randomTickPot() && canTick(state, world.setting().tickPotInterval())) { + // ignore scheduled tick + if (world.setting().tickPotMode() == 2) return; + if (canTick(state, world.setting().tickPotInterval())) { tickPot(state, world, location, offlineTick); } } @@ -350,82 +355,69 @@ public class PotBlock extends AbstractCustomCropsBlock { if (!config.blocks().contains(blockID)) { plugin.getPluginLogger().warn("Pot[" + config.id() + "] is removed at location[" + world.worldName() + "," + location + "] because the id of the block is [" + blockID + "]"); world.removeBlockState(location); - future.complete(false); return; } - future.complete(true); - } else { - future.complete(true); } - future.thenAcceptAsync((run) -> { - if (!run) return; - // work as vanilla farmland - if (config.disablePluginMechanism()) return; + // work as vanilla farmland + if (config.disablePluginMechanism()) return; - boolean hasNaturalWater = false; - boolean waterChanged = false; + boolean hasNaturalWater = false; + boolean waterChanged = false; - if (config.isRainDropAccepted()) { - if (bukkitWorld.hasStorm() || (!bukkitWorld.isClearWeather() && !bukkitWorld.isThundering())) { - double temperature = bukkitWorld.getTemperature(location.x(), location.y(), location.z()); - if (temperature > 0.15 && temperature < 0.85) { - int y = bukkitWorld.getHighestBlockYAt(location.x(), location.z()); - if (y == location.y()) { - if (addWater(state, 1)) { - waterChanged = true; - } - hasNaturalWater = true; - } - } + Location bukkitLocation = location.toLocation(bukkitWorld); + + if (config.isRainDropAccepted()) { + if (SparrowHeart.getInstance().isRainingAt(bukkitLocation.clone().add(0,1,0))) { + if (addWater(state, 1)) { + waterChanged = true; } + hasNaturalWater = true; } + } - if (!hasNaturalWater && config.isNearbyWaterAccepted()) { - outer: { - for (int i = -4; i <= 4; i++) { - for (int j = -4; j <= 4; j++) { - for (int k : new int[]{0, 1}) { - BlockData block = bukkitWorld.getBlockData(location.x() + i, location.y() + j, location.z() + k); - if (block.getMaterial() == Material.WATER || (block instanceof Waterlogged waterlogged && waterlogged.isWaterlogged())) { - if (addWater(state, 1)) { - waterChanged = true; - } - hasNaturalWater = true; - break outer; + if (!hasNaturalWater && config.isNearbyWaterAccepted()) { + outer: { + for (int i = -4; i <= 4; i++) { + for (int j = -4; j <= 4; j++) { + for (int k : new int[]{0, 1}) { + BlockData block = bukkitWorld.getBlockData(location.x() + i, location.y() + k, location.z() + j); + if (block.getMaterial() == Material.WATER || (block instanceof Waterlogged waterlogged && waterlogged.isWaterlogged())) { + if (addWater(state, 1)) { + waterChanged = true; } + hasNaturalWater = true; + break outer; } } } } } + } - if (!hasNaturalWater) { - int waterToLose = 1; - Fertilizer[] fertilizers = fertilizers(state); - for (Fertilizer fertilizer : fertilizers) { - FertilizerConfig fertilizerConfig = fertilizer.config(); - if (fertilizerConfig != null) { - waterToLose = fertilizerConfig.processWaterToLose(waterToLose); - } - } - if (waterToLose > 0) { - if (addWater(state, -waterToLose)) { - waterChanged = true; - } + if (!hasNaturalWater) { + int waterToLose = 1; + Fertilizer[] fertilizers = fertilizers(state); + for (Fertilizer fertilizer : fertilizers) { + FertilizerConfig fertilizerConfig = fertilizer.config(); + if (fertilizerConfig != null) { + waterToLose = fertilizerConfig.processWaterToLose(waterToLose); } } - - boolean fertilizerChanged = tickFertilizer(state); - - Location bukkitLocation = location.toLocation(bukkitWorld); - if (fertilizerChanged || waterChanged) { - boolean finalHasNaturalWater = hasNaturalWater; - plugin.getScheduler().sync().run(() -> updateBlockAppearance(bukkitLocation, config, finalHasNaturalWater, fertilizers(state)), bukkitLocation); + if (waterToLose > 0) { + if (addWater(state, -waterToLose)) { + waterChanged = true; + } } + } - ActionManager.trigger(Context.block(state, bukkitLocation).arg(ContextKeys.OFFLINE, offline), config.tickActions()); - }, plugin.getScheduler().async()); + boolean fertilizerChanged = tickFertilizer(state); + + if (fertilizerChanged || waterChanged) { + plugin.getScheduler().sync().run(() -> updateBlockAppearance(bukkitLocation, config, water(state) != 0, fertilizers(state)), bukkitLocation); + } + + ActionManager.trigger(Context.block(state, bukkitLocation).arg(ContextKeys.OFFLINE, offline), config.tickActions()); } public int water(CustomCropsBlockState state) { diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/block/SprinklerBlock.java b/api/src/main/java/net/momirealms/customcrops/api/core/block/SprinklerBlock.java index 9b25eb3..9d43622 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/block/SprinklerBlock.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/block/SprinklerBlock.java @@ -58,14 +58,18 @@ public class SprinklerBlock extends AbstractCustomCropsBlock { @Override public void randomTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location, boolean offlineTick) { - if (!world.setting().randomTickSprinkler() && canTick(state, world.setting().tickSprinklerInterval())) { + // ignore scheduled tick + if (world.setting().tickSprinklerMode() == 2) return; + if (canTick(state, world.setting().tickSprinklerInterval())) { tickSprinkler(state, world, location, offlineTick); } } @Override public void scheduledTick(CustomCropsBlockState state, CustomCropsWorld world, Pos3 location, boolean offlineTick) { - if (world.setting().randomTickSprinkler() && canTick(state, world.setting().tickSprinklerInterval())) { + // ignore random tick + if (world.setting().tickSprinklerMode() == 1) return; + if (canTick(state, world.setting().tickSprinklerInterval())) { tickSprinkler(state, world, location, offlineTick); } } diff --git a/api/src/main/java/net/momirealms/customcrops/api/core/world/WorldSetting.java b/api/src/main/java/net/momirealms/customcrops/api/core/world/WorldSetting.java index 96e337b..15b9da5 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/core/world/WorldSetting.java +++ b/api/src/main/java/net/momirealms/customcrops/api/core/world/WorldSetting.java @@ -38,20 +38,20 @@ public class WorldSetting implements Cloneable { private final int randomTickSpeed; private final int maxOfflineTime; private final int maxLoadingTime; - private final boolean tickCropRandomly; - private final boolean tickPotRandomly; - private final boolean tickSprinklerRandomly; + private final int tickCropMode; + private final int tickPotMode; + private final int tickSprinklerMode; /** * Private constructor to initialize a WorldSetting instance with the provided parameters. * * @param enableScheduler Whether the scheduler is enabled. * @param minTickUnit The minimum unit of tick. - * @param tickCropRandomly Whether crops are ticked randomly. + * @param tickCropMode The tick mode of crop * @param tickCropInterval The interval for ticking crops. - * @param tickPotRandomly Whether pots are ticked randomly. + * @param tickPotMode The tick mode of pot * @param tickPotInterval The interval for ticking pots. - * @param tickSprinklerRandomly Whether sprinklers are ticked randomly. + * @param tickSprinklerMode The tick mode of sprinkler * @param tickSprinklerInterval The interval for ticking sprinklers. * @param offlineTick Whether offline ticking is enabled. * @param maxOfflineTime The maximum offline time allowed. @@ -67,11 +67,11 @@ public class WorldSetting implements Cloneable { private WorldSetting( boolean enableScheduler, int minTickUnit, - boolean tickCropRandomly, + int tickCropMode, int tickCropInterval, - boolean tickPotRandomly, + int tickPotMode, int tickPotInterval, - boolean tickSprinklerRandomly, + int tickSprinklerMode, int tickSprinklerInterval, boolean offlineTick, int maxOfflineTime, @@ -99,9 +99,9 @@ public class WorldSetting implements Cloneable { this.potPerChunk = potPerChunk; this.sprinklerPerChunk = sprinklerPerChunk; this.randomTickSpeed = randomTickSpeed; - this.tickCropRandomly = tickCropRandomly; - this.tickPotRandomly = tickPotRandomly; - this.tickSprinklerRandomly = tickSprinklerRandomly; + this.tickCropMode = tickCropMode; + this.tickPotMode = tickPotMode; + this.tickSprinklerMode = tickSprinklerMode; } /** @@ -109,11 +109,11 @@ public class WorldSetting implements Cloneable { * * @param enableScheduler Whether the scheduler is enabled. * @param minTickUnit The minimum unit of tick. - * @param tickCropRandomly Whether crops are ticked randomly. + * @param tickCropMode The tick mode of crop * @param tickCropInterval The interval for ticking crops. - * @param tickPotRandomly Whether pots are ticked randomly. + * @param tickPotMode The tick mode of pot * @param tickPotInterval The interval for ticking pots. - * @param tickSprinklerRandomly Whether sprinklers are ticked randomly. + * @param tickSprinklerMode The tick mode of sprinkler * @param tickSprinklerInterval The interval for ticking sprinklers. * @param offlineGrow Whether offline ticking is enabled. * @param maxOfflineTime The maximum offline time allowed. @@ -129,11 +129,11 @@ public class WorldSetting implements Cloneable { public static WorldSetting of( boolean enableScheduler, int minTickUnit, - boolean tickCropRandomly, + int tickCropMode, int tickCropInterval, - boolean tickPotRandomly, + int tickPotMode, int tickPotInterval, - boolean tickSprinklerRandomly, + int tickSprinklerMode, int tickSprinklerInterval, boolean offlineGrow, int maxOfflineTime, @@ -149,11 +149,11 @@ public class WorldSetting implements Cloneable { return new WorldSetting( enableScheduler, minTickUnit, - tickCropRandomly, + tickCropMode, tickCropInterval, - tickPotRandomly, + tickPotMode, tickPotInterval, - tickSprinklerRandomly, + tickSprinklerMode, tickSprinklerInterval, offlineGrow, maxOfflineTime, @@ -295,30 +295,30 @@ public class WorldSetting implements Cloneable { } /** - * Checks if crops are ticked randomly. + * Gets the tick mode of crop * - * @return true if crops are ticked randomly, false otherwise. + * @return the mode */ - public boolean randomTickCrop() { - return tickCropRandomly; + public int tickCropMode() { + return tickCropMode; } /** - * Checks if sprinklers are ticked randomly. + * Gets the tick mode of sprinkler * - * @return true if sprinklers are ticked randomly, false otherwise. + * @return the mode */ - public boolean randomTickSprinkler() { - return tickSprinklerRandomly; + public int tickSprinklerMode() { + return tickSprinklerMode; } /** - * Checks if pots are ticked randomly. + * Gets the tick mode of pot * - * @return true if pots are ticked randomly, false otherwise. + * @return the mode */ - public boolean randomTickPot() { - return tickPotRandomly; + public int tickPotMode() { + return tickPotMode; } /** diff --git a/api/src/main/java/net/momirealms/customcrops/api/util/TagUtils.java b/api/src/main/java/net/momirealms/customcrops/api/util/TagUtils.java index 9a92fa0..04c0aed 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/util/TagUtils.java +++ b/api/src/main/java/net/momirealms/customcrops/api/util/TagUtils.java @@ -17,7 +17,7 @@ package net.momirealms.customcrops.api.util; -import com.flowpowered.nbt.Tag; +import com.flowpowered.nbt.*; import com.flowpowered.nbt.stream.NBTInputStream; import com.flowpowered.nbt.stream.NBTOutputStream; @@ -25,6 +25,9 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; public class TagUtils { @@ -55,4 +58,20 @@ public class TagUtils { throw new RuntimeException(e); } } + + public static CompoundMap deepClone(CompoundMap initial) { + CompoundMap clone = new CompoundMap(); + for (Tag tag : initial) { + if (tag.getType() == TagType.TAG_COMPOUND) { + clone.put(deepClone((CompoundTag) tag)); + } else { + clone.put(tag.clone()); + } + } + return clone; + } + + public static CompoundTag deepClone(CompoundTag initial) { + return new CompoundTag(initial.getName(), deepClone(initial.getValue())); + } } diff --git a/compatibility-asp-r1/src/main/java/net/momirealms/customcrops/bukkit/integration/adaptor/asp_r1/SlimeWorldAdaptorR1.java b/compatibility-asp-r1/src/main/java/net/momirealms/customcrops/bukkit/integration/adaptor/asp_r1/SlimeWorldAdaptorR1.java index 16d16cb..d2388c4 100644 --- a/compatibility-asp-r1/src/main/java/net/momirealms/customcrops/bukkit/integration/adaptor/asp_r1/SlimeWorldAdaptorR1.java +++ b/compatibility-asp-r1/src/main/java/net/momirealms/customcrops/bukkit/integration/adaptor/asp_r1/SlimeWorldAdaptorR1.java @@ -25,6 +25,7 @@ import net.momirealms.customcrops.api.core.block.CustomCropsBlock; import net.momirealms.customcrops.api.core.world.*; import net.momirealms.customcrops.api.core.world.adaptor.AbstractWorldAdaptor; import net.momirealms.customcrops.api.util.StringUtils; +import net.momirealms.customcrops.api.util.TagUtils; import net.momirealms.customcrops.common.helper.GsonHelper; import net.momirealms.customcrops.common.util.Key; import org.bukkit.Bukkit; @@ -231,7 +232,7 @@ public class SlimeWorldAdaptorR1 extends AbstractWorldAdaptor { } for (int pos : (int[]) block.get("pos").getValue()) { BlockPos blockPos = new BlockPos(pos); - blockMap.put(blockPos, CustomCropsBlockState.create(customBlock, data)); + blockMap.put(blockPos, CustomCropsBlockState.create(customBlock, TagUtils.deepClone(data))); } } sectionMap.put(id, CustomCropsSection.restore(id, blockMap)); diff --git a/gradle.properties b/gradle.properties index 8d56eaf..b625b8d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ # Project settings # Rule: [major update].[feature update].[bug fix] -project_version=3.6.5.1 +project_version=3.6.6 config_version=39 project_group=net.momirealms @@ -15,9 +15,9 @@ asm_commons_version=9.7 jar_relocator_version=1.7 adventure_bundle_version=4.17.0 adventure_platform_version=4.3.4 -sparrow_heart_version=0.42 -cloud_core_version=2.0.0-rc.2 -cloud_services_version=2.0.0-rc.2 +sparrow_heart_version=0.43 +cloud_core_version=2.0.0 +cloud_services_version=2.0.0 cloud_brigadier_version=2.0.0-beta.9 cloud_bukkit_version=2.0.0-beta.9 cloud_paper_version=2.0.0-beta.9 diff --git a/plugin/src/main/java/net/momirealms/customcrops/bukkit/integration/adaptor/BukkitWorldAdaptor.java b/plugin/src/main/java/net/momirealms/customcrops/bukkit/integration/adaptor/BukkitWorldAdaptor.java index c2d8e47..9e80463 100644 --- a/plugin/src/main/java/net/momirealms/customcrops/bukkit/integration/adaptor/BukkitWorldAdaptor.java +++ b/plugin/src/main/java/net/momirealms/customcrops/bukkit/integration/adaptor/BukkitWorldAdaptor.java @@ -28,6 +28,7 @@ import net.momirealms.customcrops.api.core.block.CustomCropsBlock; import net.momirealms.customcrops.api.core.world.*; import net.momirealms.customcrops.api.core.world.adaptor.AbstractWorldAdaptor; import net.momirealms.customcrops.api.util.StringUtils; +import net.momirealms.customcrops.api.util.TagUtils; import net.momirealms.customcrops.common.helper.GsonHelper; import net.momirealms.customcrops.common.helper.VersionHelper; import net.momirealms.customcrops.common.util.Key; @@ -423,7 +424,7 @@ public class BukkitWorldAdaptor extends AbstractWorldAdaptor { } for (int pos : (int[]) block.get("pos").getValue()) { BlockPos blockPos = new BlockPos(pos); - blockMap.put(blockPos, CustomCropsBlockState.create(customBlock, data)); + blockMap.put(blockPos, CustomCropsBlockState.create(customBlock, TagUtils.deepClone(data))); } } sectionMap.put(sectionID, CustomCropsSection.restore(sectionID, blockMap)); diff --git a/plugin/src/main/java/net/momirealms/customcrops/bukkit/world/BukkitWorldManager.java b/plugin/src/main/java/net/momirealms/customcrops/bukkit/world/BukkitWorldManager.java index 0290501..8dc63f0 100644 --- a/plugin/src/main/java/net/momirealms/customcrops/bukkit/world/BukkitWorldManager.java +++ b/plugin/src/main/java/net/momirealms/customcrops/bukkit/world/BukkitWorldManager.java @@ -21,6 +21,7 @@ import dev.dejvokep.boostedyaml.YamlDocument; import dev.dejvokep.boostedyaml.block.implementation.Section; import net.momirealms.customcrops.api.BukkitCustomCropsPlugin; import net.momirealms.customcrops.api.core.ConfigManager; +import net.momirealms.customcrops.api.core.TickMode; import net.momirealms.customcrops.api.core.world.*; import net.momirealms.customcrops.api.core.world.adaptor.WorldAdaptor; import net.momirealms.customcrops.api.integration.SeasonProvider; @@ -360,16 +361,10 @@ public class BukkitWorldManager implements WorldManager, Listener { ); } - private static boolean getRandomTickModeByString(String str) { + private static int getRandomTickModeByString(String str) { if (str == null) { - return false; + return 1; } - if (str.equalsIgnoreCase("RANDOM_TICK")) { - return true; - } - if (str.equalsIgnoreCase("SCHEDULED_TICK")) { - return false; - } - throw new IllegalArgumentException("Invalid mode found when loading world settings: " + str); + return TickMode.valueOf(str.toUpperCase(Locale.ENGLISH)).mode(); } }