9
0
mirror of https://github.com/Xiao-MoMi/Custom-Crops.git synced 2025-12-29 11:59:15 +00:00

Implement logic for dead crops

This commit is contained in:
XiaoMoMi
2024-09-03 01:28:01 +08:00
parent 32a4ab166f
commit a21af25570
18 changed files with 137 additions and 106 deletions

View File

@@ -758,17 +758,8 @@ public abstract class AbstractActionManager<T> implements ActionManager<T> {
return;
}
if (applyCorrection) {
Optional<CustomCropsBlockState> optionalState = optionalWorld.get().getBlockState(pos3);
if (optionalState.isPresent()) {
if (optionalState.get().type() instanceof CropBlock cropBlock) {
CropConfig config = cropBlock.config(optionalState.get());
int point = cropBlock.point(optionalState.get());
if (config != null) {
CropStageConfig stageConfig = config.stageWithModelByPoint(point);
location.add(0,stageConfig.displayInfoOffset(),0);
}
}
}
String itemID = plugin.getItemManager().anyID(location.clone().add(0,1,0));
location.add(0,ConfigManager.getOffset(itemID),0);
}
ArrayList<Player> viewers = new ArrayList<>();
if (onlyShowToOne) {

View File

@@ -42,6 +42,9 @@ public class ContextKeys<T> {
public static final ContextKeys<EquipmentSlot> SLOT = of("slot", EquipmentSlot.class);
public static final ContextKeys<String> TEMP_NEAR_PLAYER = of("near", String.class);
public static final ContextKeys<Boolean> OFFLINE = of("offline", Boolean.class);
public static final ContextKeys<String> ICON = of("icon", String.class);
public static final ContextKeys<Integer> MAX_TIMES = of("max_times", Integer.class);
public static final ContextKeys<Integer> LEFT_TIMES = of("left_times", Integer.class);
public static final ContextKeys<Player> PLAYER_INSTANCE = of("player_instance", Player.class);
private final String key;

View File

@@ -50,7 +50,10 @@ import org.bukkit.event.player.PlayerItemDamageEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import java.util.*;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
public abstract class AbstractCustomEventListener implements Listener {
@@ -324,27 +327,8 @@ public abstract class AbstractCustomEventListener implements Listener {
Context<Player> context = Context.player(null);
context.arg(ContextKeys.LOCATION, location);
boneMeal.triggerActions(context);
int afterPoints = Math.min(point + boneMeal.rollPoint(), cropConfig.maxPoints());
cropBlock.point(state, afterPoints);
String afterStage = null;
ExistenceForm afterForm = null;
int tempPoints = afterPoints;
while (tempPoints >= 0) {
Map.Entry<Integer, CropStageConfig> afterEntry = cropConfig.getFloorStageEntry(tempPoints);
CropStageConfig after = afterEntry.getValue();
if (after.stageID() != null) {
afterStage = after.stageID();
afterForm = after.existenceForm();
break;
}
tempPoints = after.point() - 1;
}
Objects.requireNonNull(afterForm);
Objects.requireNonNull(afterStage);
Context<CustomCropsBlockState> blockContext = Context.block(state);
blockContext.arg(ContextKeys.LOCATION, LocationUtils.toBlockLocation(location));
for (int i = point + 1; i <= afterPoints; i++) {
@@ -353,14 +337,15 @@ public abstract class AbstractCustomEventListener implements Listener {
ActionManager.trigger(blockContext, stage.growActions());
}
}
// TODO if the block model chanegs
CropStageConfig currentStage = cropConfig.stageWithModelByPoint(point);
CropStageConfig afterStage = cropConfig.stageWithModelByPoint(afterPoints);
if (currentStage == afterStage) return;
Location bukkitLocation = location.toLocation(world.bukkitWorld());
FurnitureRotation rotation = BukkitCustomCropsPlugin.getInstance().getItemManager().remove(bukkitLocation, ExistenceForm.ANY);
if (rotation == FurnitureRotation.NONE && cropConfig.rotation()) {
rotation = FurnitureRotation.random();
}
BukkitCustomCropsPlugin.getInstance().getItemManager().place(bukkitLocation, afterForm, afterStage, rotation);
BukkitCustomCropsPlugin.getInstance().getItemManager().place(bukkitLocation, afterStage.existenceForm(), Objects.requireNonNull(afterStage.stageID()), rotation);
}
}
}

View File

@@ -27,6 +27,7 @@ import java.util.Objects;
public class BuiltInBlockMechanics {
public static final BuiltInBlockMechanics CROP = create("crop");
public static final BuiltInBlockMechanics DEAD_CROP = create("dead_crop");
public static final BuiltInBlockMechanics SPRINKLER = create("sprinkler");
public static final BuiltInBlockMechanics GREENHOUSE = create("greenhouse");
public static final BuiltInBlockMechanics POT = create("pot");

View File

@@ -63,12 +63,17 @@ public abstract class ConfigManager implements ConfigLoader, Reloadable {
protected boolean preventTrampling;
protected boolean disableMoistureMechanic;
protected HashMap<String, Double> offsets = new HashMap<>();
public ConfigManager(BukkitCustomCropsPlugin plugin) {
this.plugin = plugin;
instance = this;
}
public static double getOffset(String id) {
return instance.offsets.getOrDefault(id, 0d);
}
public static boolean syncSeasons() {
return instance.syncSeasons;
}

View File

@@ -57,4 +57,5 @@ public class Registries {
public static final ClearableRegistry<String, PotConfig> ITEM_TO_POT = new ClearableMappedRegistry<>(Key.key("fast_lookup", "item_to_pot"));
public static final ClearableRegistry<String, SprinklerConfig> ITEM_TO_SPRINKLER = new ClearableMappedRegistry<>(Key.key("fast_lookup", "item_to_sprinkler"));
public static final ClearableRegistry<String, WateringCanConfig> ITEM_TO_WATERING_CAN = new ClearableMappedRegistry<>(Key.key("fast_lookup", "item_to_wateringcan"));
public static final ClearableRegistry<String, Integer> ITEM_TO_DEAD_CROP = new ClearableMappedRegistry<>(Key.key("fast_lookup", "item_to_dead_crop"));
}

View File

@@ -225,22 +225,7 @@ public class CropBlock extends AbstractCustomCropsBlock {
int afterPoints = Math.min(point + boneMeal.rollPoint(), cropConfig.maxPoints());
point(state, afterPoints);
String afterStage = null;
ExistenceForm afterForm = null;
int tempPoints = afterPoints;
while (tempPoints >= 0) {
Map.Entry<Integer, CropStageConfig> afterEntry = cropConfig.getFloorStageEntry(tempPoints);
CropStageConfig after = afterEntry.getValue();
if (after.stageID() != null) {
afterStage = after.stageID();
afterForm = after.existenceForm();
break;
}
tempPoints = after.point() - 1;
}
Objects.requireNonNull(afterForm);
Objects.requireNonNull(afterStage);
CropStageConfig nextStage = cropConfig.stageWithModelByPoint(afterPoints);
Context<CustomCropsBlockState> blockContext = Context.block(state);
blockContext.arg(ContextKeys.LOCATION, LocationUtils.toBlockLocation(location));
@@ -251,13 +236,13 @@ public class CropBlock extends AbstractCustomCropsBlock {
}
}
if (Objects.equals(afterStage, event.relatedID())) return;
if (Objects.equals(nextStage.stageID(), event.relatedID())) return;
Location bukkitLocation = location.toLocation(world.bukkitWorld());
FurnitureRotation rotation = BukkitCustomCropsPlugin.getInstance().getItemManager().remove(bukkitLocation, ExistenceForm.ANY);
if (rotation == FurnitureRotation.NONE && cropConfig.rotation()) {
rotation = FurnitureRotation.random();
}
BukkitCustomCropsPlugin.getInstance().getItemManager().place(bukkitLocation, afterForm, afterStage, rotation);
BukkitCustomCropsPlugin.getInstance().getItemManager().place(bukkitLocation, nextStage.existenceForm(), Objects.requireNonNull(nextStage.stageID()), rotation);
return;
}
}
@@ -363,39 +348,8 @@ public class CropBlock extends AbstractCustomCropsBlock {
int afterPoints = Math.min(previousPoint + pointToAdd, config.maxPoints());
point(state, afterPoints);
int tempPoints = previousPoint;
String preStage = null;
while (tempPoints >= 0) {
Map.Entry<Integer, CropStageConfig> preEntry = config.getFloorStageEntry(tempPoints);
CropStageConfig pre = preEntry.getValue();
if (pre.stageID() != null) {
preStage = pre.stageID();
break;
}
tempPoints = pre.point() - 1;
}
String afterStage = null;
ExistenceForm afterForm = null;
tempPoints = afterPoints;
while (tempPoints >= 0) {
Map.Entry<Integer, CropStageConfig> afterEntry = config.getFloorStageEntry(tempPoints);
CropStageConfig after = afterEntry.getValue();
if (after.stageID() != null) {
afterStage = after.stageID();
afterForm = after.existenceForm();
break;
}
tempPoints = after.point() - 1;
}
final String finalPreStage = preStage;
final String finalAfterStage = afterStage;
final ExistenceForm finalAfterForm = afterForm;
Objects.requireNonNull(finalAfterStage);
Objects.requireNonNull(finalPreStage);
Objects.requireNonNull(finalAfterForm);
CropStageConfig currentStage = config.stageWithModelByPoint(previousPoint);
CropStageConfig nextStage = config.stageWithModelByPoint(afterPoints);
BukkitCustomCropsPlugin.getInstance().getScheduler().sync().run(() -> {
for (int i = previousPoint + 1; i <= afterPoints; i++) {
@@ -404,12 +358,12 @@ public class CropBlock extends AbstractCustomCropsBlock {
ActionManager.trigger(context, stage.growActions());
}
}
if (Objects.equals(finalAfterStage, finalPreStage)) return;
if (currentStage == nextStage) return;
FurnitureRotation rotation = BukkitCustomCropsPlugin.getInstance().getItemManager().remove(bukkitLocation, ExistenceForm.ANY);
if (rotation == FurnitureRotation.NONE && config.rotation()) {
rotation = FurnitureRotation.random();
}
BukkitCustomCropsPlugin.getInstance().getItemManager().place(bukkitLocation, finalAfterForm, finalAfterStage, rotation);
BukkitCustomCropsPlugin.getInstance().getItemManager().place(bukkitLocation, nextStage.existenceForm(), Objects.requireNonNull(nextStage.stageID()), rotation);
}, bukkitLocation);
}

View File

@@ -0,0 +1,66 @@
/*
* 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.block;
import net.momirealms.customcrops.api.BukkitCustomCropsPlugin;
import net.momirealms.customcrops.api.context.Context;
import net.momirealms.customcrops.api.context.ContextKeys;
import net.momirealms.customcrops.api.core.BuiltInBlockMechanics;
import net.momirealms.customcrops.api.core.Registries;
import net.momirealms.customcrops.api.core.world.CustomCropsBlockState;
import net.momirealms.customcrops.api.core.world.CustomCropsWorld;
import net.momirealms.customcrops.api.core.world.Pos3;
import net.momirealms.customcrops.api.core.wrapper.WrappedInteractEvent;
import net.momirealms.customcrops.api.util.LocationUtils;
import org.bukkit.Location;
import org.bukkit.entity.Player;
public class DeadCrop extends AbstractCustomCropsBlock {
public DeadCrop() {
super(BuiltInBlockMechanics.DEAD_CROP.key());
}
@Override
public boolean isBlockInstance(String id) {
return Registries.ITEM_TO_DEAD_CROP.containsKey(id);
}
@Override
public void onInteract(WrappedInteractEvent event) {
final Player player = event.player();
Context<Player> context = Context.player(player);
// data first
CustomCropsWorld<?> world = event.world();
Location location = event.location();
context.arg(ContextKeys.SLOT, event.hand());
// check pot below
Location potLocation = location.clone().subtract(0,1,0);
String blockBelowID = BukkitCustomCropsPlugin.getInstance().getItemManager().blockID(potLocation.getBlock());
PotConfig potConfig = Registries.ITEM_TO_POT.get(blockBelowID);
if (potConfig != null) {
context.arg(ContextKeys.LOCATION, LocationUtils.toBlockLocation(potLocation));
PotBlock potBlock = (PotBlock) BuiltInBlockMechanics.POT.mechanic();
assert potBlock != null;
// fix or get data
CustomCropsBlockState potState = potBlock.fixOrGetState(world, Pos3.from(potLocation), potConfig, event.relatedID());
if (potBlock.tryWateringPot(player, context, potState, event.hand(), event.itemID(), potConfig, potLocation, event.itemInHand()))
return;
}
}
}

View File

@@ -245,6 +245,21 @@ public class PotBlock extends AbstractCustomCropsBlock {
if (tryWateringPot(player, context, state, event.hand(), event.itemID(), potConfig, location, itemInHand))
return;
int water = water(state);
context.arg(ContextKeys.STORAGE, potConfig.storage());
context.arg(ContextKeys.CURRENT_WATER, water);
context.arg(ContextKeys.WATER_BAR, Optional.ofNullable(potConfig.waterBar()).map(it -> it.getWaterBar(water, potConfig.storage())).orElse(""));
Fertilizer[] fertilizers = fertilizers(state);
// for backward compatibility
for (Fertilizer latest : fertilizers) {
FertilizerConfig config = latest.config();
if (config != null) {
context.arg(ContextKeys.ICON, config.icon());
context.arg(ContextKeys.MAX_TIMES, config.times());
context.arg(ContextKeys.LEFT_TIMES, latest.times());
break;
}
}
ActionManager.trigger(context, potConfig.interactActions());
}

View File

@@ -239,8 +239,8 @@ public class WateringCanItem extends AbstractCustomCropsItem {
}
// if the clicked block is a crop, correct the target block
List<CropConfig> cropConfigs = Registries.STAGE_TO_CROP_UNSAFE.get(event.relatedID());
if (cropConfigs != null) {
List<CropConfig> cropConfigs = Registries.STAGE_TO_CROP_UNSAFE.get(targetBlockID);
if (cropConfigs != null || Registries.ITEM_TO_DEAD_CROP.containsKey(targetBlockID)) {
// is a crop
targetLocation = targetLocation.subtract(0,1,0);
targetBlockID = BukkitCustomCropsPlugin.getInstance().getItemManager().blockID(targetLocation);

View File

@@ -19,7 +19,6 @@ package net.momirealms.customcrops.api.core.world;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Optional;
import java.util.PriorityQueue;
import java.util.Set;