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:
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user