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

Try implementing some events

This commit is contained in:
XiaoMoMi
2024-09-02 01:18:25 +08:00
parent 3f98c117fc
commit 32a4ab166f
7 changed files with 455 additions and 18 deletions

View File

@@ -17,20 +17,40 @@
package net.momirealms.customcrops.api.core; package net.momirealms.customcrops.api.core;
import net.momirealms.customcrops.api.BukkitCustomCropsPlugin;
import net.momirealms.customcrops.api.action.ActionManager;
import net.momirealms.customcrops.api.context.Context;
import net.momirealms.customcrops.api.context.ContextKeys;
import net.momirealms.customcrops.api.core.block.*;
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.event.BoneMealDispenseEvent;
import net.momirealms.customcrops.api.util.EventUtils;
import net.momirealms.customcrops.api.util.LocationUtils;
import net.momirealms.customcrops.common.helper.VersionHelper; import net.momirealms.customcrops.common.helper.VersionHelper;
import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.Dispenser;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.block.Action; import org.bukkit.event.block.*;
import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.entity.EntityChangeBlockEvent;
import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.ItemSpawnEvent;
import org.bukkit.event.player.PlayerInteractAtEntityEvent; import org.bukkit.event.player.PlayerInteractAtEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerItemDamageEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import java.util.HashSet; import java.util.*;
import java.util.List;
public abstract class AbstractCustomEventListener implements Listener { public abstract class AbstractCustomEventListener implements Listener {
@@ -135,4 +155,220 @@ public abstract class AbstractCustomEventListener implements Listener {
event event
); );
} }
@EventHandler (ignoreCancelled = true)
public void onItemSpawn(ItemSpawnEvent event) {
Item item = event.getEntity();
ItemStack itemStack = item.getItemStack();
String itemID = this.itemManager.id(itemStack);
if (Registries.STAGE_TO_CROP_UNSAFE.containsKey(itemID)) {
event.setCancelled(true);
return;
}
SprinklerConfig sprinkler = Registries.ITEM_TO_SPRINKLER.get(itemID);
if (sprinkler != null) {
String twoD = sprinkler.twoDItem();
if (twoD != null) {
if (!twoD.equals(itemID)) {
ItemStack newItem = this.itemManager.build(null, twoD);
if (newItem != null && newItem.getType() != Material.AIR) {
newItem.setAmount(itemStack.getAmount());
item.setItemStack(newItem);
}
return;
}
}
}
PotConfig pot = Registries.ITEM_TO_POT.get(itemID);
if (pot != null) {
ItemStack newItem = this.itemManager.build(null, pot.getPotAppearance(false, null));
if (newItem != null && newItem.getType() != Material.AIR) {
newItem.setAmount(itemStack.getAmount());
item.setItemStack(newItem);
}
return;
}
}
@EventHandler (ignoreCancelled = true)
public void onBlockChange(BlockFadeEvent event) {
Block block = event.getBlock();
if (block.getType() == Material.FARMLAND) {
Pos3 above = Pos3.from(block.getLocation()).add(0,1,0);
BukkitCustomCropsPlugin.getInstance().getWorldManager().getWorld(block.getWorld())
.flatMap(world -> world.getBlockState(above)).ifPresent(blockState -> {
if (blockState.type() instanceof CropBlock) {
event.setCancelled(true);
}
});
}
}
@EventHandler (ignoreCancelled = true)
public void onTrampling(EntityChangeBlockEvent event) {
Block block = event.getBlock();
if (block.getType() == Material.FARMLAND && event.getTo() == Material.DIRT) {
if (ConfigManager.preventTrampling()) {
event.setCancelled(true);
return;
}
this.itemManager.handleEntityTrample(event.getEntity(), block.getLocation(), "FARMLAND", event);
}
}
@EventHandler (ignoreCancelled = true)
public void onMoistureChange(MoistureChangeEvent event) {
if (ConfigManager.disableMoistureMechanic())
event.setCancelled(true);
}
@EventHandler (ignoreCancelled = true)
public void onPistonExtend(BlockPistonExtendEvent event) {
Optional<CustomCropsWorld<?>> world = BukkitCustomCropsPlugin.getInstance().getWorldManager().getWorld(event.getBlock().getWorld());
if (world.isEmpty()){
return;
}
CustomCropsWorld<?> w = world.get();
for (Block block : event.getBlocks()) {
if (w.getBlockState(Pos3.from(block.getLocation())).isPresent()) {
event.setCancelled(true);
return;
}
}
}
@EventHandler (ignoreCancelled = true)
public void onPistonRetract(BlockPistonRetractEvent event) {
Optional<CustomCropsWorld<?>> world = BukkitCustomCropsPlugin.getInstance().getWorldManager().getWorld(event.getBlock().getWorld());
if (world.isEmpty()){
return;
}
CustomCropsWorld<?> w = world.get();
for (Block block : event.getBlocks()) {
if (w.getBlockState(Pos3.from(block.getLocation())).isPresent()) {
event.setCancelled(true);
return;
}
}
}
@EventHandler (ignoreCancelled = true)
public void onItemDamage(PlayerItemDamageEvent event) {
ItemStack itemStack = event.getItem();
String itemID = this.itemManager.id(itemStack);
if (Registries.ITEM_TO_WATERING_CAN.containsKey(itemID)) {
event.setCancelled(true);
}
}
@EventHandler (ignoreCancelled = true, priority = EventPriority.HIGHEST)
public void onExplosion(EntityExplodeEvent event) {
Entity entity = event.getEntity();
for (Block block : event.blockList()) {
this.itemManager.handleEntityExplode(entity, block.getLocation(), this.itemManager.blockID(block), event);
if (event.isCancelled()) {
return;
}
}
}
@EventHandler (ignoreCancelled = true, priority = EventPriority.HIGHEST)
public void onExplosion(BlockExplodeEvent event) {
Block exploder = event.getBlock();
for (Block block : event.blockList()) {
this.itemManager.handleBlockExplode(exploder, block.getLocation(), this.itemManager.blockID(block), event);
if (event.isCancelled()) {
return;
}
}
}
@EventHandler (ignoreCancelled = true)
public void onDispenser(BlockDispenseEvent event) {
Block block = event.getBlock();
if (!(block.getBlockData() instanceof org.bukkit.block.data.type.Dispenser directional)) {
return;
}
Optional<CustomCropsWorld<?>> optionalWorld = BukkitCustomCropsPlugin.getInstance().getWorldManager().getWorld(event.getBlock().getWorld());
if (optionalWorld.isEmpty()){
return;
}
CustomCropsWorld<?> world = optionalWorld.get();
Block relative = block.getRelative(directional.getFacing());
Location location = relative.getLocation();
Pos3 pos3 = Pos3.from(location);
world.getBlockState(pos3).ifPresent(state -> {
if (state.type() instanceof CropBlock cropBlock) {
ItemStack itemStack = event.getItem();
String itemID = itemManager.id(itemStack);
CropConfig cropConfig = cropBlock.config(state);
int point = cropBlock.point(state);
if (point < cropConfig.maxPoints()) {
for (BoneMeal boneMeal : cropConfig.boneMeals()) {
if (boneMeal.isDispenserAllowed()) {
if (EventUtils.fireAndCheckCancel(new BoneMealDispenseEvent(block, itemStack, location, boneMeal, state))) {
event.setCancelled(true);
return;
}
if (block.getState() instanceof Dispenser dispenser) {
event.setCancelled(true);
Inventory inventory = dispenser.getInventory();
for (ItemStack storage : inventory.getStorageContents()) {
if (storage == null) continue;
String id = itemManager.id(storage);
if (id.equals(itemID)) {
storage.setAmount(storage.getAmount() - 1);
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++) {
CropStageConfig stage = cropConfig.stageByPoint(i);
if (stage != null) {
ActionManager.trigger(blockContext, stage.growActions());
}
}
// TODO if the block model chanegs
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);
}
}
}
return;
}
}
}
}
});
}
} }

