mirror of
https://github.com/Xiao-MoMi/Custom-Crops.git
synced 2025-12-19 15:09:25 +00:00
move all built in action impl out of AbstractActionManager
This commit is contained in:
@@ -18,47 +18,9 @@
|
|||||||
package net.momirealms.customcrops.api.action;
|
package net.momirealms.customcrops.api.action;
|
||||||
|
|
||||||
import dev.dejvokep.boostedyaml.block.implementation.Section;
|
import dev.dejvokep.boostedyaml.block.implementation.Section;
|
||||||
import net.kyori.adventure.audience.Audience;
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import net.momirealms.customcrops.api.BukkitCustomCropsPlugin;
|
import net.momirealms.customcrops.api.BukkitCustomCropsPlugin;
|
||||||
import net.momirealms.customcrops.api.context.Context;
|
import net.momirealms.customcrops.api.action.builtin.*;
|
||||||
import net.momirealms.customcrops.api.context.ContextKeys;
|
|
||||||
import net.momirealms.customcrops.api.core.*;
|
|
||||||
import net.momirealms.customcrops.api.core.block.BreakReason;
|
|
||||||
import net.momirealms.customcrops.api.core.block.CropBlock;
|
|
||||||
import net.momirealms.customcrops.api.core.block.PotBlock;
|
|
||||||
import net.momirealms.customcrops.api.core.mechanic.crop.CropConfig;
|
|
||||||
import net.momirealms.customcrops.api.core.mechanic.crop.CropStageConfig;
|
|
||||||
import net.momirealms.customcrops.api.core.mechanic.fertilizer.Fertilizer;
|
|
||||||
import net.momirealms.customcrops.api.core.mechanic.fertilizer.FertilizerConfig;
|
|
||||||
import net.momirealms.customcrops.api.core.mechanic.pot.PotConfig;
|
|
||||||
import net.momirealms.customcrops.api.core.world.CustomCropsBlockState;
|
|
||||||
import net.momirealms.customcrops.api.core.world.CustomCropsChunk;
|
|
||||||
import net.momirealms.customcrops.api.core.world.CustomCropsWorld;
|
|
||||||
import net.momirealms.customcrops.api.core.world.Pos3;
|
|
||||||
import net.momirealms.customcrops.api.core.wrapper.WrappedBreakEvent;
|
|
||||||
import net.momirealms.customcrops.api.event.CropPlantEvent;
|
|
||||||
import net.momirealms.customcrops.api.misc.HologramManager;
|
|
||||||
import net.momirealms.customcrops.api.misc.placeholder.BukkitPlaceholderManager;
|
|
||||||
import net.momirealms.customcrops.api.misc.value.MathValue;
|
|
||||||
import net.momirealms.customcrops.api.misc.value.TextValue;
|
|
||||||
import net.momirealms.customcrops.api.requirement.Requirement;
|
|
||||||
import net.momirealms.customcrops.api.util.*;
|
|
||||||
import net.momirealms.customcrops.common.helper.AdventureHelper;
|
|
||||||
import net.momirealms.customcrops.common.helper.VersionHelper;
|
|
||||||
import net.momirealms.customcrops.common.plugin.scheduler.SchedulerTask;
|
|
||||||
import net.momirealms.customcrops.common.util.ClassUtils;
|
import net.momirealms.customcrops.common.util.ClassUtils;
|
||||||
import net.momirealms.customcrops.common.util.ListUtils;
|
|
||||||
import net.momirealms.customcrops.common.util.Pair;
|
|
||||||
import net.momirealms.customcrops.common.util.RandomUtils;
|
|
||||||
import net.momirealms.sparrow.heart.SparrowHeart;
|
|
||||||
import net.momirealms.sparrow.heart.feature.entity.FakeEntity;
|
|
||||||
import net.momirealms.sparrow.heart.feature.entity.armorstand.FakeArmorStand;
|
|
||||||
import net.momirealms.sparrow.heart.feature.entity.display.FakeItemDisplay;
|
|
||||||
import org.bukkit.*;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.inventory.EquipmentSlot;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@@ -66,10 +28,6 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import static java.util.Objects.requireNonNull;
|
|
||||||
|
|
||||||
public abstract class AbstractActionManager<T> implements ActionManager<T> {
|
public abstract class AbstractActionManager<T> implements ActionManager<T> {
|
||||||
|
|
||||||
@@ -194,55 +152,13 @@ public abstract class AbstractActionManager<T> implements ActionManager<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void registerBroadcastAction() {
|
protected void registerBroadcastAction() {
|
||||||
registerAction((args, chance) -> {
|
registerAction((args, chance) -> new ActionBroadcast<>(plugin, args, chance), "broadcast");
|
||||||
List<String> messages = ListUtils.toList(args);
|
|
||||||
return context -> {
|
|
||||||
if (context.argOrDefault(ContextKeys.OFFLINE, false)) return;
|
|
||||||
if (Math.random() > chance) return;
|
|
||||||
OfflinePlayer offlinePlayer = null;
|
|
||||||
if (context.holder() instanceof Player player) {
|
|
||||||
offlinePlayer = player;
|
|
||||||
}
|
|
||||||
List<String> replaced = plugin.getPlaceholderManager().parse(offlinePlayer, messages, context.placeholderMap());
|
|
||||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
|
||||||
Audience audience = plugin.getSenderFactory().getAudience(player);
|
|
||||||
for (String text : replaced) {
|
|
||||||
audience.sendMessage(AdventureHelper.miniMessage(text));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}, "broadcast");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void registerNearbyMessage() {
|
protected void registerNearbyMessage() {
|
||||||
registerAction((args, chance) -> {
|
registerAction((args, chance) -> {
|
||||||
if (args instanceof Section section) {
|
if (args instanceof Section section) {
|
||||||
List<String> messages = ListUtils.toList(section.get("message"));
|
return new ActionMessageNearby<>(plugin, section, chance);
|
||||||
MathValue<T> range = MathValue.auto(section.get("range"));
|
|
||||||
return context -> {
|
|
||||||
if (context.argOrDefault(ContextKeys.OFFLINE, false)) return;
|
|
||||||
if (Math.random() > chance) return;
|
|
||||||
double realRange = range.evaluate(context);
|
|
||||||
OfflinePlayer owner = null;
|
|
||||||
if (context.holder() instanceof Player player) {
|
|
||||||
owner = player;
|
|
||||||
}
|
|
||||||
Location location = requireNonNull(context.arg(ContextKeys.LOCATION));
|
|
||||||
for (Player player : location.getWorld().getPlayers()) {
|
|
||||||
if (LocationUtils.getDistance(player.getLocation(), location) <= realRange) {
|
|
||||||
context.arg(ContextKeys.TEMP_NEAR_PLAYER, player.getName());
|
|
||||||
List<String> replaced = BukkitPlaceholderManager.getInstance().parse(
|
|
||||||
owner,
|
|
||||||
messages,
|
|
||||||
context.placeholderMap()
|
|
||||||
);
|
|
||||||
Audience audience = plugin.getSenderFactory().getAudience(player);
|
|
||||||
for (String text : replaced) {
|
|
||||||
audience.sendMessage(AdventureHelper.miniMessage(text));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at message-nearby action which should be Section");
|
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at message-nearby action which should be Section");
|
||||||
return Action.empty();
|
return Action.empty();
|
||||||
@@ -253,26 +169,7 @@ public abstract class AbstractActionManager<T> implements ActionManager<T> {
|
|||||||
protected void registerNearbyActionBar() {
|
protected void registerNearbyActionBar() {
|
||||||
registerAction((args, chance) -> {
|
registerAction((args, chance) -> {
|
||||||
if (args instanceof Section section) {
|
if (args instanceof Section section) {
|
||||||
String actionbar = section.getString("actionbar");
|
return new ActionActionbarNearby<>(plugin, section, chance);
|
||||||
MathValue<T> range = MathValue.auto(section.get("range"));
|
|
||||||
return context -> {
|
|
||||||
if (context.argOrDefault(ContextKeys.OFFLINE, false)) return;
|
|
||||||
if (Math.random() > chance) return;
|
|
||||||
OfflinePlayer owner = null;
|
|
||||||
if (context.holder() instanceof Player player) {
|
|
||||||
owner = player;
|
|
||||||
}
|
|
||||||
Location location = requireNonNull(context.arg(ContextKeys.LOCATION));
|
|
||||||
double realRange = range.evaluate(context);
|
|
||||||
for (Player player : location.getWorld().getPlayers()) {
|
|
||||||
if (LocationUtils.getDistance(player.getLocation(), location) <= realRange) {
|
|
||||||
context.arg(ContextKeys.TEMP_NEAR_PLAYER, player.getName());
|
|
||||||
String replaced = plugin.getPlaceholderManager().parse(owner, actionbar, context.placeholderMap());
|
|
||||||
Audience audience = plugin.getSenderFactory().getAudience(player);
|
|
||||||
audience.sendActionBar(AdventureHelper.miniMessage(replaced));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at actionbar-nearby action which should be Section");
|
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at actionbar-nearby action which should be Section");
|
||||||
return Action.empty();
|
return Action.empty();
|
||||||
@@ -281,63 +178,11 @@ public abstract class AbstractActionManager<T> implements ActionManager<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void registerCommandAction() {
|
protected void registerCommandAction() {
|
||||||
registerAction((args, chance) -> {
|
registerAction((args, chance) -> new ActionCommand<>(plugin, args, chance), "command");
|
||||||
List<String> commands = ListUtils.toList(args);
|
registerAction((args, chance) -> new ActionRandomCommand<>(plugin, args, chance), "random-command");
|
||||||
return context -> {
|
|
||||||
if (context.argOrDefault(ContextKeys.OFFLINE, false)) return;
|
|
||||||
if (Math.random() > chance) return;
|
|
||||||
OfflinePlayer owner = null;
|
|
||||||
if (context.holder() instanceof Player player) {
|
|
||||||
owner = player;
|
|
||||||
}
|
|
||||||
List<String> replaced = BukkitPlaceholderManager.getInstance().parse(owner, commands, context.placeholderMap());
|
|
||||||
plugin.getScheduler().sync().run(() -> {
|
|
||||||
for (String text : replaced) {
|
|
||||||
Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), text);
|
|
||||||
}
|
|
||||||
}, null);
|
|
||||||
};
|
|
||||||
}, "command");
|
|
||||||
registerAction((args, chance) -> {
|
|
||||||
List<String> commands = ListUtils.toList(args);
|
|
||||||
return context -> {
|
|
||||||
if (context.argOrDefault(ContextKeys.OFFLINE, false)) return;
|
|
||||||
if (Math.random() > chance) return;
|
|
||||||
OfflinePlayer owner = null;
|
|
||||||
if (context.holder() instanceof Player player) {
|
|
||||||
owner = player;
|
|
||||||
}
|
|
||||||
String random = commands.get(ThreadLocalRandom.current().nextInt(commands.size()));
|
|
||||||
random = BukkitPlaceholderManager.getInstance().parse(owner, random, context.placeholderMap());
|
|
||||||
String finalRandom = random;
|
|
||||||
plugin.getScheduler().sync().run(() -> {
|
|
||||||
Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), finalRandom);
|
|
||||||
}, null);
|
|
||||||
};
|
|
||||||
}, "random-command");
|
|
||||||
registerAction((args, chance) -> {
|
registerAction((args, chance) -> {
|
||||||
if (args instanceof Section section) {
|
if (args instanceof Section section) {
|
||||||
List<String> cmd = ListUtils.toList(section.get("command"));
|
return new ActionCommandNearby<>(plugin, section, chance);
|
||||||
MathValue<T> range = MathValue.auto(section.get("range"));
|
|
||||||
return context -> {
|
|
||||||
if (context.argOrDefault(ContextKeys.OFFLINE, false)) return;
|
|
||||||
if (Math.random() > chance) return;
|
|
||||||
OfflinePlayer owner = null;
|
|
||||||
if (context.holder() instanceof Player player) {
|
|
||||||
owner = player;
|
|
||||||
}
|
|
||||||
double realRange = range.evaluate(context);
|
|
||||||
Location location = requireNonNull(context.arg(ContextKeys.LOCATION));
|
|
||||||
for (Player player : location.getWorld().getPlayers()) {
|
|
||||||
if (LocationUtils.getDistance(player.getLocation(), location) <= realRange) {
|
|
||||||
context.arg(ContextKeys.TEMP_NEAR_PLAYER, player.getName());
|
|
||||||
List<String> replaced = BukkitPlaceholderManager.getInstance().parse(owner, cmd, context.placeholderMap());
|
|
||||||
for (String text : replaced) {
|
|
||||||
Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at command-nearby action which should be Section");
|
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at command-nearby action which should be Section");
|
||||||
return Action.empty();
|
return Action.empty();
|
||||||
@@ -346,109 +191,12 @@ public abstract class AbstractActionManager<T> implements ActionManager<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void registerBundleAction(Class<T> tClass) {
|
protected void registerBundleAction(Class<T> tClass) {
|
||||||
registerAction((args, chance) -> {
|
registerAction((args, chance) -> new ActionBundle<>(plugin, this, args, chance), "chain");
|
||||||
List<Action<T>> actions = new ArrayList<>();
|
registerAction((args, chance) -> new ActionDelay<>(plugin, this, args, chance), "delay");
|
||||||
if (args instanceof Section section) {
|
registerAction((args, chance) -> new ActionTimer<>(plugin, this, args, chance), "timer");
|
||||||
for (Map.Entry<String, Object> entry : section.getStringRouteMappedValues(false).entrySet()) {
|
|
||||||
if (entry.getValue() instanceof Section innerSection) {
|
|
||||||
actions.add(parseAction(innerSection));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return context -> {
|
|
||||||
if (Math.random() > chance) return;
|
|
||||||
for (Action<T> action : actions) {
|
|
||||||
action.trigger(context);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}, "chain");
|
|
||||||
registerAction((args, chance) -> {
|
|
||||||
List<Action<T>> actions = new ArrayList<>();
|
|
||||||
int delay;
|
|
||||||
boolean async;
|
|
||||||
if (args instanceof Section section) {
|
|
||||||
delay = section.getInt("delay", 1);
|
|
||||||
async = section.getBoolean("async", false);
|
|
||||||
Section actionSection = section.getSection("actions");
|
|
||||||
if (actionSection != null)
|
|
||||||
for (Map.Entry<String, Object> entry : actionSection.getStringRouteMappedValues(false).entrySet())
|
|
||||||
if (entry.getValue() instanceof Section innerSection)
|
|
||||||
actions.add(parseAction(innerSection));
|
|
||||||
} else {
|
|
||||||
delay = 1;
|
|
||||||
async = false;
|
|
||||||
}
|
|
||||||
return context -> {
|
|
||||||
if (Math.random() > chance) return;
|
|
||||||
Location location = context.arg(ContextKeys.LOCATION);
|
|
||||||
if (async) {
|
|
||||||
plugin.getScheduler().asyncLater(() -> {
|
|
||||||
for (Action<T> action : actions)
|
|
||||||
action.trigger(context);
|
|
||||||
}, delay * 50L, TimeUnit.MILLISECONDS);
|
|
||||||
} else {
|
|
||||||
plugin.getScheduler().sync().runLater(() -> {
|
|
||||||
for (Action<T> action : actions)
|
|
||||||
action.trigger(context);
|
|
||||||
}, delay, location);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}, "delay");
|
|
||||||
registerAction((args, chance) -> {
|
|
||||||
List<Action<T>> actions = new ArrayList<>();
|
|
||||||
int delay, duration, period;
|
|
||||||
boolean async;
|
|
||||||
if (args instanceof Section section) {
|
|
||||||
delay = section.getInt("delay", 2);
|
|
||||||
duration = section.getInt("duration", 20);
|
|
||||||
period = section.getInt("period", 2);
|
|
||||||
async = section.getBoolean("async", false);
|
|
||||||
Section actionSection = section.getSection("actions");
|
|
||||||
if (actionSection != null)
|
|
||||||
for (Map.Entry<String, Object> entry : actionSection.getStringRouteMappedValues(false).entrySet())
|
|
||||||
if (entry.getValue() instanceof Section innerSection)
|
|
||||||
actions.add(parseAction(innerSection));
|
|
||||||
} else {
|
|
||||||
delay = 1;
|
|
||||||
period = 1;
|
|
||||||
async = false;
|
|
||||||
duration = 20;
|
|
||||||
}
|
|
||||||
return context -> {
|
|
||||||
if (Math.random() > chance) return;
|
|
||||||
Location location = context.arg(ContextKeys.LOCATION);
|
|
||||||
SchedulerTask task;
|
|
||||||
if (async) {
|
|
||||||
task = plugin.getScheduler().asyncRepeating(() -> {
|
|
||||||
for (Action<T> action : actions) {
|
|
||||||
action.trigger(context);
|
|
||||||
}
|
|
||||||
}, delay * 50L, period * 50L, TimeUnit.MILLISECONDS);
|
|
||||||
} else {
|
|
||||||
task = plugin.getScheduler().sync().runRepeating(() -> {
|
|
||||||
for (Action<T> action : actions) {
|
|
||||||
action.trigger(context);
|
|
||||||
}
|
|
||||||
}, delay, period, location);
|
|
||||||
}
|
|
||||||
plugin.getScheduler().asyncLater(task::cancel, duration * 50L, TimeUnit.MILLISECONDS);
|
|
||||||
};
|
|
||||||
}, "timer");
|
|
||||||
registerAction((args, chance) -> {
|
registerAction((args, chance) -> {
|
||||||
if (args instanceof Section section) {
|
if (args instanceof Section section) {
|
||||||
Action<T>[] actions = parseActions(section.getSection("actions"));
|
return new ActionConditional<>(plugin, this, tClass, section, chance);
|
||||||
Requirement<T>[] requirements = plugin.getRequirementManager(tClass).parseRequirements(section.getSection("conditions"), true);
|
|
||||||
return condition -> {
|
|
||||||
if (Math.random() > chance) return;
|
|
||||||
for (Requirement<T> requirement : requirements) {
|
|
||||||
if (!requirement.isSatisfied(condition)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (Action<T> action : actions) {
|
|
||||||
action.trigger(condition);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at conditional action which is expected to be `Section`");
|
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at conditional action which is expected to be `Section`");
|
||||||
return Action.empty();
|
return Action.empty();
|
||||||
@@ -456,31 +204,7 @@ public abstract class AbstractActionManager<T> implements ActionManager<T> {
|
|||||||
}, "conditional");
|
}, "conditional");
|
||||||
registerAction((args, chance) -> {
|
registerAction((args, chance) -> {
|
||||||
if (args instanceof Section section) {
|
if (args instanceof Section section) {
|
||||||
List<Pair<Requirement<T>[], Action<T>[]>> conditionActionPairList = new ArrayList<>();
|
return new ActionPriority<>(plugin, this, tClass, section, chance);
|
||||||
for (Map.Entry<String, Object> entry : section.getStringRouteMappedValues(false).entrySet()) {
|
|
||||||
if (entry.getValue() instanceof Section inner) {
|
|
||||||
Action<T>[] actions = parseActions(inner.getSection("actions"));
|
|
||||||
Requirement<T>[] requirements = plugin.getRequirementManager(tClass).parseRequirements(inner.getSection("conditions"), false);
|
|
||||||
conditionActionPairList.add(Pair.of(requirements, actions));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return context -> {
|
|
||||||
if (Math.random() > chance) return;
|
|
||||||
outer:
|
|
||||||
for (Pair<Requirement<T>[], Action<T>[]> pair : conditionActionPairList) {
|
|
||||||
if (pair.left() != null)
|
|
||||||
for (Requirement<T> requirement : pair.left()) {
|
|
||||||
if (!requirement.isSatisfied(context)) {
|
|
||||||
continue outer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pair.right() != null)
|
|
||||||
for (Action<T> action : pair.right()) {
|
|
||||||
action.trigger(context);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at priority action which is expected to be `Section`");
|
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at priority action which is expected to be `Section`");
|
||||||
return Action.empty();
|
return Action.empty();
|
||||||
@@ -491,28 +215,7 @@ public abstract class AbstractActionManager<T> implements ActionManager<T> {
|
|||||||
protected void registerNearbyTitle() {
|
protected void registerNearbyTitle() {
|
||||||
registerAction((args, chance) -> {
|
registerAction((args, chance) -> {
|
||||||
if (args instanceof Section section) {
|
if (args instanceof Section section) {
|
||||||
TextValue<T> title = TextValue.auto(section.getString("title"));
|
return new ActionTitleNearby<>(plugin, section, chance);
|
||||||
TextValue<T> subtitle = TextValue.auto(section.getString("subtitle"));
|
|
||||||
int fadeIn = section.getInt("fade-in", 20);
|
|
||||||
int stay = section.getInt("stay", 30);
|
|
||||||
int fadeOut = section.getInt("fade-out", 10);
|
|
||||||
int range = section.getInt("range", 0);
|
|
||||||
return context -> {
|
|
||||||
if (context.argOrDefault(ContextKeys.OFFLINE, false)) return;
|
|
||||||
if (Math.random() > chance) return;
|
|
||||||
Location location = requireNonNull(context.arg(ContextKeys.LOCATION));
|
|
||||||
for (Player player : location.getWorld().getPlayers()) {
|
|
||||||
if (LocationUtils.getDistance(player.getLocation(), location) <= range) {
|
|
||||||
context.arg(ContextKeys.TEMP_NEAR_PLAYER, player.getName());
|
|
||||||
Audience audience = plugin.getSenderFactory().getAudience(player);
|
|
||||||
AdventureHelper.sendTitle(audience,
|
|
||||||
AdventureHelper.miniMessage(title.render(context)),
|
|
||||||
AdventureHelper.miniMessage(subtitle.render(context)),
|
|
||||||
fadeIn, stay, fadeOut
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at title-nearby action which is expected to be `Section`");
|
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at title-nearby action which is expected to be `Section`");
|
||||||
return Action.empty();
|
return Action.empty();
|
||||||
@@ -523,54 +226,7 @@ public abstract class AbstractActionManager<T> implements ActionManager<T> {
|
|||||||
protected void registerParticleAction() {
|
protected void registerParticleAction() {
|
||||||
registerAction((args, chance) -> {
|
registerAction((args, chance) -> {
|
||||||
if (args instanceof Section section) {
|
if (args instanceof Section section) {
|
||||||
Particle particleType = ParticleUtils.getParticle(section.getString("particle", "ASH").toUpperCase(Locale.ENGLISH));
|
return new ActionParticle<>(plugin, section, chance);
|
||||||
double x = section.getDouble("x",0.0);
|
|
||||||
double y = section.getDouble("y",0.0);
|
|
||||||
double z = section.getDouble("z",0.0);
|
|
||||||
double offSetX = section.getDouble("offset-x",0.0);
|
|
||||||
double offSetY = section.getDouble("offset-y",0.0);
|
|
||||||
double offSetZ = section.getDouble("offset-z",0.0);
|
|
||||||
int count = section.getInt("count", 1);
|
|
||||||
double extra = section.getDouble("extra", 0.0);
|
|
||||||
float scale = section.getDouble("scale", 1d).floatValue();
|
|
||||||
|
|
||||||
ItemStack itemStack;
|
|
||||||
if (section.contains("itemStack"))
|
|
||||||
itemStack = BukkitCustomCropsPlugin.getInstance()
|
|
||||||
.getItemManager()
|
|
||||||
.build(null, section.getString("itemStack"));
|
|
||||||
else
|
|
||||||
itemStack = null;
|
|
||||||
|
|
||||||
Color color;
|
|
||||||
if (section.contains("color")) {
|
|
||||||
String[] rgb = section.getString("color","255,255,255").split(",");
|
|
||||||
color = Color.fromRGB(Integer.parseInt(rgb[0]), Integer.parseInt(rgb[1]), Integer.parseInt(rgb[2]));
|
|
||||||
} else {
|
|
||||||
color = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Color toColor;
|
|
||||||
if (section.contains("color")) {
|
|
||||||
String[] rgb = section.getString("to-color","255,255,255").split(",");
|
|
||||||
toColor = Color.fromRGB(Integer.parseInt(rgb[0]), Integer.parseInt(rgb[1]), Integer.parseInt(rgb[2]));
|
|
||||||
} else {
|
|
||||||
toColor = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return context -> {
|
|
||||||
if (context.argOrDefault(ContextKeys.OFFLINE, false)) return;
|
|
||||||
if (Math.random() > chance) return;
|
|
||||||
Location location = requireNonNull(context.arg(ContextKeys.LOCATION));
|
|
||||||
location.getWorld().spawnParticle(
|
|
||||||
particleType,
|
|
||||||
location.getX() + x, location.getY() + y, location.getZ() + z,
|
|
||||||
count,
|
|
||||||
offSetX, offSetY, offSetZ,
|
|
||||||
extra,
|
|
||||||
itemStack != null ? itemStack : (color != null && toColor != null ? new Particle.DustTransition(color, toColor, scale) : (color != null ? new Particle.DustOptions(color, scale) : null))
|
|
||||||
);
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at particle action which is expected to be `Section`");
|
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at particle action which is expected to be `Section`");
|
||||||
return Action.empty();
|
return Action.empty();
|
||||||
@@ -581,71 +237,7 @@ public abstract class AbstractActionManager<T> implements ActionManager<T> {
|
|||||||
protected void registerQualityCropsAction() {
|
protected void registerQualityCropsAction() {
|
||||||
registerAction((args, chance) -> {
|
registerAction((args, chance) -> {
|
||||||
if (args instanceof Section section) {
|
if (args instanceof Section section) {
|
||||||
MathValue<T> min = MathValue.auto(section.get("min"));
|
return new ActionQualityCrops<>(plugin, section, chance);
|
||||||
MathValue<T> max = MathValue.auto(section.get("max"));
|
|
||||||
boolean toInv = section.getBoolean("to-inventory", false);
|
|
||||||
String[] qualityLoots = new String[ConfigManager.defaultQualityRatio().length];
|
|
||||||
for (int i = 1; i <= ConfigManager.defaultQualityRatio().length; i++) {
|
|
||||||
qualityLoots[i-1] = section.getString("items." + i);
|
|
||||||
if (qualityLoots[i-1] == null) {
|
|
||||||
plugin.getPluginLogger().warn("items." + i + " should not be null");
|
|
||||||
qualityLoots[i-1] = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return context -> {
|
|
||||||
if (Math.random() > chance) return;
|
|
||||||
double[] ratio = ConfigManager.defaultQualityRatio();
|
|
||||||
int random = RandomUtils.generateRandomInt((int) min.evaluate(context), (int) max.evaluate(context));
|
|
||||||
Location location = requireNonNull(context.arg(ContextKeys.LOCATION));
|
|
||||||
Optional<CustomCropsWorld<?>> world = plugin.getWorldManager().getWorld(location.getWorld());
|
|
||||||
if (world.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Pos3 pos3 = Pos3.from(location);
|
|
||||||
Fertilizer[] fertilizers = null;
|
|
||||||
Player player = null;
|
|
||||||
if (context.holder() instanceof Player p) {
|
|
||||||
player = p;
|
|
||||||
}
|
|
||||||
Pos3 potLocation = pos3.add(0, -1, 0);
|
|
||||||
Optional<CustomCropsChunk> chunk = world.get().getChunk(potLocation.toChunkPos());
|
|
||||||
if (chunk.isPresent()) {
|
|
||||||
Optional<CustomCropsBlockState> state = chunk.get().getBlockState(potLocation);
|
|
||||||
if (state.isPresent()) {
|
|
||||||
if (state.get().type() instanceof PotBlock potBlock) {
|
|
||||||
fertilizers = potBlock.fertilizers(state.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ArrayList<FertilizerConfig> configs = new ArrayList<>();
|
|
||||||
if (fertilizers != null) {
|
|
||||||
for (Fertilizer fertilizer : fertilizers) {
|
|
||||||
Optional.ofNullable(fertilizer.config()).ifPresent(configs::add);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (FertilizerConfig config : configs) {
|
|
||||||
random = config.processDroppedItemAmount(random);
|
|
||||||
double[] newRatio = config.overrideQualityRatio();
|
|
||||||
if (newRatio != null) {
|
|
||||||
ratio = newRatio;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int i = 0; i < random; i++) {
|
|
||||||
double r1 = Math.random();
|
|
||||||
for (int j = 0; j < ratio.length; j++) {
|
|
||||||
if (r1 < ratio[j]) {
|
|
||||||
ItemStack drop = plugin.getItemManager().build(player, qualityLoots[j]);
|
|
||||||
if (drop == null || drop.getType() == Material.AIR) return;
|
|
||||||
if (toInv && player != null) {
|
|
||||||
PlayerUtils.giveItem(player, drop, 1);
|
|
||||||
} else {
|
|
||||||
location.getWorld().dropItemNaturally(location, drop);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at quality-crops action which is expected to be `Section`");
|
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at quality-crops action which is expected to be `Section`");
|
||||||
return Action.empty();
|
return Action.empty();
|
||||||
@@ -656,58 +248,7 @@ public abstract class AbstractActionManager<T> implements ActionManager<T> {
|
|||||||
protected void registerDropItemsAction() {
|
protected void registerDropItemsAction() {
|
||||||
registerAction((args, chance) -> {
|
registerAction((args, chance) -> {
|
||||||
if (args instanceof Section section) {
|
if (args instanceof Section section) {
|
||||||
boolean ignoreFertilizer = section.getBoolean("ignore-fertilizer", true);
|
return new ActionDropItem<>(plugin, section, chance);
|
||||||
String item = section.getString("item");
|
|
||||||
MathValue<T> min = MathValue.auto(section.get("min"));
|
|
||||||
MathValue<T> max = MathValue.auto(section.get("max"));
|
|
||||||
boolean toInv = section.getBoolean("to-inventory", false);
|
|
||||||
return context -> {
|
|
||||||
if (Math.random() > chance) return;
|
|
||||||
Location location = requireNonNull(context.arg(ContextKeys.LOCATION));
|
|
||||||
Optional<CustomCropsWorld<?>> world = plugin.getWorldManager().getWorld(location.getWorld());
|
|
||||||
if (world.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Player player = null;
|
|
||||||
if (context.holder() instanceof Player p) {
|
|
||||||
player = p;
|
|
||||||
}
|
|
||||||
ItemStack itemStack = plugin.getItemManager().build(player, item);
|
|
||||||
if (itemStack != null) {
|
|
||||||
int random = RandomUtils.generateRandomInt((int) min.evaluate(context), (int) max.evaluate(context));
|
|
||||||
if (!ignoreFertilizer) {
|
|
||||||
Pos3 pos3 = Pos3.from(location);
|
|
||||||
Fertilizer[] fertilizers = null;
|
|
||||||
Pos3 potLocation = pos3.add(0, -1, 0);
|
|
||||||
Optional<CustomCropsChunk> chunk = world.get().getChunk(potLocation.toChunkPos());
|
|
||||||
if (chunk.isPresent()) {
|
|
||||||
Optional<CustomCropsBlockState> state = chunk.get().getBlockState(potLocation);
|
|
||||||
if (state.isPresent()) {
|
|
||||||
if (state.get().type() instanceof PotBlock potBlock) {
|
|
||||||
fertilizers = potBlock.fertilizers(state.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ArrayList<FertilizerConfig> configs = new ArrayList<>();
|
|
||||||
if (fertilizers != null) {
|
|
||||||
for (Fertilizer fertilizer : fertilizers) {
|
|
||||||
Optional.ofNullable(fertilizer.config()).ifPresent(configs::add);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (FertilizerConfig config : configs) {
|
|
||||||
random = config.processDroppedItemAmount(random);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
itemStack.setAmount(random);
|
|
||||||
if (toInv && player != null) {
|
|
||||||
PlayerUtils.giveItem(player, itemStack, random);
|
|
||||||
} else {
|
|
||||||
location.getWorld().dropItemNaturally(location, itemStack);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
plugin.getPluginLogger().warn("Item: " + item + " doesn't exist");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at drop-item action which is expected to be `Section`");
|
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at drop-item action which is expected to be `Section`");
|
||||||
return Action.empty();
|
return Action.empty();
|
||||||
@@ -718,25 +259,7 @@ public abstract class AbstractActionManager<T> implements ActionManager<T> {
|
|||||||
protected void registerLegacyDropItemsAction() {
|
protected void registerLegacyDropItemsAction() {
|
||||||
registerAction((args, chance) -> {
|
registerAction((args, chance) -> {
|
||||||
if (args instanceof Section section) {
|
if (args instanceof Section section) {
|
||||||
List<Action<T>> actions = new ArrayList<>();
|
return new ActionDropItemLegacy<>(plugin, this, section, chance);
|
||||||
Section otherItemSection = section.getSection("other-items");
|
|
||||||
if (otherItemSection != null) {
|
|
||||||
for (Map.Entry<String, Object> entry : otherItemSection.getStringRouteMappedValues(false).entrySet()) {
|
|
||||||
if (entry.getValue() instanceof Section inner) {
|
|
||||||
actions.add(requireNonNull(getActionFactory("drop-item")).process(inner, inner.getDouble("chance", 1D)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Section qualitySection = section.getSection("quality-crops");
|
|
||||||
if (qualitySection != null) {
|
|
||||||
actions.add(requireNonNull(getActionFactory("quality-crops")).process(qualitySection, 1));
|
|
||||||
}
|
|
||||||
return context -> {
|
|
||||||
if (Math.random() > chance) return;
|
|
||||||
for (Action<T> action : actions) {
|
|
||||||
action.trigger(context);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at drop-items action which is expected to be `Section`");
|
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at drop-items action which is expected to be `Section`");
|
||||||
return Action.empty();
|
return Action.empty();
|
||||||
@@ -747,51 +270,7 @@ public abstract class AbstractActionManager<T> implements ActionManager<T> {
|
|||||||
protected void registerHologramAction() {
|
protected void registerHologramAction() {
|
||||||
registerAction(((args, chance) -> {
|
registerAction(((args, chance) -> {
|
||||||
if (args instanceof Section section) {
|
if (args instanceof Section section) {
|
||||||
TextValue<T> text = TextValue.auto(section.getString("text", ""));
|
return new ActionHologram<>(plugin, section, chance);
|
||||||
MathValue<T> duration = MathValue.auto(section.get("duration", 20));
|
|
||||||
boolean other = section.getString("position", "other").equals("other");
|
|
||||||
MathValue<T> x = MathValue.auto(section.get("x", 0));
|
|
||||||
MathValue<T> y = MathValue.auto(section.get("y", 0));
|
|
||||||
MathValue<T> z = MathValue.auto(section.get("z", 0));
|
|
||||||
boolean applyCorrection = section.getBoolean("apply-correction", false);
|
|
||||||
boolean onlyShowToOne = !section.getBoolean("visible-to-all", false);
|
|
||||||
int range = section.getInt("range", 32);
|
|
||||||
return context -> {
|
|
||||||
if (context.argOrDefault(ContextKeys.OFFLINE, false)) return;
|
|
||||||
if (context.holder() == null) return;
|
|
||||||
if (Math.random() > chance) return;
|
|
||||||
Player owner = null;
|
|
||||||
if (context.holder() instanceof Player p) {
|
|
||||||
owner = p;
|
|
||||||
}
|
|
||||||
Location location = other ? requireNonNull(context.arg(ContextKeys.LOCATION)).clone() : owner.getLocation().clone();
|
|
||||||
Pos3 pos3 = Pos3.from(location).add(0,1,0);
|
|
||||||
location.add(x.evaluate(context), y.evaluate(context), z.evaluate(context));
|
|
||||||
Optional<CustomCropsWorld<?>> optionalWorld = plugin.getWorldManager().getWorld(location.getWorld());
|
|
||||||
if (optionalWorld.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (applyCorrection) {
|
|
||||||
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) {
|
|
||||||
if (owner == null) return;
|
|
||||||
viewers.add(owner);
|
|
||||||
} else {
|
|
||||||
for (Player player : location.getWorld().getPlayers()) {
|
|
||||||
if (LocationUtils.getDistance(player.getLocation(), location) <= range) {
|
|
||||||
viewers.add(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (viewers.isEmpty()) return;
|
|
||||||
Component component = AdventureHelper.miniMessage(text.render(context));
|
|
||||||
for (Player viewer : viewers) {
|
|
||||||
HologramManager.getInstance().showHologram(viewer, location, AdventureHelper.componentToJson(component), (int) (duration.evaluate(context) * 50));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at hologram action which is expected to be `Section`");
|
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at hologram action which is expected to be `Section`");
|
||||||
return Action.empty();
|
return Action.empty();
|
||||||
@@ -802,66 +281,7 @@ public abstract class AbstractActionManager<T> implements ActionManager<T> {
|
|||||||
protected void registerFakeItemAction() {
|
protected void registerFakeItemAction() {
|
||||||
registerAction(((args, chance) -> {
|
registerAction(((args, chance) -> {
|
||||||
if (args instanceof Section section) {
|
if (args instanceof Section section) {
|
||||||
String itemID = section.getString("item", "");
|
return new ActionFakeItem<>(plugin, section, chance);
|
||||||
String[] split = itemID.split(":");
|
|
||||||
if (split.length >= 2) itemID = split[split.length - 1];
|
|
||||||
MathValue<T> duration = MathValue.auto(section.get("duration", 20));
|
|
||||||
boolean other = section.getString("position", "other").equals("other");
|
|
||||||
MathValue<T> x = MathValue.auto(section.get("x", 0));
|
|
||||||
MathValue<T> y = MathValue.auto(section.get("y", 0));
|
|
||||||
MathValue<T> z = MathValue.auto(section.get("z", 0));
|
|
||||||
MathValue<T> yaw = MathValue.auto(section.get("yaw", 0));
|
|
||||||
int range = section.getInt("range", 32);
|
|
||||||
boolean visibleToAll = section.getBoolean("visible-to-all", true);
|
|
||||||
boolean useItemDisplay = section.getBoolean("use-item-display", false);
|
|
||||||
String finalItemID = itemID;
|
|
||||||
return context -> {
|
|
||||||
if (Math.random() > chance) return;
|
|
||||||
if (context.argOrDefault(ContextKeys.OFFLINE, false)) return;
|
|
||||||
Player owner = null;
|
|
||||||
if (context.holder() instanceof Player p) {
|
|
||||||
owner = p;
|
|
||||||
}
|
|
||||||
Location location = other ? requireNonNull(context.arg(ContextKeys.LOCATION)).clone() : requireNonNull(owner).getLocation().clone();
|
|
||||||
location.add(x.evaluate(context), y.evaluate(context), z.evaluate(context));
|
|
||||||
location.setPitch(0);
|
|
||||||
location.setYaw((float) yaw.evaluate(context));
|
|
||||||
FakeEntity fakeEntity;
|
|
||||||
if (useItemDisplay && VersionHelper.isVersionNewerThan1_19_4()) {
|
|
||||||
location.add(0,1.5,0);
|
|
||||||
FakeItemDisplay itemDisplay = SparrowHeart.getInstance().createFakeItemDisplay(location);
|
|
||||||
itemDisplay.item(plugin.getItemManager().build(owner, finalItemID));
|
|
||||||
fakeEntity = itemDisplay;
|
|
||||||
} else {
|
|
||||||
FakeArmorStand armorStand = SparrowHeart.getInstance().createFakeArmorStand(location);
|
|
||||||
armorStand.invisible(true);
|
|
||||||
armorStand.equipment(EquipmentSlot.HEAD, plugin.getItemManager().build(owner, finalItemID));
|
|
||||||
fakeEntity = armorStand;
|
|
||||||
}
|
|
||||||
ArrayList<Player> viewers = new ArrayList<>();
|
|
||||||
if (range > 0 && visibleToAll) {
|
|
||||||
for (Player player : location.getWorld().getPlayers()) {
|
|
||||||
if (LocationUtils.getDistance(player.getLocation(), location) <= range) {
|
|
||||||
viewers.add(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (owner != null) {
|
|
||||||
viewers.add(owner);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (viewers.isEmpty()) return;
|
|
||||||
for (Player player : viewers) {
|
|
||||||
fakeEntity.spawn(player);
|
|
||||||
}
|
|
||||||
plugin.getScheduler().asyncLater(() -> {
|
|
||||||
for (Player player : viewers) {
|
|
||||||
if (player.isOnline() && player.isValid()) {
|
|
||||||
fakeEntity.destroy(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, (long) (duration.evaluate(context) * 50), TimeUnit.MILLISECONDS);
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at fake-item action which is expected to be `Section`");
|
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at fake-item action which is expected to be `Section`");
|
||||||
return Action.empty();
|
return Action.empty();
|
||||||
@@ -869,62 +289,10 @@ public abstract class AbstractActionManager<T> implements ActionManager<T> {
|
|||||||
}), "fake-item");
|
}), "fake-item");
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
protected void registerPlantAction() {
|
protected void registerPlantAction() {
|
||||||
this.registerAction((args, chance) -> {
|
this.registerAction((args, chance) -> {
|
||||||
if (args instanceof Section section) {
|
if (args instanceof Section section) {
|
||||||
int point = section.getInt("point", 0);
|
return new ActionPlant<>(plugin, section, chance);
|
||||||
String key = requireNonNull(section.getString("crop"));
|
|
||||||
int y = section.getInt("y", 0);
|
|
||||||
boolean triggerAction = section.getBoolean("trigger-event", false);
|
|
||||||
return context -> {
|
|
||||||
if (Math.random() > chance) return;
|
|
||||||
CropConfig cropConfig = Registries.CROP.get(key);
|
|
||||||
if (cropConfig == null) {
|
|
||||||
plugin.getPluginLogger().warn("`plant` action is not executed due to crop[" + key + "] not exists");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Location cropLocation = requireNonNull(context.arg(ContextKeys.LOCATION)).clone().add(0,y,0);
|
|
||||||
Location potLocation = cropLocation.clone().subtract(0,1,0);
|
|
||||||
Optional<CustomCropsWorld<?>> optionalWorld = plugin.getWorldManager().getWorld(cropLocation.getWorld());
|
|
||||||
if (optionalWorld.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
CustomCropsWorld<?> world = optionalWorld.get();
|
|
||||||
PotBlock potBlock = (PotBlock) BuiltInBlockMechanics.POT.mechanic();
|
|
||||||
Pos3 potPos3 = Pos3.from(potLocation);
|
|
||||||
String potItemID = plugin.getItemManager().blockID(potLocation);
|
|
||||||
PotConfig potConfig = Registries.ITEM_TO_POT.get(potItemID);
|
|
||||||
CustomCropsBlockState potState = potBlock.fixOrGetState(world, potPos3, potConfig, potItemID);
|
|
||||||
if (potState == null) {
|
|
||||||
plugin.getPluginLogger().warn("Pot doesn't exist below the crop when executing `plant` action at location[" + world.worldName() + "," + potPos3 + "]");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CropBlock cropBlock = (CropBlock) BuiltInBlockMechanics.CROP.mechanic();
|
|
||||||
CustomCropsBlockState state = BuiltInBlockMechanics.CROP.createBlockState();
|
|
||||||
cropBlock.id(state, key);
|
|
||||||
cropBlock.point(state, point);
|
|
||||||
|
|
||||||
if (context.holder() instanceof Player player) {
|
|
||||||
EquipmentSlot slot = requireNonNull(context.arg(ContextKeys.SLOT));
|
|
||||||
CropPlantEvent plantEvent = new CropPlantEvent(player, player.getInventory().getItem(slot), slot, cropLocation, cropConfig, state, point);
|
|
||||||
if (EventUtils.fireAndCheckCancel(plantEvent)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
cropBlock.point(state, plantEvent.point());
|
|
||||||
if (triggerAction) {
|
|
||||||
ActionManager.trigger((Context<Player>) context, cropConfig.plantActions());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CropStageConfig stageConfigWithModel = cropConfig.stageWithModelByPoint(cropBlock.point(state));
|
|
||||||
world.addBlockState(Pos3.from(cropLocation), state);
|
|
||||||
plugin.getScheduler().sync().run(() -> {
|
|
||||||
plugin.getItemManager().remove(cropLocation, ExistenceForm.ANY);
|
|
||||||
plugin.getItemManager().place(cropLocation, stageConfigWithModel.existenceForm(), requireNonNull(stageConfigWithModel.stageID()), cropConfig.rotation() ? FurnitureRotation.random() : FurnitureRotation.NONE);
|
|
||||||
}, cropLocation);
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at plant action which is expected to be `Section`");
|
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at plant action which is expected to be `Section`");
|
||||||
return Action.empty();
|
return Action.empty();
|
||||||
@@ -933,49 +301,6 @@ public abstract class AbstractActionManager<T> implements ActionManager<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void registerBreakAction() {
|
protected void registerBreakAction() {
|
||||||
this.registerAction((args, chance) -> {
|
this.registerAction((args, chance) -> new ActionBreak<>(plugin, args, chance), "break");
|
||||||
boolean triggerEvent = (boolean) args;
|
|
||||||
return context -> {
|
|
||||||
Location location = requireNonNull(context.arg(ContextKeys.LOCATION));
|
|
||||||
Optional<CustomCropsWorld<?>> optionalWorld = plugin.getWorldManager().getWorld(location.getWorld());
|
|
||||||
if (optionalWorld.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Pos3 pos3 = Pos3.from(location);
|
|
||||||
CustomCropsWorld<?> world = optionalWorld.get();
|
|
||||||
Optional<CustomCropsBlockState> optionalState = world.getBlockState(pos3);
|
|
||||||
if (optionalState.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
CustomCropsBlockState state = optionalState.get();
|
|
||||||
if (!(state.type() instanceof CropBlock cropBlock)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
CropConfig config = cropBlock.config(state);
|
|
||||||
if (config == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (triggerEvent) {
|
|
||||||
CropStageConfig stageConfig = config.stageWithModelByPoint(cropBlock.point(state));
|
|
||||||
Player player = null;
|
|
||||||
if (context.holder() instanceof Player p) {
|
|
||||||
player = p;
|
|
||||||
}
|
|
||||||
DummyCancellable dummyCancellable = new DummyCancellable();
|
|
||||||
if (player != null) {
|
|
||||||
EquipmentSlot slot = requireNonNull(context.arg(ContextKeys.SLOT));
|
|
||||||
ItemStack itemStack = player.getInventory().getItem(slot);
|
|
||||||
state.type().onBreak(new WrappedBreakEvent(player, null, world, location, stageConfig.stageID(), itemStack, plugin.getItemManager().id(itemStack), BreakReason.ACTION, dummyCancellable));
|
|
||||||
} else {
|
|
||||||
state.type().onBreak(new WrappedBreakEvent(null, null, world, location, stageConfig.stageID(), null, null, BreakReason.ACTION, dummyCancellable));
|
|
||||||
}
|
|
||||||
if (dummyCancellable.isCancelled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
world.removeBlockState(pos3);
|
|
||||||
plugin.getItemManager().remove(location, ExistenceForm.ANY);
|
|
||||||
};
|
|
||||||
}, "break");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* 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.action.builtin;
|
||||||
|
|
||||||
|
import net.momirealms.customcrops.api.BukkitCustomCropsPlugin;
|
||||||
|
import net.momirealms.customcrops.api.action.Action;
|
||||||
|
|
||||||
|
public abstract class AbstractBuiltInAction<T> implements Action<T> {
|
||||||
|
protected final BukkitCustomCropsPlugin plugin;
|
||||||
|
protected final double chance;
|
||||||
|
protected AbstractBuiltInAction(BukkitCustomCropsPlugin plugin, double chance) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.chance = chance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BukkitCustomCropsPlugin getPlugin() {
|
||||||
|
return plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getChance() {
|
||||||
|
return chance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean checkChance() {
|
||||||
|
return !(Math.random() > chance);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* 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.action.builtin;
|
||||||
|
|
||||||
|
import dev.dejvokep.boostedyaml.block.implementation.Section;
|
||||||
|
import net.kyori.adventure.audience.Audience;
|
||||||
|
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.misc.value.MathValue;
|
||||||
|
import net.momirealms.customcrops.api.util.LocationUtils;
|
||||||
|
import net.momirealms.customcrops.common.helper.AdventureHelper;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
|
public class ActionActionbarNearby<T> extends AbstractBuiltInAction<T> {
|
||||||
|
final String actionbar;
|
||||||
|
final MathValue<T> range;
|
||||||
|
public ActionActionbarNearby(
|
||||||
|
BukkitCustomCropsPlugin plugin,
|
||||||
|
Section section,
|
||||||
|
double chance
|
||||||
|
) {
|
||||||
|
super(plugin, chance);
|
||||||
|
this.actionbar = section.getString("actionbar");
|
||||||
|
this.range = MathValue.auto(section.get("range"));
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void trigger(Context<T> context) {
|
||||||
|
if (context.argOrDefault(ContextKeys.OFFLINE, false)) return;
|
||||||
|
if (Math.random() > chance) return;
|
||||||
|
OfflinePlayer owner = null;
|
||||||
|
if (context.holder() instanceof Player player) {
|
||||||
|
owner = player;
|
||||||
|
}
|
||||||
|
Location location = requireNonNull(context.arg(ContextKeys.LOCATION));
|
||||||
|
double realRange = range.evaluate(context);
|
||||||
|
for (Player player : location.getWorld().getPlayers()) {
|
||||||
|
if (LocationUtils.getDistance(player.getLocation(), location) <= realRange) {
|
||||||
|
context.arg(ContextKeys.TEMP_NEAR_PLAYER, player.getName());
|
||||||
|
String replaced = plugin.getPlaceholderManager().parse(owner, actionbar, context.placeholderMap());
|
||||||
|
Audience audience = plugin.getSenderFactory().getAudience(player);
|
||||||
|
audience.sendActionBar(AdventureHelper.miniMessage(replaced));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getActionbar() {
|
||||||
|
return actionbar;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MathValue<T> getRange() {
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* 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.action.builtin;
|
||||||
|
|
||||||
|
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.ExistenceForm;
|
||||||
|
import net.momirealms.customcrops.api.core.block.BreakReason;
|
||||||
|
import net.momirealms.customcrops.api.core.block.CropBlock;
|
||||||
|
import net.momirealms.customcrops.api.core.mechanic.crop.CropConfig;
|
||||||
|
import net.momirealms.customcrops.api.core.mechanic.crop.CropStageConfig;
|
||||||
|
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.WrappedBreakEvent;
|
||||||
|
import net.momirealms.customcrops.api.util.DummyCancellable;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.EquipmentSlot;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
|
public class ActionBreak<T> extends AbstractBuiltInAction<T> {
|
||||||
|
final boolean triggerEvent;
|
||||||
|
public ActionBreak(
|
||||||
|
BukkitCustomCropsPlugin plugin,
|
||||||
|
Object args,
|
||||||
|
double chance
|
||||||
|
) {
|
||||||
|
super(plugin, chance);
|
||||||
|
this.triggerEvent = (boolean) args;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void trigger(Context<T> context) {
|
||||||
|
Location location = requireNonNull(context.arg(ContextKeys.LOCATION));
|
||||||
|
Optional<CustomCropsWorld<?>> optionalWorld = plugin.getWorldManager().getWorld(location.getWorld());
|
||||||
|
if (optionalWorld.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Pos3 pos3 = Pos3.from(location);
|
||||||
|
CustomCropsWorld<?> world = optionalWorld.get();
|
||||||
|
Optional<CustomCropsBlockState> optionalState = world.getBlockState(pos3);
|
||||||
|
if (optionalState.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CustomCropsBlockState state = optionalState.get();
|
||||||
|
if (!(state.type() instanceof CropBlock cropBlock)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CropConfig config = cropBlock.config(state);
|
||||||
|
if (config == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (triggerEvent) {
|
||||||
|
CropStageConfig stageConfig = config.stageWithModelByPoint(cropBlock.point(state));
|
||||||
|
Player player = null;
|
||||||
|
if (context.holder() instanceof Player p) {
|
||||||
|
player = p;
|
||||||
|
}
|
||||||
|
DummyCancellable dummyCancellable = new DummyCancellable();
|
||||||
|
if (player != null) {
|
||||||
|
EquipmentSlot slot = requireNonNull(context.arg(ContextKeys.SLOT));
|
||||||
|
ItemStack itemStack = player.getInventory().getItem(slot);
|
||||||
|
state.type().onBreak(new WrappedBreakEvent(player, null, world, location, stageConfig.stageID(), itemStack, plugin.getItemManager().id(itemStack), BreakReason.ACTION, dummyCancellable));
|
||||||
|
} else {
|
||||||
|
state.type().onBreak(new WrappedBreakEvent(null, null, world, location, stageConfig.stageID(), null, null, BreakReason.ACTION, dummyCancellable));
|
||||||
|
}
|
||||||
|
if (dummyCancellable.isCancelled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
world.removeBlockState(pos3);
|
||||||
|
plugin.getItemManager().remove(location, ExistenceForm.ANY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTriggerEvent() {
|
||||||
|
return triggerEvent;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* 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.action.builtin;
|
||||||
|
|
||||||
|
import net.kyori.adventure.audience.Audience;
|
||||||
|
import net.momirealms.customcrops.api.BukkitCustomCropsPlugin;
|
||||||
|
import net.momirealms.customcrops.api.context.Context;
|
||||||
|
import net.momirealms.customcrops.api.context.ContextKeys;
|
||||||
|
import net.momirealms.customcrops.common.helper.AdventureHelper;
|
||||||
|
import net.momirealms.customcrops.common.util.ListUtils;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ActionBroadcast<T> extends AbstractBuiltInAction<T> {
|
||||||
|
final List<String> messages;
|
||||||
|
public ActionBroadcast(
|
||||||
|
BukkitCustomCropsPlugin plugin,
|
||||||
|
Object args,
|
||||||
|
double chance
|
||||||
|
) {
|
||||||
|
super(plugin, chance);
|
||||||
|
this.messages = ListUtils.toList(args);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void trigger(Context<T> context) {
|
||||||
|
if (context.argOrDefault(ContextKeys.OFFLINE, false)) return;
|
||||||
|
if (Math.random() > chance) return;
|
||||||
|
OfflinePlayer offlinePlayer = null;
|
||||||
|
if (context.holder() instanceof Player player) {
|
||||||
|
offlinePlayer = player;
|
||||||
|
}
|
||||||
|
List<String> replaced = plugin.getPlaceholderManager().parse(offlinePlayer, messages, context.placeholderMap());
|
||||||
|
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||||
|
Audience audience = plugin.getSenderFactory().getAudience(player);
|
||||||
|
for (String text : replaced) {
|
||||||
|
audience.sendMessage(AdventureHelper.miniMessage(text));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getMessages() {
|
||||||
|
return messages;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* 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.action.builtin;
|
||||||
|
|
||||||
|
import dev.dejvokep.boostedyaml.block.implementation.Section;
|
||||||
|
import net.momirealms.customcrops.api.BukkitCustomCropsPlugin;
|
||||||
|
import net.momirealms.customcrops.api.action.AbstractActionManager;
|
||||||
|
import net.momirealms.customcrops.api.action.Action;
|
||||||
|
import net.momirealms.customcrops.api.context.Context;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class ActionBundle<T> extends AbstractBuiltInAction<T> {
|
||||||
|
final List<Action<T>> actions;
|
||||||
|
public ActionBundle(
|
||||||
|
BukkitCustomCropsPlugin plugin,
|
||||||
|
AbstractActionManager<T> manager,
|
||||||
|
Object args,
|
||||||
|
double chance
|
||||||
|
) {
|
||||||
|
super(plugin, chance);
|
||||||
|
this.actions = new ArrayList<>();
|
||||||
|
if (args instanceof Section section) {
|
||||||
|
for (Map.Entry<String, Object> entry : section.getStringRouteMappedValues(false).entrySet()) {
|
||||||
|
if (entry.getValue() instanceof Section innerSection) {
|
||||||
|
actions.add(manager.parseAction(innerSection));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void trigger(Context<T> context) {
|
||||||
|
if (!checkChance()) return;
|
||||||
|
for (Action<T> action : actions) {
|
||||||
|
action.trigger(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Action<T>> getActions() {
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* 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.action.builtin;
|
||||||
|
|
||||||
|
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.misc.placeholder.BukkitPlaceholderManager;
|
||||||
|
import net.momirealms.customcrops.common.util.ListUtils;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ActionCommand<T> extends AbstractBuiltInAction<T> {
|
||||||
|
final List<String> commands;
|
||||||
|
public ActionCommand(
|
||||||
|
BukkitCustomCropsPlugin plugin,
|
||||||
|
Object args,
|
||||||
|
double chance
|
||||||
|
) {
|
||||||
|
super(plugin, chance);
|
||||||
|
this.commands = ListUtils.toList(args);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void trigger(Context<T> context) {
|
||||||
|
if (context.argOrDefault(ContextKeys.OFFLINE, false)) return;
|
||||||
|
if (Math.random() > chance) return;
|
||||||
|
OfflinePlayer owner = null;
|
||||||
|
if (context.holder() instanceof Player player) {
|
||||||
|
owner = player;
|
||||||
|
}
|
||||||
|
List<String> replaced = BukkitPlaceholderManager.getInstance().parse(owner, commands, context.placeholderMap());
|
||||||
|
plugin.getScheduler().sync().run(() -> {
|
||||||
|
for (String text : replaced) {
|
||||||
|
Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), text);
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getCommands() {
|
||||||
|
return commands;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* 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.action.builtin;
|
||||||
|
|
||||||
|
import dev.dejvokep.boostedyaml.block.implementation.Section;
|
||||||
|
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.misc.placeholder.BukkitPlaceholderManager;
|
||||||
|
import net.momirealms.customcrops.api.misc.value.MathValue;
|
||||||
|
import net.momirealms.customcrops.api.util.LocationUtils;
|
||||||
|
import net.momirealms.customcrops.common.util.ListUtils;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
|
public class ActionCommandNearby<T> extends AbstractBuiltInAction<T> {
|
||||||
|
final List<String> cmd;
|
||||||
|
final MathValue<T> range;
|
||||||
|
public ActionCommandNearby(
|
||||||
|
BukkitCustomCropsPlugin plugin,
|
||||||
|
Section section,
|
||||||
|
double chance
|
||||||
|
) {
|
||||||
|
super(plugin, chance);
|
||||||
|
this.cmd = ListUtils.toList(section.get("command"));
|
||||||
|
this.range = MathValue.auto(section.get("range"));
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void trigger(Context<T> context) {
|
||||||
|
if (context.argOrDefault(ContextKeys.OFFLINE, false)) return;
|
||||||
|
if (Math.random() > chance) return;
|
||||||
|
OfflinePlayer owner = null;
|
||||||
|
if (context.holder() instanceof Player player) {
|
||||||
|
owner = player;
|
||||||
|
}
|
||||||
|
double realRange = range.evaluate(context);
|
||||||
|
Location location = requireNonNull(context.arg(ContextKeys.LOCATION));
|
||||||
|
for (Player player : location.getWorld().getPlayers()) {
|
||||||
|
if (LocationUtils.getDistance(player.getLocation(), location) <= realRange) {
|
||||||
|
context.arg(ContextKeys.TEMP_NEAR_PLAYER, player.getName());
|
||||||
|
List<String> replaced = BukkitPlaceholderManager.getInstance().parse(owner, cmd, context.placeholderMap());
|
||||||
|
for (String text : replaced) {
|
||||||
|
Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getCmd() {
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MathValue<T> getRange() {
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* 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.action.builtin;
|
||||||
|
|
||||||
|
import dev.dejvokep.boostedyaml.block.implementation.Section;
|
||||||
|
import net.momirealms.customcrops.api.BukkitCustomCropsPlugin;
|
||||||
|
import net.momirealms.customcrops.api.action.AbstractActionManager;
|
||||||
|
import net.momirealms.customcrops.api.action.Action;
|
||||||
|
import net.momirealms.customcrops.api.context.Context;
|
||||||
|
import net.momirealms.customcrops.api.requirement.Requirement;
|
||||||
|
|
||||||
|
public class ActionConditional<T> extends AbstractBuiltInAction<T> {
|
||||||
|
final Action<T>[] actions;
|
||||||
|
final Requirement<T>[] requirements;
|
||||||
|
public ActionConditional(
|
||||||
|
BukkitCustomCropsPlugin plugin,
|
||||||
|
AbstractActionManager<T> manager,
|
||||||
|
Class<T> tClass,
|
||||||
|
Section section,
|
||||||
|
double chance
|
||||||
|
) {
|
||||||
|
super(plugin, chance);
|
||||||
|
this.actions = manager.parseActions(section.getSection("actions"));
|
||||||
|
this.requirements = plugin.getRequirementManager(tClass).parseRequirements(section.getSection("conditions"), true);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void trigger(Context<T> condition) {
|
||||||
|
if (!checkChance()) return;
|
||||||
|
for (Requirement<T> requirement : requirements) {
|
||||||
|
if (!requirement.isSatisfied(condition)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Action<T> action : actions) {
|
||||||
|
action.trigger(condition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action<T>[] getActions() {
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Requirement<T>[] getRequirements() {
|
||||||
|
return requirements;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* 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.action.builtin;
|
||||||
|
|
||||||
|
import dev.dejvokep.boostedyaml.block.implementation.Section;
|
||||||
|
import net.momirealms.customcrops.api.BukkitCustomCropsPlugin;
|
||||||
|
import net.momirealms.customcrops.api.action.AbstractActionManager;
|
||||||
|
import net.momirealms.customcrops.api.action.Action;
|
||||||
|
import net.momirealms.customcrops.api.context.Context;
|
||||||
|
import net.momirealms.customcrops.api.context.ContextKeys;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class ActionDelay<T> extends AbstractBuiltInAction<T> {
|
||||||
|
final List<Action<T>> actions;
|
||||||
|
final int delay;
|
||||||
|
final boolean async;
|
||||||
|
public ActionDelay(
|
||||||
|
BukkitCustomCropsPlugin plugin,
|
||||||
|
AbstractActionManager<T> manager,
|
||||||
|
Object args,
|
||||||
|
double chance
|
||||||
|
) {
|
||||||
|
super(plugin, chance);
|
||||||
|
this.actions = new ArrayList<>();
|
||||||
|
if (args instanceof Section section) {
|
||||||
|
delay = section.getInt("delay", 1);
|
||||||
|
async = section.getBoolean("async", false);
|
||||||
|
Section actionSection = section.getSection("actions");
|
||||||
|
if (actionSection != null)
|
||||||
|
for (Map.Entry<String, Object> entry : actionSection.getStringRouteMappedValues(false).entrySet())
|
||||||
|
if (entry.getValue() instanceof Section innerSection)
|
||||||
|
actions.add(manager.parseAction(innerSection));
|
||||||
|
} else {
|
||||||
|
delay = 1;
|
||||||
|
async = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void trigger(Context<T> context) {
|
||||||
|
if (!checkChance()) return;
|
||||||
|
Location location = context.arg(ContextKeys.LOCATION);
|
||||||
|
if (async) {
|
||||||
|
plugin.getScheduler().asyncLater(() -> {
|
||||||
|
for (Action<T> action : actions)
|
||||||
|
action.trigger(context);
|
||||||
|
}, delay * 50L, TimeUnit.MILLISECONDS);
|
||||||
|
} else {
|
||||||
|
plugin.getScheduler().sync().runLater(() -> {
|
||||||
|
for (Action<T> action : actions)
|
||||||
|
action.trigger(context);
|
||||||
|
}, delay, location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Action<T>> getActions() {
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDelay() {
|
||||||
|
return delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAsync() {
|
||||||
|
return async;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
/*
|
||||||
|
* 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.action.builtin;
|
||||||
|
|
||||||
|
import dev.dejvokep.boostedyaml.block.implementation.Section;
|
||||||
|
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.block.PotBlock;
|
||||||
|
import net.momirealms.customcrops.api.core.mechanic.fertilizer.Fertilizer;
|
||||||
|
import net.momirealms.customcrops.api.core.mechanic.fertilizer.FertilizerConfig;
|
||||||
|
import net.momirealms.customcrops.api.core.world.CustomCropsBlockState;
|
||||||
|
import net.momirealms.customcrops.api.core.world.CustomCropsChunk;
|
||||||
|
import net.momirealms.customcrops.api.core.world.CustomCropsWorld;
|
||||||
|
import net.momirealms.customcrops.api.core.world.Pos3;
|
||||||
|
import net.momirealms.customcrops.api.misc.value.MathValue;
|
||||||
|
import net.momirealms.customcrops.api.util.PlayerUtils;
|
||||||
|
import net.momirealms.customcrops.common.util.RandomUtils;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
|
public class ActionDropItem<T> extends AbstractBuiltInAction<T> {
|
||||||
|
final boolean ignoreFertilizer;
|
||||||
|
final String item;
|
||||||
|
final MathValue<T> min;
|
||||||
|
final MathValue<T> max;
|
||||||
|
final boolean toInv;
|
||||||
|
public ActionDropItem(
|
||||||
|
BukkitCustomCropsPlugin plugin,
|
||||||
|
Section section,
|
||||||
|
double chance
|
||||||
|
) {
|
||||||
|
super(plugin, chance);
|
||||||
|
this.ignoreFertilizer = section.getBoolean("ignore-fertilizer", true);
|
||||||
|
this.item = section.getString("item");
|
||||||
|
this.min = MathValue.auto(section.get("min"));
|
||||||
|
this.max = MathValue.auto(section.get("max"));
|
||||||
|
this.toInv = section.getBoolean("to-inventory", false);
|
||||||
|
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void trigger(Context<T> context) {
|
||||||
|
if (!checkChance()) return;
|
||||||
|
Location location = requireNonNull(context.arg(ContextKeys.LOCATION));
|
||||||
|
Player player = null;
|
||||||
|
if (context.holder() instanceof Player p) {
|
||||||
|
player = p;
|
||||||
|
}
|
||||||
|
int random = RandomUtils.generateRandomInt((int) min.evaluate(context), (int) max.evaluate(context));
|
||||||
|
ItemStack itemStack = generateItem(location, player, random);
|
||||||
|
if (itemStack != null) {
|
||||||
|
if (toInv && player != null) {
|
||||||
|
PlayerUtils.giveItem(player, itemStack, random);
|
||||||
|
} else {
|
||||||
|
location.getWorld().dropItemNaturally(location, itemStack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public ItemStack generateItem(Location location, @Nullable Player player, int amount) {
|
||||||
|
Optional<CustomCropsWorld<?>> world = plugin.getWorldManager().getWorld(location.getWorld());
|
||||||
|
if (world.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ItemStack itemStack = plugin.getItemManager().build(player, item);
|
||||||
|
if (itemStack != null) {
|
||||||
|
if (!ignoreFertilizer) {
|
||||||
|
Pos3 pos3 = Pos3.from(location);
|
||||||
|
Fertilizer[] fertilizers = null;
|
||||||
|
Pos3 potLocation = pos3.add(0, -1, 0);
|
||||||
|
Optional<CustomCropsChunk> chunk = world.get().getChunk(potLocation.toChunkPos());
|
||||||
|
if (chunk.isPresent()) {
|
||||||
|
Optional<CustomCropsBlockState> state = chunk.get().getBlockState(potLocation);
|
||||||
|
if (state.isPresent()) {
|
||||||
|
if (state.get().type() instanceof PotBlock potBlock) {
|
||||||
|
fertilizers = potBlock.fertilizers(state.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ArrayList<FertilizerConfig> configs = new ArrayList<>();
|
||||||
|
if (fertilizers != null) {
|
||||||
|
for (Fertilizer fertilizer : fertilizers) {
|
||||||
|
Optional.ofNullable(fertilizer.config()).ifPresent(configs::add);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (FertilizerConfig config : configs) {
|
||||||
|
amount = config.processDroppedItemAmount(amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
itemStack.setAmount(amount);
|
||||||
|
} else {
|
||||||
|
plugin.getPluginLogger().warn("Item: " + item + " doesn't exist");
|
||||||
|
}
|
||||||
|
return itemStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isIgnoreFertilizer() {
|
||||||
|
return ignoreFertilizer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getItem() {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MathValue<T> getMin() {
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MathValue<T> getMax() {
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isToInv() {
|
||||||
|
return toInv;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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.action.builtin;
|
||||||
|
|
||||||
|
import dev.dejvokep.boostedyaml.block.implementation.Section;
|
||||||
|
import net.momirealms.customcrops.api.BukkitCustomCropsPlugin;
|
||||||
|
import net.momirealms.customcrops.api.action.Action;
|
||||||
|
import net.momirealms.customcrops.api.action.ActionManager;
|
||||||
|
import net.momirealms.customcrops.api.context.Context;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
|
public class ActionDropItemLegacy<T> extends AbstractBuiltInAction<T> {
|
||||||
|
final List<Action<T>> actions;
|
||||||
|
public ActionDropItemLegacy(
|
||||||
|
BukkitCustomCropsPlugin plugin,
|
||||||
|
ActionManager<T> manager,
|
||||||
|
Section section,
|
||||||
|
double chance
|
||||||
|
) {
|
||||||
|
super(plugin, chance);
|
||||||
|
this.actions = new ArrayList<>();
|
||||||
|
Section otherItemSection = section.getSection("other-items");
|
||||||
|
if (otherItemSection != null) {
|
||||||
|
for (Map.Entry<String, Object> entry : otherItemSection.getStringRouteMappedValues(false).entrySet()) {
|
||||||
|
if (entry.getValue() instanceof Section inner) {
|
||||||
|
actions.add(requireNonNull(manager.getActionFactory("drop-item")).process(inner, inner.getDouble("chance", 1D)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Section qualitySection = section.getSection("quality-crops");
|
||||||
|
if (qualitySection != null) {
|
||||||
|
actions.add(requireNonNull(manager.getActionFactory("quality-crops")).process(qualitySection, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void trigger(Context<T> context) {
|
||||||
|
if (!checkChance()) return;
|
||||||
|
for (Action<T> action : actions) {
|
||||||
|
action.trigger(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Action<T>> getActions() {
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,159 @@
|
|||||||
|
/*
|
||||||
|
* 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.action.builtin;
|
||||||
|
|
||||||
|
import dev.dejvokep.boostedyaml.block.implementation.Section;
|
||||||
|
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.misc.value.MathValue;
|
||||||
|
import net.momirealms.customcrops.api.util.LocationUtils;
|
||||||
|
import net.momirealms.customcrops.common.helper.VersionHelper;
|
||||||
|
import net.momirealms.sparrow.heart.SparrowHeart;
|
||||||
|
import net.momirealms.sparrow.heart.feature.entity.FakeEntity;
|
||||||
|
import net.momirealms.sparrow.heart.feature.entity.armorstand.FakeArmorStand;
|
||||||
|
import net.momirealms.sparrow.heart.feature.entity.display.FakeItemDisplay;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.EquipmentSlot;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
|
public class ActionFakeItem<T> extends AbstractBuiltInAction<T> {
|
||||||
|
final String itemID;
|
||||||
|
final MathValue<T> duration;
|
||||||
|
final boolean other;
|
||||||
|
final MathValue<T> x;
|
||||||
|
final MathValue<T> y;
|
||||||
|
final MathValue<T> z;
|
||||||
|
final MathValue<T> yaw;
|
||||||
|
final int range;
|
||||||
|
final boolean visibleToAll;
|
||||||
|
final boolean useItemDisplay;
|
||||||
|
public ActionFakeItem(
|
||||||
|
BukkitCustomCropsPlugin plugin,
|
||||||
|
Section section,
|
||||||
|
double chance
|
||||||
|
) {
|
||||||
|
super(plugin, chance);
|
||||||
|
String itemID = section.getString("item", "");
|
||||||
|
String[] split = itemID.split(":");
|
||||||
|
if (split.length >= 2) itemID = split[split.length - 1];
|
||||||
|
this.itemID = itemID;
|
||||||
|
this.duration = MathValue.auto(section.get("duration", 20));
|
||||||
|
this.other = section.getString("position", "other").equals("other");
|
||||||
|
this.x = MathValue.auto(section.get("x", 0));
|
||||||
|
this.y = MathValue.auto(section.get("y", 0));
|
||||||
|
this.z = MathValue.auto(section.get("z", 0));
|
||||||
|
this.yaw = MathValue.auto(section.get("yaw", 0));
|
||||||
|
this.range = section.getInt("range", 32);
|
||||||
|
this.visibleToAll = section.getBoolean("visible-to-all", true);
|
||||||
|
this.useItemDisplay = section.getBoolean("use-item-display", false);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void trigger(Context<T> context) {
|
||||||
|
if (!checkChance()) return;
|
||||||
|
if (context.argOrDefault(ContextKeys.OFFLINE, false)) return;
|
||||||
|
Player owner = null;
|
||||||
|
if (context.holder() instanceof Player p) {
|
||||||
|
owner = p;
|
||||||
|
}
|
||||||
|
Location location = other ? requireNonNull(context.arg(ContextKeys.LOCATION)).clone() : requireNonNull(owner).getLocation().clone();
|
||||||
|
location.add(x.evaluate(context), y.evaluate(context), z.evaluate(context));
|
||||||
|
location.setPitch(0);
|
||||||
|
location.setYaw((float) yaw.evaluate(context));
|
||||||
|
FakeEntity fakeEntity;
|
||||||
|
if (useItemDisplay && VersionHelper.isVersionNewerThan1_19_4()) {
|
||||||
|
location.add(0,1.5,0);
|
||||||
|
FakeItemDisplay itemDisplay = SparrowHeart.getInstance().createFakeItemDisplay(location);
|
||||||
|
itemDisplay.item(plugin.getItemManager().build(owner, itemID));
|
||||||
|
fakeEntity = itemDisplay;
|
||||||
|
} else {
|
||||||
|
FakeArmorStand armorStand = SparrowHeart.getInstance().createFakeArmorStand(location);
|
||||||
|
armorStand.invisible(true);
|
||||||
|
armorStand.equipment(EquipmentSlot.HEAD, plugin.getItemManager().build(owner, itemID));
|
||||||
|
fakeEntity = armorStand;
|
||||||
|
}
|
||||||
|
ArrayList<Player> viewers = new ArrayList<>();
|
||||||
|
if (range > 0 && visibleToAll) {
|
||||||
|
for (Player player : location.getWorld().getPlayers()) {
|
||||||
|
if (LocationUtils.getDistance(player.getLocation(), location) <= range) {
|
||||||
|
viewers.add(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (owner != null) {
|
||||||
|
viewers.add(owner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (viewers.isEmpty()) return;
|
||||||
|
for (Player player : viewers) {
|
||||||
|
fakeEntity.spawn(player);
|
||||||
|
}
|
||||||
|
plugin.getScheduler().asyncLater(() -> {
|
||||||
|
for (Player player : viewers) {
|
||||||
|
if (player.isOnline() && player.isValid()) {
|
||||||
|
fakeEntity.destroy(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, (long) (duration.evaluate(context) * 50), TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getItemID() {
|
||||||
|
return itemID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MathValue<T> getDuration() {
|
||||||
|
return duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOther() {
|
||||||
|
return other;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MathValue<T> getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MathValue<T> getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MathValue<T> getZ() {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MathValue<T> getYaw() {
|
||||||
|
return yaw;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRange() {
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isVisibleToAll() {
|
||||||
|
return visibleToAll;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isUseItemDisplay() {
|
||||||
|
return useItemDisplay;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
package net.momirealms.customcrops.api.action.builtin;
|
||||||
|
|
||||||
|
import dev.dejvokep.boostedyaml.block.implementation.Section;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
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.ConfigManager;
|
||||||
|
import net.momirealms.customcrops.api.core.world.CustomCropsWorld;
|
||||||
|
import net.momirealms.customcrops.api.misc.HologramManager;
|
||||||
|
import net.momirealms.customcrops.api.misc.value.MathValue;
|
||||||
|
import net.momirealms.customcrops.api.misc.value.TextValue;
|
||||||
|
import net.momirealms.customcrops.api.util.LocationUtils;
|
||||||
|
import net.momirealms.customcrops.common.helper.AdventureHelper;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
|
public class ActionHologram<T> extends AbstractBuiltInAction<T> {
|
||||||
|
final TextValue<T> text;
|
||||||
|
final MathValue<T> duration;
|
||||||
|
final boolean other;
|
||||||
|
final MathValue<T> x;
|
||||||
|
final MathValue<T> y;
|
||||||
|
final MathValue<T> z;
|
||||||
|
final boolean applyCorrection;
|
||||||
|
final boolean onlyShowToOne;
|
||||||
|
final int range;
|
||||||
|
public ActionHologram(
|
||||||
|
BukkitCustomCropsPlugin plugin,
|
||||||
|
Section section,
|
||||||
|
double chance
|
||||||
|
) {
|
||||||
|
super(plugin, chance);
|
||||||
|
this.text = TextValue.auto(section.getString("text", ""));
|
||||||
|
this.duration = MathValue.auto(section.get("duration", 20));
|
||||||
|
this.other = section.getString("position", "other").equals("other");
|
||||||
|
this.x = MathValue.auto(section.get("x", 0));
|
||||||
|
this.y = MathValue.auto(section.get("y", 0));
|
||||||
|
this.z = MathValue.auto(section.get("z", 0));
|
||||||
|
this.applyCorrection = section.getBoolean("apply-correction", false);
|
||||||
|
this.onlyShowToOne = !section.getBoolean("visible-to-all", false);
|
||||||
|
this.range = section.getInt("range", 32);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void trigger(Context<T> context) {
|
||||||
|
if (context.argOrDefault(ContextKeys.OFFLINE, false)) return;
|
||||||
|
if (context.holder() == null) return;
|
||||||
|
if (Math.random() > chance) return;
|
||||||
|
Player owner = null;
|
||||||
|
if (context.holder() instanceof Player p) {
|
||||||
|
owner = p;
|
||||||
|
}
|
||||||
|
Location location = other ? requireNonNull(context.arg(ContextKeys.LOCATION)).clone() : owner.getLocation().clone();
|
||||||
|
// Pos3 pos3 = Pos3.from(location).add(0,1,0);
|
||||||
|
location.add(x.evaluate(context), y.evaluate(context), z.evaluate(context));
|
||||||
|
Optional<CustomCropsWorld<?>> optionalWorld = plugin.getWorldManager().getWorld(location.getWorld());
|
||||||
|
if (optionalWorld.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (applyCorrection) {
|
||||||
|
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) {
|
||||||
|
if (owner == null) return;
|
||||||
|
viewers.add(owner);
|
||||||
|
} else {
|
||||||
|
for (Player player : location.getWorld().getPlayers()) {
|
||||||
|
if (LocationUtils.getDistance(player.getLocation(), location) <= range) {
|
||||||
|
viewers.add(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (viewers.isEmpty()) return;
|
||||||
|
Component component = AdventureHelper.miniMessage(text.render(context));
|
||||||
|
for (Player viewer : viewers) {
|
||||||
|
HologramManager.getInstance().showHologram(viewer, location, AdventureHelper.componentToJson(component), (int) (duration.evaluate(context) * 50));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextValue<T> getText() {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MathValue<T> getDuration() {
|
||||||
|
return duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOther() {
|
||||||
|
return other;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MathValue<T> getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MathValue<T> getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MathValue<T> getZ() {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isApplyCorrection() {
|
||||||
|
return applyCorrection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOnlyShowToOne() {
|
||||||
|
return onlyShowToOne;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRange() {
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* 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.action.builtin;
|
||||||
|
|
||||||
|
import dev.dejvokep.boostedyaml.block.implementation.Section;
|
||||||
|
import net.kyori.adventure.audience.Audience;
|
||||||
|
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.misc.placeholder.BukkitPlaceholderManager;
|
||||||
|
import net.momirealms.customcrops.api.misc.value.MathValue;
|
||||||
|
import net.momirealms.customcrops.api.util.LocationUtils;
|
||||||
|
import net.momirealms.customcrops.common.helper.AdventureHelper;
|
||||||
|
import net.momirealms.customcrops.common.util.ListUtils;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
|
public class ActionMessageNearby<T> extends AbstractBuiltInAction<T> {
|
||||||
|
final List<String> messages;
|
||||||
|
final MathValue<T> range;
|
||||||
|
public ActionMessageNearby(
|
||||||
|
BukkitCustomCropsPlugin plugin,
|
||||||
|
Section section,
|
||||||
|
double chance
|
||||||
|
) {
|
||||||
|
super(plugin, chance);
|
||||||
|
this.messages = ListUtils.toList(section.get("message"));
|
||||||
|
this.range = MathValue.auto(section.get("range"));
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void trigger(Context<T> context) {
|
||||||
|
if (context.argOrDefault(ContextKeys.OFFLINE, false)) return;
|
||||||
|
if (Math.random() > chance) return;
|
||||||
|
double realRange = range.evaluate(context);
|
||||||
|
OfflinePlayer owner = null;
|
||||||
|
if (context.holder() instanceof Player player) {
|
||||||
|
owner = player;
|
||||||
|
}
|
||||||
|
Location location = requireNonNull(context.arg(ContextKeys.LOCATION));
|
||||||
|
for (Player player : location.getWorld().getPlayers()) {
|
||||||
|
if (LocationUtils.getDistance(player.getLocation(), location) <= realRange) {
|
||||||
|
context.arg(ContextKeys.TEMP_NEAR_PLAYER, player.getName());
|
||||||
|
List<String> replaced = BukkitPlaceholderManager.getInstance().parse(
|
||||||
|
owner,
|
||||||
|
messages,
|
||||||
|
context.placeholderMap()
|
||||||
|
);
|
||||||
|
Audience audience = plugin.getSenderFactory().getAudience(player);
|
||||||
|
for (String text : replaced) {
|
||||||
|
audience.sendMessage(AdventureHelper.miniMessage(text));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getMessages() {
|
||||||
|
return messages;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MathValue<T> getRange() {
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
* 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.action.builtin;
|
||||||
|
|
||||||
|
import dev.dejvokep.boostedyaml.block.implementation.Section;
|
||||||
|
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.util.ParticleUtils;
|
||||||
|
import org.bukkit.Color;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Particle;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
|
public class ActionParticle<T> extends AbstractBuiltInAction<T> {
|
||||||
|
final Particle particleType;
|
||||||
|
final double x;
|
||||||
|
final double y;
|
||||||
|
final double z;
|
||||||
|
final double offSetX;
|
||||||
|
final double offSetY;
|
||||||
|
final double offSetZ;
|
||||||
|
final int count;
|
||||||
|
final double extra;
|
||||||
|
final float scale;
|
||||||
|
final ItemStack itemStack;
|
||||||
|
final Color color;
|
||||||
|
final Color toColor;
|
||||||
|
public ActionParticle(
|
||||||
|
BukkitCustomCropsPlugin plugin,
|
||||||
|
Section section,
|
||||||
|
double chance
|
||||||
|
) {
|
||||||
|
super(plugin, chance);
|
||||||
|
this.particleType = ParticleUtils.getParticle(section.getString("particle", "ASH").toUpperCase(Locale.ENGLISH));
|
||||||
|
this.x = section.getDouble("x",0.0);
|
||||||
|
this.y = section.getDouble("y",0.0);
|
||||||
|
this.z = section.getDouble("z",0.0);
|
||||||
|
this.offSetX = section.getDouble("offset-x",0.0);
|
||||||
|
this.offSetY = section.getDouble("offset-y",0.0);
|
||||||
|
this.offSetZ = section.getDouble("offset-z",0.0);
|
||||||
|
this.count = section.getInt("count", 1);
|
||||||
|
this.extra = section.getDouble("extra", 0.0);
|
||||||
|
this.scale = section.getDouble("scale", 1d).floatValue();
|
||||||
|
|
||||||
|
if (section.contains("itemStack"))
|
||||||
|
itemStack = BukkitCustomCropsPlugin.getInstance()
|
||||||
|
.getItemManager()
|
||||||
|
.build(null, section.getString("itemStack"));
|
||||||
|
else
|
||||||
|
itemStack = null;
|
||||||
|
|
||||||
|
if (section.contains("color")) {
|
||||||
|
String[] rgb = section.getString("color","255,255,255").split(",");
|
||||||
|
color = Color.fromRGB(Integer.parseInt(rgb[0]), Integer.parseInt(rgb[1]), Integer.parseInt(rgb[2]));
|
||||||
|
} else {
|
||||||
|
color = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (section.contains("color")) {
|
||||||
|
String[] rgb = section.getString("to-color","255,255,255").split(",");
|
||||||
|
toColor = Color.fromRGB(Integer.parseInt(rgb[0]), Integer.parseInt(rgb[1]), Integer.parseInt(rgb[2]));
|
||||||
|
} else {
|
||||||
|
toColor = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void trigger(Context<T> context) {
|
||||||
|
if (context.argOrDefault(ContextKeys.OFFLINE, false)) return;
|
||||||
|
if (Math.random() > chance) return;
|
||||||
|
Location location = requireNonNull(context.arg(ContextKeys.LOCATION));
|
||||||
|
location.getWorld().spawnParticle(
|
||||||
|
particleType,
|
||||||
|
location.getX() + x, location.getY() + y, location.getZ() + z,
|
||||||
|
count,
|
||||||
|
offSetX, offSetY, offSetZ,
|
||||||
|
extra,
|
||||||
|
itemStack != null ? itemStack : (color != null && toColor != null ? new Particle.DustTransition(color, toColor, scale) : (color != null ? new Particle.DustOptions(color, scale) : null))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Particle getParticleType() {
|
||||||
|
return particleType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getZ() {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getOffSetX() {
|
||||||
|
return offSetX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getOffSetY() {
|
||||||
|
return offSetY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getOffSetZ() {
|
||||||
|
return offSetZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCount() {
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getExtra() {
|
||||||
|
return extra;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getScale() {
|
||||||
|
return scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack getItemStack() {
|
||||||
|
return itemStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color getColor() {
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color getToColor() {
|
||||||
|
return toColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
* 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.action.builtin;
|
||||||
|
|
||||||
|
import dev.dejvokep.boostedyaml.block.implementation.Section;
|
||||||
|
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.BuiltInBlockMechanics;
|
||||||
|
import net.momirealms.customcrops.api.core.ExistenceForm;
|
||||||
|
import net.momirealms.customcrops.api.core.FurnitureRotation;
|
||||||
|
import net.momirealms.customcrops.api.core.Registries;
|
||||||
|
import net.momirealms.customcrops.api.core.block.CropBlock;
|
||||||
|
import net.momirealms.customcrops.api.core.block.PotBlock;
|
||||||
|
import net.momirealms.customcrops.api.core.mechanic.crop.CropConfig;
|
||||||
|
import net.momirealms.customcrops.api.core.mechanic.crop.CropStageConfig;
|
||||||
|
import net.momirealms.customcrops.api.core.mechanic.pot.PotConfig;
|
||||||
|
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.CropPlantEvent;
|
||||||
|
import net.momirealms.customcrops.api.util.EventUtils;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.EquipmentSlot;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
|
public class ActionPlant<T> extends AbstractBuiltInAction<T> {
|
||||||
|
final int point;
|
||||||
|
final String key;
|
||||||
|
final int y;
|
||||||
|
final boolean triggerAction;
|
||||||
|
public ActionPlant(
|
||||||
|
BukkitCustomCropsPlugin plugin,
|
||||||
|
Section section,
|
||||||
|
double chance
|
||||||
|
) {
|
||||||
|
super(plugin, chance);
|
||||||
|
this.point = section.getInt("point", 0);
|
||||||
|
this.key = requireNonNull(section.getString("crop"));
|
||||||
|
this.y = section.getInt("y", 0);
|
||||||
|
this.triggerAction = section.getBoolean("trigger-event", false);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void trigger(Context<T> context) {
|
||||||
|
if (!checkChance()) return;
|
||||||
|
CropConfig cropConfig = Registries.CROP.get(key);
|
||||||
|
if (cropConfig == null) {
|
||||||
|
plugin.getPluginLogger().warn("`plant` action is not executed due to crop[" + key + "] not exists");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Location cropLocation = requireNonNull(context.arg(ContextKeys.LOCATION)).clone().add(0,y,0);
|
||||||
|
Location potLocation = cropLocation.clone().subtract(0,1,0);
|
||||||
|
Optional<CustomCropsWorld<?>> optionalWorld = plugin.getWorldManager().getWorld(cropLocation.getWorld());
|
||||||
|
if (optionalWorld.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CustomCropsWorld<?> world = optionalWorld.get();
|
||||||
|
PotBlock potBlock = (PotBlock) BuiltInBlockMechanics.POT.mechanic();
|
||||||
|
Pos3 potPos3 = Pos3.from(potLocation);
|
||||||
|
String potItemID = plugin.getItemManager().blockID(potLocation);
|
||||||
|
PotConfig potConfig = Registries.ITEM_TO_POT.get(potItemID);
|
||||||
|
CustomCropsBlockState potState = potBlock.fixOrGetState(world, potPos3, potConfig, potItemID);
|
||||||
|
if (potState == null) {
|
||||||
|
plugin.getPluginLogger().warn("Pot doesn't exist below the crop when executing `plant` action at location[" + world.worldName() + "," + potPos3 + "]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CropBlock cropBlock = (CropBlock) BuiltInBlockMechanics.CROP.mechanic();
|
||||||
|
CustomCropsBlockState state = BuiltInBlockMechanics.CROP.createBlockState();
|
||||||
|
cropBlock.id(state, key);
|
||||||
|
cropBlock.point(state, point);
|
||||||
|
|
||||||
|
if (context.holder() instanceof Player player) {
|
||||||
|
EquipmentSlot slot = requireNonNull(context.arg(ContextKeys.SLOT));
|
||||||
|
CropPlantEvent plantEvent = new CropPlantEvent(player, player.getInventory().getItem(slot), slot, cropLocation, cropConfig, state, point);
|
||||||
|
if (EventUtils.fireAndCheckCancel(plantEvent)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cropBlock.point(state, plantEvent.point());
|
||||||
|
if (triggerAction) {
|
||||||
|
ActionManager.trigger((Context<Player>) context, cropConfig.plantActions());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CropStageConfig stageConfigWithModel = cropConfig.stageWithModelByPoint(cropBlock.point(state));
|
||||||
|
world.addBlockState(Pos3.from(cropLocation), state);
|
||||||
|
plugin.getScheduler().sync().run(() -> {
|
||||||
|
plugin.getItemManager().remove(cropLocation, ExistenceForm.ANY);
|
||||||
|
plugin.getItemManager().place(cropLocation, stageConfigWithModel.existenceForm(), requireNonNull(stageConfigWithModel.stageID()), cropConfig.rotation() ? FurnitureRotation.random() : FurnitureRotation.NONE);
|
||||||
|
}, cropLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPoint() {
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTriggerAction() {
|
||||||
|
return triggerAction;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* 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.action.builtin;
|
||||||
|
|
||||||
|
import dev.dejvokep.boostedyaml.block.implementation.Section;
|
||||||
|
import net.momirealms.customcrops.api.BukkitCustomCropsPlugin;
|
||||||
|
import net.momirealms.customcrops.api.action.AbstractActionManager;
|
||||||
|
import net.momirealms.customcrops.api.action.Action;
|
||||||
|
import net.momirealms.customcrops.api.context.Context;
|
||||||
|
import net.momirealms.customcrops.api.requirement.Requirement;
|
||||||
|
import net.momirealms.customcrops.common.util.Pair;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class ActionPriority<T> extends AbstractBuiltInAction<T> {
|
||||||
|
final List<Pair<Requirement<T>[], Action<T>[]>> conditionActionPairList;
|
||||||
|
public ActionPriority(
|
||||||
|
BukkitCustomCropsPlugin plugin,
|
||||||
|
AbstractActionManager<T> manager,
|
||||||
|
Class<T> tClass,
|
||||||
|
Section section,
|
||||||
|
double chance
|
||||||
|
) {
|
||||||
|
super(plugin, chance);
|
||||||
|
this.conditionActionPairList = new ArrayList<>();
|
||||||
|
for (Map.Entry<String, Object> entry : section.getStringRouteMappedValues(false).entrySet()) {
|
||||||
|
if (entry.getValue() instanceof Section inner) {
|
||||||
|
Action<T>[] actions = manager.parseActions(inner.getSection("actions"));
|
||||||
|
Requirement<T>[] requirements = plugin.getRequirementManager(tClass).parseRequirements(inner.getSection("conditions"), false);
|
||||||
|
conditionActionPairList.add(Pair.of(requirements, actions));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void trigger(Context<T> context) {
|
||||||
|
if (!checkChance()) return;
|
||||||
|
outer:
|
||||||
|
for (Pair<Requirement<T>[], Action<T>[]> pair : conditionActionPairList) {
|
||||||
|
if (pair.left() != null)
|
||||||
|
for (Requirement<T> requirement : pair.left()) {
|
||||||
|
if (!requirement.isSatisfied(context)) {
|
||||||
|
continue outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pair.right() != null)
|
||||||
|
for (Action<T> action : pair.right()) {
|
||||||
|
action.trigger(context);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Pair<Requirement<T>[], Action<T>[]>> getConditionActionPairList() {
|
||||||
|
return conditionActionPairList;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
* 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.action.builtin;
|
||||||
|
|
||||||
|
import dev.dejvokep.boostedyaml.block.implementation.Section;
|
||||||
|
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.ConfigManager;
|
||||||
|
import net.momirealms.customcrops.api.core.block.PotBlock;
|
||||||
|
import net.momirealms.customcrops.api.core.mechanic.fertilizer.Fertilizer;
|
||||||
|
import net.momirealms.customcrops.api.core.mechanic.fertilizer.FertilizerConfig;
|
||||||
|
import net.momirealms.customcrops.api.core.world.CustomCropsBlockState;
|
||||||
|
import net.momirealms.customcrops.api.core.world.CustomCropsChunk;
|
||||||
|
import net.momirealms.customcrops.api.core.world.CustomCropsWorld;
|
||||||
|
import net.momirealms.customcrops.api.core.world.Pos3;
|
||||||
|
import net.momirealms.customcrops.api.misc.value.MathValue;
|
||||||
|
import net.momirealms.customcrops.api.util.PlayerUtils;
|
||||||
|
import net.momirealms.customcrops.common.util.RandomUtils;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
|
public class ActionQualityCrops<T> extends AbstractBuiltInAction<T> {
|
||||||
|
final MathValue<T> min;
|
||||||
|
final MathValue<T> max;
|
||||||
|
final boolean toInv;
|
||||||
|
final String[] qualityLoots;
|
||||||
|
public ActionQualityCrops(
|
||||||
|
BukkitCustomCropsPlugin plugin,
|
||||||
|
Section section,
|
||||||
|
double chance
|
||||||
|
) {
|
||||||
|
super(plugin, chance);
|
||||||
|
this.min = MathValue.auto(section.get("min"));
|
||||||
|
this.max = MathValue.auto(section.get("max"));
|
||||||
|
this.toInv = section.getBoolean("to-inventory", false);
|
||||||
|
this.qualityLoots = new String[ConfigManager.defaultQualityRatio().length];
|
||||||
|
for (int i = 1; i <= ConfigManager.defaultQualityRatio().length; i++) {
|
||||||
|
qualityLoots[i-1] = section.getString("items." + i);
|
||||||
|
if (qualityLoots[i-1] == null) {
|
||||||
|
plugin.getPluginLogger().warn("items." + i + " should not be null");
|
||||||
|
qualityLoots[i-1] = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void trigger(Context<T> context) {
|
||||||
|
if (!checkChance()) return;
|
||||||
|
Location location = requireNonNull(context.arg(ContextKeys.LOCATION));
|
||||||
|
int random = RandomUtils.generateRandomInt((int) min.evaluate(context), (int) max.evaluate(context));
|
||||||
|
Player player = null;
|
||||||
|
if (context.holder() instanceof Player p) {
|
||||||
|
player = p;
|
||||||
|
}
|
||||||
|
ItemStack drop = generateItem(location, player, random);
|
||||||
|
if (drop != null) {
|
||||||
|
if (toInv && player != null) {
|
||||||
|
PlayerUtils.giveItem(player, drop, 1);
|
||||||
|
} else {
|
||||||
|
location.getWorld().dropItemNaturally(location, drop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public ItemStack generateItem(Location location, @Nullable Player player, int randomAmount) {
|
||||||
|
double[] ratio = ConfigManager.defaultQualityRatio();
|
||||||
|
Optional<CustomCropsWorld<?>> world = plugin.getWorldManager().getWorld(location.getWorld());
|
||||||
|
if (world.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Pos3 pos3 = Pos3.from(location);
|
||||||
|
Fertilizer[] fertilizers = null;
|
||||||
|
Pos3 potLocation = pos3.add(0, -1, 0);
|
||||||
|
Optional<CustomCropsChunk> chunk = world.get().getChunk(potLocation.toChunkPos());
|
||||||
|
if (chunk.isPresent()) {
|
||||||
|
Optional<CustomCropsBlockState> state = chunk.get().getBlockState(potLocation);
|
||||||
|
if (state.isPresent()) {
|
||||||
|
if (state.get().type() instanceof PotBlock potBlock) {
|
||||||
|
fertilizers = potBlock.fertilizers(state.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ArrayList<FertilizerConfig> configs = new ArrayList<>();
|
||||||
|
if (fertilizers != null) {
|
||||||
|
for (Fertilizer fertilizer : fertilizers) {
|
||||||
|
Optional.ofNullable(fertilizer.config()).ifPresent(configs::add);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (FertilizerConfig config : configs) {
|
||||||
|
randomAmount = config.processDroppedItemAmount(randomAmount);
|
||||||
|
double[] newRatio = config.overrideQualityRatio();
|
||||||
|
if (newRatio != null) {
|
||||||
|
ratio = newRatio;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < randomAmount; i++) {
|
||||||
|
double r1 = Math.random();
|
||||||
|
for (int j = 0; j < ratio.length; j++) {
|
||||||
|
if (r1 < ratio[j]) {
|
||||||
|
ItemStack drop = plugin.getItemManager().build(player, qualityLoots[j]);
|
||||||
|
if (drop == null || drop.getType() == Material.AIR) return null;
|
||||||
|
return drop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MathValue<T> getMin() {
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MathValue<T> getMax() {
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isToInv() {
|
||||||
|
return toInv;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getQualityLoots() {
|
||||||
|
return qualityLoots;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* 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.action.builtin;
|
||||||
|
|
||||||
|
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.misc.placeholder.BukkitPlaceholderManager;
|
||||||
|
import net.momirealms.customcrops.common.util.ListUtils;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
|
public class ActionRandomCommand<T> extends AbstractBuiltInAction<T> {
|
||||||
|
final List<String> commands;
|
||||||
|
public ActionRandomCommand(
|
||||||
|
BukkitCustomCropsPlugin plugin,
|
||||||
|
Object args,
|
||||||
|
double chance
|
||||||
|
) {
|
||||||
|
super(plugin, chance);
|
||||||
|
this.commands = ListUtils.toList(args);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void trigger(Context<T> context) {
|
||||||
|
if (context.argOrDefault(ContextKeys.OFFLINE, false)) return;
|
||||||
|
if (Math.random() > chance) return;
|
||||||
|
OfflinePlayer owner = null;
|
||||||
|
if (context.holder() instanceof Player player) {
|
||||||
|
owner = player;
|
||||||
|
}
|
||||||
|
String random = commands.get(ThreadLocalRandom.current().nextInt(commands.size()));
|
||||||
|
random = BukkitPlaceholderManager.getInstance().parse(owner, random, context.placeholderMap());
|
||||||
|
String finalRandom = random;
|
||||||
|
plugin.getScheduler().sync().run(() -> {
|
||||||
|
Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), finalRandom);
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getCommands() {
|
||||||
|
return commands;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* 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.action.builtin;
|
||||||
|
|
||||||
|
import dev.dejvokep.boostedyaml.block.implementation.Section;
|
||||||
|
import net.momirealms.customcrops.api.BukkitCustomCropsPlugin;
|
||||||
|
import net.momirealms.customcrops.api.action.AbstractActionManager;
|
||||||
|
import net.momirealms.customcrops.api.action.Action;
|
||||||
|
import net.momirealms.customcrops.api.context.Context;
|
||||||
|
import net.momirealms.customcrops.api.context.ContextKeys;
|
||||||
|
import net.momirealms.customcrops.common.plugin.scheduler.SchedulerTask;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class ActionTimer<T> extends AbstractBuiltInAction<T> {
|
||||||
|
final List<Action<T>> actions;
|
||||||
|
final int delay, duration, period;
|
||||||
|
final boolean async;
|
||||||
|
public ActionTimer(
|
||||||
|
BukkitCustomCropsPlugin plugin,
|
||||||
|
AbstractActionManager<T> manager,
|
||||||
|
Object args,
|
||||||
|
double chance
|
||||||
|
) {
|
||||||
|
super(plugin, chance);
|
||||||
|
this.actions = new ArrayList<>();
|
||||||
|
if (args instanceof Section section) {
|
||||||
|
delay = section.getInt("delay", 2);
|
||||||
|
duration = section.getInt("duration", 20);
|
||||||
|
period = section.getInt("period", 2);
|
||||||
|
async = section.getBoolean("async", false);
|
||||||
|
Section actionSection = section.getSection("actions");
|
||||||
|
if (actionSection != null)
|
||||||
|
for (Map.Entry<String, Object> entry : actionSection.getStringRouteMappedValues(false).entrySet())
|
||||||
|
if (entry.getValue() instanceof Section innerSection)
|
||||||
|
actions.add(manager.parseAction(innerSection));
|
||||||
|
} else {
|
||||||
|
delay = 1;
|
||||||
|
period = 1;
|
||||||
|
async = false;
|
||||||
|
duration = 20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void trigger(Context<T> context) {
|
||||||
|
if (!checkChance()) return;
|
||||||
|
Location location = context.arg(ContextKeys.LOCATION);
|
||||||
|
SchedulerTask task;
|
||||||
|
if (async) {
|
||||||
|
task = plugin.getScheduler().asyncRepeating(() -> {
|
||||||
|
for (Action<T> action : actions) {
|
||||||
|
action.trigger(context);
|
||||||
|
}
|
||||||
|
}, delay * 50L, period * 50L, TimeUnit.MILLISECONDS);
|
||||||
|
} else {
|
||||||
|
task = plugin.getScheduler().sync().runRepeating(() -> {
|
||||||
|
for (Action<T> action : actions) {
|
||||||
|
action.trigger(context);
|
||||||
|
}
|
||||||
|
}, delay, period, location);
|
||||||
|
}
|
||||||
|
plugin.getScheduler().asyncLater(task::cancel, duration * 50L, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Action<T>> getActions() {
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDelay() {
|
||||||
|
return delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDuration() {
|
||||||
|
return duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPeriod() {
|
||||||
|
return period;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAsync() {
|
||||||
|
return async;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* 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.action.builtin;
|
||||||
|
|
||||||
|
import dev.dejvokep.boostedyaml.block.implementation.Section;
|
||||||
|
import net.kyori.adventure.audience.Audience;
|
||||||
|
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.misc.value.TextValue;
|
||||||
|
import net.momirealms.customcrops.api.util.LocationUtils;
|
||||||
|
import net.momirealms.customcrops.common.helper.AdventureHelper;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
|
public class ActionTitleNearby<T> extends AbstractBuiltInAction<T> {
|
||||||
|
final TextValue<T> title;
|
||||||
|
final TextValue<T> subtitle;
|
||||||
|
final int fadeIn;
|
||||||
|
final int stay;
|
||||||
|
final int fadeOut;
|
||||||
|
final int range;
|
||||||
|
public ActionTitleNearby(
|
||||||
|
BukkitCustomCropsPlugin plugin,
|
||||||
|
Section section,
|
||||||
|
double chance
|
||||||
|
) {
|
||||||
|
super(plugin, chance);
|
||||||
|
this.title = TextValue.auto(section.getString("title"));
|
||||||
|
this.subtitle = TextValue.auto(section.getString("subtitle"));
|
||||||
|
this.fadeIn = section.getInt("fade-in", 20);
|
||||||
|
this.stay = section.getInt("stay", 30);
|
||||||
|
this.fadeOut = section.getInt("fade-out", 10);
|
||||||
|
this.range = section.getInt("range", 0);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void trigger(Context<T> context) {
|
||||||
|
if (context.argOrDefault(ContextKeys.OFFLINE, false)) return;
|
||||||
|
if (Math.random() > chance) return;
|
||||||
|
Location location = requireNonNull(context.arg(ContextKeys.LOCATION));
|
||||||
|
for (Player player : location.getWorld().getPlayers()) {
|
||||||
|
if (LocationUtils.getDistance(player.getLocation(), location) <= range) {
|
||||||
|
context.arg(ContextKeys.TEMP_NEAR_PLAYER, player.getName());
|
||||||
|
Audience audience = plugin.getSenderFactory().getAudience(player);
|
||||||
|
AdventureHelper.sendTitle(audience,
|
||||||
|
AdventureHelper.miniMessage(title.render(context)),
|
||||||
|
AdventureHelper.miniMessage(subtitle.render(context)),
|
||||||
|
fadeIn, stay, fadeOut
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextValue<T> getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextValue<T> getSubtitle() {
|
||||||
|
return subtitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFadeIn() {
|
||||||
|
return fadeIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getStay() {
|
||||||
|
return stay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFadeOut() {
|
||||||
|
return fadeOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRange() {
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user