9
0
mirror of https://github.com/Xiao-MoMi/Custom-Crops.git synced 2025-12-27 19:09:09 +00:00

deep clone a compound

This commit is contained in:
XiaoMoMi
2024-09-08 16:17:11 +08:00
parent 90b1ce1994
commit e04f787587
10 changed files with 162 additions and 111 deletions

View File

@@ -0,0 +1,35 @@
/*
* Copyright (C) <2024> <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.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;
}
}

View File

@@ -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);
}
}

View File

@@ -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) {

View File

@@ -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);
}
}

View File

@@ -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;
}
/**

View File

@@ -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()));
}
}