View File

@@ -20,6 +20,7 @@ package net.momirealms.customcrops.api.core;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockFace; import org.bukkit.block.BlockFace;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable; import org.bukkit.event.Cancellable;
import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.EquipmentSlot;
@@ -61,6 +62,27 @@ public abstract class AbstractItemManager implements ItemManager {
Cancellable event Cancellable event
); );
public abstract void handleEntityTrample(
Entity entity,
Location location,
String brokenID,
Cancellable event
);
public abstract void handleEntityExplode(
Entity entity,
Location location,
String brokenID,
Cancellable event
);
public abstract void handleBlockExplode(
Block block,
Location location,
String brokenID,
Cancellable event
);
public abstract void handlePlayerPlace( public abstract void handlePlayerPlace(
Player player, Player player,
Location location, Location location,

View File

@@ -61,7 +61,8 @@ public abstract class ConfigManager implements ConfigLoader, Reloadable {
protected double[] defaultQualityRatio; protected double[] defaultQualityRatio;
protected boolean hasNamespace; protected boolean preventTrampling;
protected boolean disableMoistureMechanic;
public ConfigManager(BukkitCustomCropsPlugin plugin) { public ConfigManager(BukkitCustomCropsPlugin plugin) {
this.plugin = plugin; this.plugin = plugin;
@@ -144,8 +145,12 @@ public abstract class ConfigManager implements ConfigLoader, Reloadable {
return instance.defaultQualityRatio; return instance.defaultQualityRatio;
} }
public static boolean hasNamespace() { public static boolean preventTrampling() {
return instance.hasNamespace; return instance.preventTrampling;
}
public static boolean disableMoistureMechanic() {
return instance.disableMoistureMechanic;
} }
@Override @Override

View File

@@ -36,7 +36,6 @@ public class CrowAttack {
private SchedulerTask task; private SchedulerTask task;
private final Location dynamicLocation; private final Location dynamicLocation;
private final Location cropLocation;
private final Vector vectorDown; private final Vector vectorDown;
private final Vector vectorUp; private final Vector vectorUp;
private final Player[] viewers; private final Player[] viewers;
@@ -52,14 +51,14 @@ public class CrowAttack {
} }
} }
this.viewers = viewers.toArray(new Player[0]); this.viewers = viewers.toArray(new Player[0]);
this.cropLocation = LocationUtils.toBlockCenterLocation(location).add(RandomUtils.generateRandomDouble(-0.25, 0.25), 0, RandomUtils.generateRandomDouble(-0.25, 0.25)); Location landLocation = LocationUtils.toBlockCenterLocation(location).add(RandomUtils.generateRandomDouble(-0.25, 0.25), 0, RandomUtils.generateRandomDouble(-0.25, 0.25));
float yaw = RandomUtils.generateRandomInt(-180, 180); float yaw = RandomUtils.generateRandomInt(-180, 180);
this.cropLocation.setYaw(yaw); landLocation.setYaw(yaw);
this.flyModel = flyModel; this.flyModel = flyModel;
this.standModel = standModel; this.standModel = standModel;
this.dynamicLocation = cropLocation.clone().add((10 * Math.sin((Math.PI * yaw) / 180)), 10, (- 10 * Math.cos((Math.PI * yaw) / 180))); this.dynamicLocation = landLocation.clone().add((10 * Math.sin((Math.PI * yaw) / 180)), 10, (- 10 * Math.cos((Math.PI * yaw) / 180)));
this.dynamicLocation.setYaw(yaw); this.dynamicLocation.setYaw(yaw);
Location relative = cropLocation.clone().subtract(dynamicLocation); Location relative = landLocation.clone().subtract(dynamicLocation);
this.vectorDown = new Vector(relative.getX() / 100, -0.1, relative.getZ() / 100); this.vectorDown = new Vector(relative.getX() / 100, -0.1, relative.getZ() / 100);
this.vectorUp = new Vector(relative.getX() / 100, 0.1, relative.getZ() / 100); this.vectorUp = new Vector(relative.getX() / 100, 0.1, relative.getZ() / 100);
} }

