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;
|
||||
|
||||
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.context.Context;
|
||||
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.api.action.builtin.*;
|
||||
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.Nullable;
|
||||
|
||||
@@ -66,10 +28,6 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
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> {
|
||||
|
||||
@@ -194,55 +152,13 @@ public abstract class AbstractActionManager<T> implements ActionManager<T> {
|
||||
}
|
||||
|
||||
protected void registerBroadcastAction() {
|
||||
registerAction((args, chance) -> {
|
||||
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");
|
||||
registerAction((args, chance) -> new ActionBroadcast<>(plugin, args, chance), "broadcast");
|
||||
}
|
||||
|
||||
protected void registerNearbyMessage() {
|
||||
registerAction((args, chance) -> {
|
||||
if (args instanceof Section section) {
|
||||
List<String> messages = ListUtils.toList(section.get("message"));
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
return new ActionMessageNearby<>(plugin, section, chance);
|
||||
} else {
|
||||
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at message-nearby action which should be Section");
|
||||
return Action.empty();
|
||||
@@ -253,26 +169,7 @@ public abstract class AbstractActionManager<T> implements ActionManager<T> {
|
||||
protected void registerNearbyActionBar() {
|
||||
registerAction((args, chance) -> {
|
||||
if (args instanceof Section section) {
|
||||
String actionbar = section.getString("actionbar");
|
||||
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));
|
||||
}
|
||||
}
|
||||
};
|
||||
return new ActionActionbarNearby<>(plugin, section, chance);
|
||||
} else {
|
||||
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at actionbar-nearby action which should be Section");
|
||||
return Action.empty();
|
||||
@@ -281,63 +178,11 @@ public abstract class AbstractActionManager<T> implements ActionManager<T> {
|
||||
}
|
||||
|
||||
protected void registerCommandAction() {
|
||||
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;
|
||||
}
|
||||
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) -> new ActionCommand<>(plugin, args, chance), "command");
|
||||
registerAction((args, chance) -> new ActionRandomCommand<>(plugin, args, chance), "random-command");
|
||||
registerAction((args, chance) -> {
|
||||
if (args instanceof Section section) {
|
||||
List<String> cmd = ListUtils.toList(section.get("command"));
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
return new ActionCommandNearby<>(plugin, section, chance);
|
||||
} else {
|
||||
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at command-nearby action which should be Section");
|
||||
return Action.empty();
|
||||
@@ -346,109 +191,12 @@ public abstract class AbstractActionManager<T> implements ActionManager<T> {
|
||||
}
|
||||
|
||||
protected void registerBundleAction(Class<T> tClass) {
|
||||
registerAction((args, chance) -> {
|
||||
List<Action<T>> 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(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) -> new ActionBundle<>(plugin, this, args, chance), "chain");
|
||||
registerAction((args, chance) -> new ActionDelay<>(plugin, this, args, chance), "delay");
|
||||
registerAction((args, chance) -> new ActionTimer<>(plugin, this, args, chance), "timer");
|
||||
registerAction((args, chance) -> {
|
||||
if (args instanceof Section section) {
|
||||
Action<T>[] actions = parseActions(section.getSection("actions"));
|
||||
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);
|
||||
}
|
||||
};
|
||||
return new ActionConditional<>(plugin, this, tClass, section, chance);
|
||||
} else {
|
||||
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at conditional action which is expected to be `Section`");
|
||||
return Action.empty();
|
||||
@@ -456,31 +204,7 @@ public abstract class AbstractActionManager<T> implements ActionManager<T> {
|
||||
}, "conditional");
|
||||
registerAction((args, chance) -> {
|
||||
if (args instanceof Section section) {
|
||||
List<Pair<Requirement<T>[], Action<T>[]>> conditionActionPairList = new ArrayList<>();
|
||||
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;
|
||||
}
|
||||
};
|
||||
return new ActionPriority<>(plugin, this, tClass, section, chance);
|
||||
} else {
|
||||
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at priority action which is expected to be `Section`");
|
||||
return Action.empty();
|
||||
@@ -491,28 +215,7 @@ public abstract class AbstractActionManager<T> implements ActionManager<T> {
|
||||
protected void registerNearbyTitle() {
|
||||
registerAction((args, chance) -> {
|
||||
if (args instanceof Section section) {
|
||||
TextValue<T> title = TextValue.auto(section.getString("title"));
|
||||
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
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
return new ActionTitleNearby<>(plugin, section, chance);
|
||||
} else {
|
||||
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at title-nearby action which is expected to be `Section`");
|
||||
return Action.empty();
|
||||
@@ -523,54 +226,7 @@ public abstract class AbstractActionManager<T> implements ActionManager<T> {
|
||||
protected void registerParticleAction() {
|
||||
registerAction((args, chance) -> {
|
||||
if (args instanceof Section section) {
|
||||
Particle particleType = ParticleUtils.getParticle(section.getString("particle", "ASH").toUpperCase(Locale.ENGLISH));
|
||||
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))
|
||||
);
|
||||
};
|
||||
return new ActionParticle<>(plugin, section, chance);
|
||||
} else {
|
||||
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at particle action which is expected to be `Section`");
|
||||
return Action.empty();
|
||||
@@ -581,71 +237,7 @@ public abstract class AbstractActionManager<T> implements ActionManager<T> {
|
||||
protected void registerQualityCropsAction() {
|
||||
registerAction((args, chance) -> {
|
||||
if (args instanceof Section section) {
|
||||
MathValue<T> min = MathValue.auto(section.get("min"));
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
return new ActionQualityCrops<>(plugin, section, chance);
|
||||
} else {
|
||||
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at quality-crops action which is expected to be `Section`");
|
||||
return Action.empty();
|
||||
@@ -656,58 +248,7 @@ public abstract class AbstractActionManager<T> implements ActionManager<T> {
|
||||
protected void registerDropItemsAction() {
|
||||
registerAction((args, chance) -> {
|
||||
if (args instanceof Section section) {
|
||||
boolean ignoreFertilizer = section.getBoolean("ignore-fertilizer", true);
|
||||
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");
|
||||
}
|
||||
};
|
||||
return new ActionDropItem<>(plugin, section, chance);
|
||||
} else {
|
||||
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at drop-item action which is expected to be `Section`");
|
||||
return Action.empty();
|
||||
@@ -718,25 +259,7 @@ public abstract class AbstractActionManager<T> implements ActionManager<T> {
|
||||
protected void registerLegacyDropItemsAction() {
|
||||
registerAction((args, chance) -> {
|
||||
if (args instanceof Section section) {
|
||||
List<Action<T>> 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(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);
|
||||
}
|
||||
};
|
||||
return new ActionDropItemLegacy<>(plugin, this, section, chance);
|
||||
} else {
|
||||
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at drop-items action which is expected to be `Section`");
|
||||
return Action.empty();
|
||||
@@ -747,51 +270,7 @@ public abstract class AbstractActionManager<T> implements ActionManager<T> {
|
||||
protected void registerHologramAction() {
|
||||
registerAction(((args, chance) -> {
|
||||
if (args instanceof Section section) {
|
||||
TextValue<T> text = TextValue.auto(section.getString("text", ""));
|
||||
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));
|
||||
}
|
||||
};
|
||||
return new ActionHologram<>(plugin, section, chance);
|
||||
} else {
|
||||
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at hologram action which is expected to be `Section`");
|
||||
return Action.empty();
|
||||
@@ -802,66 +281,7 @@ public abstract class AbstractActionManager<T> implements ActionManager<T> {
|
||||
protected void registerFakeItemAction() {
|
||||
registerAction(((args, chance) -> {
|
||||
if (args instanceof Section section) {
|
||||
String itemID = section.getString("item", "");
|
||||
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);
|
||||
};
|
||||
return new ActionFakeItem<>(plugin, section, chance);
|
||||
} else {
|
||||
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at fake-item action which is expected to be `Section`");
|
||||
return Action.empty();
|
||||
@@ -869,62 +289,10 @@ public abstract class AbstractActionManager<T> implements ActionManager<T> {
|
||||
}), "fake-item");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void registerPlantAction() {
|
||||
this.registerAction((args, chance) -> {
|
||||
if (args instanceof Section section) {
|
||||
int point = section.getInt("point", 0);
|
||||
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);
|
||||
};
|
||||
return new ActionPlant<>(plugin, section, chance);
|
||||
} else {
|
||||
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at plant action which is expected to be `Section`");
|
||||
return Action.empty();
|
||||
@@ -933,49 +301,6 @@ public abstract class AbstractActionManager<T> implements ActionManager<T> {
|
||||
}
|
||||
|
||||
protected void registerBreakAction() {
|
||||
this.registerAction((args, chance) -> {
|
||||
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");
|
||||
this.registerAction((args, chance) -> new ActionBreak<>(plugin, args, chance), "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