View File

@@ -0,0 +1,121 @@
/*
* Copyright (C) <2022> <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.event;
import net.momirealms.customcrops.api.core.block.BoneMeal;
import net.momirealms.customcrops.api.core.world.CustomCropsBlockState;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
/**
* An event that triggered when the bone meal is dispensed
*/
public class BoneMealDispenseEvent extends Event implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean cancelled;
private final Location location;
private final BoneMeal boneMeal;
private final CustomCropsBlockState blockState;
private final ItemStack boneMealItem;
private final Block dispenser;
public BoneMealDispenseEvent(
@NotNull Block dispenser,
@NotNull ItemStack boneMealItem,
@NotNull Location location,
@NotNull BoneMeal boneMeal,
@NotNull CustomCropsBlockState blockState
) {
this.location = location;
this.blockState = blockState;
this.boneMeal = boneMeal;
this.boneMealItem = boneMealItem;
this.dispenser = dispenser;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
}
@NotNull
public static HandlerList getHandlerList() {
return handlers;
}
@NotNull
@Override
public HandlerList getHandlers() {
return getHandlerList();
}
/**
* Get the crop location
* @return location
*/
@NotNull
public Location getLocation() {
return location;
}
/**
* Get the item in player's hand
* If there's nothing in hand, it would return AIR
* @return item in hand
*/
@NotNull
public ItemStack getBoneMealItem() {
return boneMealItem;
}
@NotNull
public CustomCropsBlockState getBlockState() {
return blockState;
}
/**
* Get the bone meal's config
*
* @return bone meal config
*/
@NotNull
public BoneMeal getBoneMeal() {
return boneMeal;
}
/**
* Get the dispenser block
*
* @return dispenser block
*/
@NotNull
public Block getDispenser() {
return dispenser;
}
}

View File

@@ -36,7 +36,6 @@ import net.momirealms.customcrops.api.core.block.PotConfig;
import net.momirealms.customcrops.api.core.block.SprinklerConfig; import net.momirealms.customcrops.api.core.block.SprinklerConfig;
import net.momirealms.customcrops.api.core.item.FertilizerConfig; import net.momirealms.customcrops.api.core.item.FertilizerConfig;
import net.momirealms.customcrops.api.core.item.WateringCanConfig; import net.momirealms.customcrops.api.core.item.WateringCanConfig;
import net.momirealms.customcrops.api.util.PluginUtils;
import net.momirealms.customcrops.common.helper.AdventureHelper; import net.momirealms.customcrops.common.helper.AdventureHelper;
import net.momirealms.customcrops.common.locale.TranslationManager; import net.momirealms.customcrops.common.locale.TranslationManager;
import net.momirealms.customcrops.common.plugin.CustomCropsProperties; import net.momirealms.customcrops.common.plugin.CustomCropsProperties;
@@ -131,7 +130,8 @@ public class BukkitConfigManager extends ConfigManager {
defaultQualityRatio = getQualityRatio(config.getString("mechanics.default-quality-ratio", "17/2/1")); defaultQualityRatio = getQualityRatio(config.getString("mechanics.default-quality-ratio", "17/2/1"));
hasNamespace = PluginUtils.isEnabled("ItemsAdder"); preventTrampling = config.getBoolean("mechanics.vanilla-farmland.prevent-trampling", false);
disableMoistureMechanic = config.getBoolean("mechanics.vanilla-farmland.disable-moisture-mechanic", false);
} }
@Override @Override

View File

@@ -449,6 +449,51 @@ public class BukkitItemManager extends AbstractItemManager {
} }
} }
@Override
public void handleEntityTrample(Entity entity, Location location, String brokenID, Cancellable event) {
Optional<CustomCropsWorld<?>> optionalWorld = plugin.getWorldManager().getWorld(entity.getWorld());
if (optionalWorld.isEmpty()) {
return;
}
CustomCropsWorld<?> world = optionalWorld.get();
WrappedBreakEvent wrapped = new WrappedBreakEvent(entity, null, world, location, brokenID, null, null, BreakReason.TRAMPLE, event);
CustomCropsBlock customCropsBlock = Registries.BLOCKS.get(brokenID);
if (customCropsBlock != null) {
customCropsBlock.onBreak(wrapped);
}
}
@Override
public void handleEntityExplode(Entity entity, Location location, String brokenID, Cancellable event) {
Optional<CustomCropsWorld<?>> optionalWorld = plugin.getWorldManager().getWorld(entity.getWorld());
if (optionalWorld.isEmpty()) {
return;
}
CustomCropsWorld<?> world = optionalWorld.get();
WrappedBreakEvent wrapped = new WrappedBreakEvent(entity, null, world, location, brokenID, null, null, BreakReason.EXPLODE, event);
CustomCropsBlock customCropsBlock = Registries.BLOCKS.get(brokenID);
if (customCropsBlock != null) {
customCropsBlock.onBreak(wrapped);
}
}
@Override
public void handleBlockExplode(Block block, Location location, String brokenID, Cancellable event) {
Optional<CustomCropsWorld<?>> optionalWorld = plugin.getWorldManager().getWorld(block.getWorld());
if (optionalWorld.isEmpty()) {
return;
}
CustomCropsWorld<?> world = optionalWorld.get();
WrappedBreakEvent wrapped = new WrappedBreakEvent(null, block, world, location, brokenID, null, null, BreakReason.EXPLODE, event);
CustomCropsBlock customCropsBlock = Registries.BLOCKS.get(brokenID);
if (customCropsBlock != null) {
customCropsBlock.onBreak(wrapped);
}
}
@Override @Override
public void handlePlayerPlace(Player player, Location location, String placedID, EquipmentSlot hand, ItemStack itemInHand, Cancellable event) { public void handlePlayerPlace(Player player, Location location, String placedID, EquipmentSlot hand, ItemStack itemInHand, Cancellable event) {
Optional<CustomCropsWorld<?>> optionalWorld = plugin.getWorldManager().getWorld(player.getWorld()); Optional<CustomCropsWorld<?>> optionalWorld = plugin.getWorldManager().getWorld(player.getWorld());
@@ -461,9 +506,18 @@ public class BukkitItemManager extends AbstractItemManager {
Optional<CustomCropsBlockState> optionalState = world.getBlockState(pos3); Optional<CustomCropsBlockState> optionalState = world.getBlockState(pos3);
if (optionalState.isPresent()) { if (optionalState.isPresent()) {
CustomCropsBlockState customCropsBlockState = optionalState.get(); CustomCropsBlockState customCropsBlockState = optionalState.get();
String anyID = anyID(location); String anyFurnitureID = furnitureID(location);
System.out.println(anyID); if (anyFurnitureID != null) {
if (!customCropsBlockState.type().isBlockInstance(anyID)) { if (!customCropsBlockState.type().isBlockInstance(anyFurnitureID)) {
world.removeBlockState(pos3);
plugin.debug("[" + location.getWorld().getName() + "] Removed inconsistent block data at " + pos3 + " which used to be " + customCropsBlockState);
} else {
event.setCancelled(true);
return;
}
}
String anyBlockID = blockID(location);
if (!customCropsBlockState.type().isBlockInstance(anyBlockID)) {
world.removeBlockState(pos3); world.removeBlockState(pos3);
plugin.debug("[" + location.getWorld().getName() + "] Removed inconsistent block data at " + pos3 + " which used to be " + customCropsBlockState); plugin.debug("[" + location.getWorld().getName() + "] Removed inconsistent block data at " + pos3 + " which used to be " + customCropsBlockState);
} else { } else {