mirror of
https://github.com/Xiao-MoMi/Custom-Fishing.git
synced 2025-12-19 15:09:24 +00:00
checkpoint - 10
This commit is contained in:
@@ -35,10 +35,12 @@ import net.momirealms.customfishing.api.mechanic.misc.placeholder.PlaceholderMan
|
||||
import net.momirealms.customfishing.api.mechanic.requirement.RequirementManager;
|
||||
import net.momirealms.customfishing.api.mechanic.statistic.StatisticsManager;
|
||||
import net.momirealms.customfishing.api.storage.StorageManager;
|
||||
import net.momirealms.customfishing.common.dependency.DependencyManager;
|
||||
import net.momirealms.customfishing.common.locale.TranslationManager;
|
||||
import net.momirealms.customfishing.common.plugin.CustomFishingPlugin;
|
||||
import net.momirealms.customfishing.common.plugin.feature.Reloadable;
|
||||
import net.momirealms.customfishing.common.plugin.scheduler.AbstractJavaScheduler;
|
||||
import net.momirealms.customfishing.common.sender.SenderFactory;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -46,12 +48,10 @@ import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public abstract class BukkitCustomFishingPlugin implements CustomFishingPlugin {
|
||||
public abstract class BukkitCustomFishingPlugin implements CustomFishingPlugin, Reloadable {
|
||||
|
||||
private static BukkitCustomFishingPlugin instance;
|
||||
private final Plugin boostrap = requireNonNull(Bukkit.getPluginManager().getPlugin("CustomFishing"));
|
||||
private final Plugin boostrap;
|
||||
|
||||
protected EventManager eventManager;
|
||||
protected ConfigManager configManager;
|
||||
@@ -73,13 +73,20 @@ public abstract class BukkitCustomFishingPlugin implements CustomFishingPlugin {
|
||||
protected EffectManager effectManager;
|
||||
protected HookManager hookManager;
|
||||
protected BagManager bagManager;
|
||||
protected DependencyManager dependencyManager;
|
||||
protected TranslationManager translationManager;
|
||||
protected boolean initialized = false;
|
||||
|
||||
public BukkitCustomFishingPlugin() {
|
||||
public BukkitCustomFishingPlugin(Plugin boostrap) {
|
||||
if (!boostrap.getName().equals("CustomFishing")) {
|
||||
throw new IllegalArgumentException("CustomFishing plugin requires custom fishing plugin");
|
||||
}
|
||||
this.boostrap = boostrap;
|
||||
instance = this;
|
||||
}
|
||||
|
||||
public static BukkitCustomFishingPlugin getInstance() {
|
||||
if (instance == null) {
|
||||
if (instance == null || !instance.initialized) {
|
||||
throw new IllegalArgumentException("Plugin not initialized");
|
||||
}
|
||||
return instance;
|
||||
@@ -175,7 +182,15 @@ public abstract class BukkitCustomFishingPlugin implements CustomFishingPlugin {
|
||||
return boostrap;
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
@Override
|
||||
public DependencyManager getDependencyManager() {
|
||||
return dependencyManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TranslationManager getTranslationManager() {
|
||||
return translationManager;
|
||||
}
|
||||
|
||||
public abstract void enable();
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
|
||||
package net.momirealms.customfishing.api.event;
|
||||
|
||||
import net.momirealms.customfishing.api.mechanic.condition.FishingPreparation;
|
||||
import net.momirealms.customfishing.api.mechanic.effect.Effect;
|
||||
import net.momirealms.customfishing.api.mechanic.fishing.FishingPreparation;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.player.PlayerEvent;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
package net.momirealms.customfishing.api.integration;
|
||||
|
||||
import net.momirealms.customfishing.common.plugin.feature.Reloadable;
|
||||
import net.momirealms.customfishing.common.util.Pair;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -29,7 +30,7 @@ import java.util.List;
|
||||
* This allows for the registration and retrieval of various types of providers
|
||||
* such as Leveler, Enchantment, and Season providers.
|
||||
*/
|
||||
public interface IntegrationManager {
|
||||
public interface IntegrationManager extends Reloadable {
|
||||
|
||||
/**
|
||||
* Registers a LevelerProvider.
|
||||
|
||||
@@ -19,6 +19,7 @@ package net.momirealms.customfishing.api.mechanic.action;
|
||||
|
||||
import dev.dejvokep.boostedyaml.block.implementation.Section;
|
||||
import net.momirealms.customfishing.api.mechanic.context.Context;
|
||||
import net.momirealms.customfishing.common.plugin.feature.Reloadable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -29,7 +30,7 @@ import java.util.*;
|
||||
*
|
||||
* @param <T> the type of the context in which the actions are triggered.
|
||||
*/
|
||||
public interface ActionManager<T> {
|
||||
public interface ActionManager<T> extends Reloadable {
|
||||
|
||||
/**
|
||||
* Registers a custom action type with its corresponding factory.
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
package net.momirealms.customfishing.api.mechanic.competition;
|
||||
|
||||
import net.kyori.adventure.util.Index;
|
||||
import net.momirealms.customfishing.common.locale.StandardLocales;
|
||||
import net.momirealms.customfishing.common.util.RandomUtils;
|
||||
import org.apache.logging.log4j.util.Supplier;
|
||||
import org.apache.logging.log4j.util.TriConsumer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@@ -26,11 +28,13 @@ public final class CompetitionGoal {
|
||||
|
||||
public static final CompetitionGoal CATCH_AMOUNT = new CompetitionGoal(
|
||||
"catch_amount",
|
||||
((rankingProvider, player, score) -> rankingProvider.refreshData(player, 1))
|
||||
((rankingProvider, player, score) -> rankingProvider.refreshData(player, 1)),
|
||||
() -> StandardLocales.GOAL_CATCH_AMOUNT
|
||||
);
|
||||
public static final CompetitionGoal TOTAL_SCORE = new CompetitionGoal(
|
||||
"total_score",
|
||||
(RankingProvider::refreshData)
|
||||
(RankingProvider::refreshData),
|
||||
() -> StandardLocales.GOAL_TOTAL_SCORE
|
||||
);
|
||||
public static final CompetitionGoal MAX_SIZE = new CompetitionGoal(
|
||||
"max_size",
|
||||
@@ -38,15 +42,18 @@ public final class CompetitionGoal {
|
||||
if (rankingProvider.getPlayerScore(player) < score) {
|
||||
rankingProvider.setData(player, score);
|
||||
}
|
||||
})
|
||||
}),
|
||||
() -> StandardLocales.GOAL_MAX_SIZE
|
||||
);
|
||||
public static final CompetitionGoal TOTAL_SIZE = new CompetitionGoal(
|
||||
"total_size",
|
||||
(RankingProvider::refreshData)
|
||||
(RankingProvider::refreshData),
|
||||
() -> StandardLocales.GOAL_TOTAL_SIZE
|
||||
);
|
||||
public static final CompetitionGoal RANDOM = new CompetitionGoal(
|
||||
"random",
|
||||
(rankingProvider, player, score) -> {}
|
||||
(rankingProvider, player, score) -> {},
|
||||
() -> "random"
|
||||
);
|
||||
|
||||
private static final CompetitionGoal[] values = new CompetitionGoal[] {
|
||||
@@ -84,10 +91,12 @@ public final class CompetitionGoal {
|
||||
|
||||
private final String key;
|
||||
private final TriConsumer<RankingProvider, String, Double> scoreConsumer;
|
||||
private final Supplier<String> nameSupplier;
|
||||
|
||||
private CompetitionGoal(String key, TriConsumer<RankingProvider, String, Double> scoreConsumer) {
|
||||
private CompetitionGoal(String key, TriConsumer<RankingProvider, String, Double> scoreConsumer, Supplier<String> nameSupplier) {
|
||||
this.key = key;
|
||||
this.scoreConsumer = scoreConsumer;
|
||||
this.nameSupplier = nameSupplier;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -105,6 +114,6 @@ public final class CompetitionGoal {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString();
|
||||
return nameSupplier.get();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,9 +17,10 @@
|
||||
|
||||
package net.momirealms.customfishing.api.mechanic.competition;
|
||||
|
||||
import net.momirealms.customfishing.common.plugin.feature.Reloadable;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface CompetitionManager {
|
||||
public interface CompetitionManager extends Reloadable {
|
||||
|
||||
boolean startCompetition(String competition, boolean force, @Nullable String serverGroup);
|
||||
|
||||
|
||||
@@ -89,6 +89,15 @@ public abstract class ConfigManager implements ConfigLoader, Reloadable {
|
||||
}
|
||||
|
||||
public static String bagTitle() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean metrics() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean checkUpdate() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void registerLootParser(Function<Object, Consumer<Loot.Builder>> function, String... nodes) {
|
||||
|
||||
@@ -42,14 +42,14 @@ public interface EntityConfig {
|
||||
*
|
||||
* @return the horizontal vector value as a double
|
||||
*/
|
||||
MathValue<Player> getHorizontalVector();
|
||||
MathValue<Player> horizontalVector();
|
||||
|
||||
/**
|
||||
* Retrieves the vertical vector value for the entity.
|
||||
*
|
||||
* @return the vertical vector value as a double
|
||||
*/
|
||||
MathValue<Player> getVerticalVector();
|
||||
MathValue<Player> verticalVector();
|
||||
|
||||
/**
|
||||
* Retrieves the unique identifier for the entity.
|
||||
@@ -57,7 +57,7 @@ public interface EntityConfig {
|
||||
* @return the entity ID as a non-null String
|
||||
*/
|
||||
@NotNull
|
||||
String getEntityID();
|
||||
String entityID();
|
||||
|
||||
/**
|
||||
* Retrieves a map of properties associated with the entity.
|
||||
@@ -65,7 +65,7 @@ public interface EntityConfig {
|
||||
* @return a non-null map where keys are property names and values are property values
|
||||
*/
|
||||
@NotNull
|
||||
Map<String, Object> getPropertyMap();
|
||||
Map<String, Object> propertyMap();
|
||||
|
||||
/**
|
||||
* Creates a new Builder instance for constructing an EntityConfig.
|
||||
|
||||
@@ -45,24 +45,24 @@ public class EntityConfigImpl implements EntityConfig {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MathValue<Player> getHorizontalVector() {
|
||||
public MathValue<Player> horizontalVector() {
|
||||
return horizontalVector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MathValue<Player> getVerticalVector() {
|
||||
public MathValue<Player> verticalVector() {
|
||||
return verticalVector;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getEntityID() {
|
||||
public String entityID() {
|
||||
return entityID;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Map<String, Object> getPropertyMap() {
|
||||
public Map<String, Object> propertyMap() {
|
||||
return propertyMap;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
package net.momirealms.customfishing.api.mechanic.fishing;
|
||||
|
||||
public class FishingPreparation {
|
||||
}
|
||||
@@ -30,7 +30,7 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
public abstract class AbstractGamingPlayer implements GamingPlayer, Runnable {
|
||||
|
||||
private final FishingManager manager;
|
||||
// private final FishingManager manager;
|
||||
protected long deadline;
|
||||
protected boolean success;
|
||||
protected SchedulerTask task;
|
||||
@@ -43,7 +43,7 @@ public abstract class AbstractGamingPlayer implements GamingPlayer, Runnable {
|
||||
this.player = player;
|
||||
this.fishHook = hook;
|
||||
this.settings = settings;
|
||||
this.manager = BukkitCustomFishingPlugin.getFishingManager();
|
||||
// this.manager = BukkitCustomFishingPlugin.getInstance().get();
|
||||
this.deadline = (long) (System.currentTimeMillis() + settings.time() * 1000L);
|
||||
this.arrangeTask();
|
||||
}
|
||||
@@ -119,7 +119,7 @@ public abstract class AbstractGamingPlayer implements GamingPlayer, Runnable {
|
||||
}
|
||||
|
||||
protected void endGame() {
|
||||
this.manager.processGameResult(this);
|
||||
// this.manager.processGameResult(this);
|
||||
}
|
||||
|
||||
protected void setGameResult(boolean success) {
|
||||
|
||||
@@ -17,11 +17,12 @@
|
||||
|
||||
package net.momirealms.customfishing.api.mechanic.hook;
|
||||
|
||||
import net.momirealms.customfishing.common.plugin.feature.Reloadable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface HookManager {
|
||||
public interface HookManager extends Reloadable {
|
||||
|
||||
boolean registerHook(HookConfig hook);
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ package net.momirealms.customfishing.api.mechanic.loot;
|
||||
|
||||
import net.momirealms.customfishing.api.mechanic.context.Context;
|
||||
import net.momirealms.customfishing.api.mechanic.effect.Effect;
|
||||
import net.momirealms.customfishing.common.plugin.feature.Reloadable;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -27,7 +28,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface LootManager {
|
||||
public interface LootManager extends Reloadable {
|
||||
|
||||
void registerLoot(@NotNull Loot loot);
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
package net.momirealms.customfishing.api.mechanic.misc.cooldown;
|
||||
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import net.momirealms.customfishing.common.plugin.feature.Reloadable;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.HandlerList;
|
||||
@@ -34,7 +35,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
* Manages cooldowns for various actions or events.
|
||||
* Keeps track of cooldown times for different keys associated with player UUIDs.
|
||||
*/
|
||||
public class CoolDownManager implements Listener {
|
||||
public class CoolDownManager implements Listener, Reloadable {
|
||||
|
||||
private final ConcurrentHashMap<UUID, Data> dataMap;
|
||||
private final BukkitCustomFishingPlugin plugin;
|
||||
@@ -57,14 +58,17 @@ public class CoolDownManager implements Listener {
|
||||
return data.isCoolDown(key, time);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin.getBoostrap());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unload() {
|
||||
HandlerList.unregisterAll(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
unload();
|
||||
this.dataMap.clear();
|
||||
|
||||
@@ -32,17 +32,21 @@ import java.util.stream.Collectors;
|
||||
public class BukkitPlaceholderManager implements PlaceholderManager {
|
||||
|
||||
private final BukkitCustomFishingPlugin plugin;
|
||||
private final boolean hasPapi;
|
||||
private boolean hasPapi;
|
||||
private final HashMap<String, String> customPlaceholderMap;
|
||||
private static BukkitPlaceholderManager instance;
|
||||
|
||||
public BukkitPlaceholderManager(BukkitCustomFishingPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.hasPapi = Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI");
|
||||
this.customPlaceholderMap = new HashMap<>();
|
||||
instance = this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
this.hasPapi = Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI");
|
||||
}
|
||||
|
||||
public static BukkitPlaceholderManager getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
package net.momirealms.customfishing.api.mechanic.misc.placeholder;
|
||||
|
||||
import net.momirealms.customfishing.common.plugin.feature.Reloadable;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -24,7 +25,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public interface PlaceholderManager {
|
||||
public interface PlaceholderManager extends Reloadable {
|
||||
|
||||
Pattern PATTERN = Pattern.compile("\\{[^{}]+}");
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ package net.momirealms.customfishing.api.mechanic.requirement;
|
||||
|
||||
import dev.dejvokep.boostedyaml.block.implementation.Section;
|
||||
import net.momirealms.customfishing.api.mechanic.context.Context;
|
||||
import net.momirealms.customfishing.common.plugin.feature.Reloadable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -29,7 +30,7 @@ import java.util.List;
|
||||
*
|
||||
* @param <T> the type of the context in which the requirements are evaluated.
|
||||
*/
|
||||
public interface RequirementManager<T> {
|
||||
public interface RequirementManager<T> extends Reloadable {
|
||||
|
||||
/**
|
||||
* Registers a custom requirement type with its corresponding factory.
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package net.momirealms.customfishing.api.mechanic.totem;
|
||||
|
||||
import net.momirealms.customfishing.api.mechanic.requirement.Requirement;
|
||||
import net.momirealms.customfishing.api.mechanic.totem.block.TotemBlock;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public interface TotemConfig
|
||||
{
|
||||
TotemModel[] totemModels();
|
||||
|
||||
Requirement<Player>[] activateRequirements();
|
||||
|
||||
String id();
|
||||
|
||||
boolean isRightPattern(Location location);
|
||||
|
||||
TotemParticle[] particleSettings();
|
||||
|
||||
double radius();
|
||||
|
||||
int duration();
|
||||
|
||||
TotemBlock[] totemCore();
|
||||
|
||||
static Builder builder() {
|
||||
return new TotemConfigImpl.BuilderImpl();
|
||||
}
|
||||
|
||||
interface Builder {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customfishing.api.mechanic.totem;
|
||||
|
||||
import net.momirealms.customfishing.api.mechanic.requirement.Requirement;
|
||||
import net.momirealms.customfishing.api.mechanic.totem.block.TotemBlock;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public class TotemConfigImpl implements TotemConfig {
|
||||
|
||||
private String id;
|
||||
private TotemModel[] totemModels;
|
||||
private TotemParticle[] particleSettings;
|
||||
private Requirement<Player>[] activateRequirements;
|
||||
private double radius;
|
||||
private int duration;
|
||||
|
||||
public TotemConfigImpl(String id, TotemModel[] totemModels, TotemParticle[] particleSettings, Requirement<Player>[] activateRequirements, double radius, int duration) {
|
||||
this.id = id;
|
||||
this.totemModels = totemModels;
|
||||
this.particleSettings = particleSettings;
|
||||
this.activateRequirements = activateRequirements;
|
||||
this.radius = radius;
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TotemModel[] totemModels() {
|
||||
return totemModels;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Requirement<Player>[] activateRequirements() {
|
||||
return activateRequirements;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRightPattern(Location location) {
|
||||
for (TotemModel totemModel : totemModels) {
|
||||
if (totemModel.isPatternSatisfied(location)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TotemParticle[] particleSettings() {
|
||||
return particleSettings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double radius() {
|
||||
return radius;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int duration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TotemBlock[] totemCore() {
|
||||
return totemModels[0].getTotemCore();
|
||||
}
|
||||
|
||||
public static class BuilderImpl implements Builder {
|
||||
private String id;
|
||||
private TotemModel[] totemModels;
|
||||
private TotemParticle[] particleSettings;
|
||||
private Requirement<Player>[] activateRequirements;
|
||||
private double radius;
|
||||
private int duration;
|
||||
public Builder id(String id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
public Builder totemModels(TotemModel[] totemModels) {
|
||||
this.totemModels = totemModels;
|
||||
return this;
|
||||
}
|
||||
public Builder particleSettings(TotemParticle[] particleSettings) {
|
||||
this.particleSettings = particleSettings;
|
||||
return this;
|
||||
}
|
||||
public Builder radius(double radius) {
|
||||
this.radius = radius;
|
||||
return this;
|
||||
}
|
||||
public Builder duration(int duration) {
|
||||
this.duration = duration;
|
||||
return this;
|
||||
}
|
||||
public Builder activateRequirements(Requirement<Player>[] activateRequirements) {
|
||||
this.activateRequirements = activateRequirements;
|
||||
return this;
|
||||
}
|
||||
public TotemConfig build() {
|
||||
return new TotemConfigImpl(requireNonNull(id), requireNonNull(totemModels), particleSettings, activateRequirements, radius, duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package net.momirealms.customfishing.api.mechanic.totem;
|
||||
|
||||
import net.momirealms.customfishing.common.plugin.feature.Reloadable;
|
||||
|
||||
public interface TotemManager extends Reloadable {
|
||||
}
|
||||
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customfishing.api.mechanic.totem;
|
||||
|
||||
import net.momirealms.customfishing.api.mechanic.totem.block.TotemBlock;
|
||||
import org.apache.commons.lang3.SerializationUtils;
|
||||
import org.bukkit.Axis;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/**
|
||||
* This class represents a totem model used to define the pattern of a totem.
|
||||
*/
|
||||
public class TotemModel implements Serializable {
|
||||
|
||||
private int coreX;
|
||||
private final int coreY;
|
||||
private int coreZ;
|
||||
// [Y][Z][X][alternative totem blocks]
|
||||
private TotemBlock[][][][] model;
|
||||
|
||||
/**
|
||||
* Constructs a TotemModel with the specified parameters.
|
||||
*
|
||||
* @param coreX X-coordinate of the totem's core within the model.
|
||||
* @param coreY Y-coordinate of the totem's core within the model.
|
||||
* @param coreZ Z-coordinate of the totem's core within the model.
|
||||
* @param model 3D array representing the totem model's structure.
|
||||
*/
|
||||
public TotemModel(int coreX, int coreY, int coreZ, TotemBlock[][][][] model) {
|
||||
this.coreX = coreX;
|
||||
this.coreY = coreY;
|
||||
this.coreZ = coreZ;
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the totem core as an array of TotemBlock objects.
|
||||
*
|
||||
* @return An array of TotemBlock objects representing the totem's core.
|
||||
*/
|
||||
public TotemBlock[] getTotemCore() {
|
||||
return model[coreY][coreZ][coreX];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the X-coordinate of the totem's core within the model.
|
||||
*
|
||||
* @return The X-coordinate as an integer.
|
||||
*/
|
||||
public int getCoreX() {
|
||||
return coreX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Y-coordinate of the totem's core within the model.
|
||||
*
|
||||
* @return The Y-coordinate as an integer.
|
||||
*/
|
||||
public int getCoreY() {
|
||||
return coreY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Z-coordinate of the totem's core within the model.
|
||||
*
|
||||
* @return The Z-coordinate as an integer.
|
||||
*/
|
||||
public int getCoreZ() {
|
||||
return coreZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the 3D array representing the totem model's structure.
|
||||
*
|
||||
* @return The 3D array of TotemBlock objects.
|
||||
*/
|
||||
public TotemBlock[][][][] getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for (int h = 0; h < model.length; h++) {
|
||||
stringBuilder.append("layer: ").append(h + 1).append("\n");
|
||||
TotemBlock[][][] totemBlocks1 = model[h];
|
||||
for (TotemBlock[][] totemBlocks2 : totemBlocks1) {
|
||||
for (TotemBlock[] totemBlocks3 : totemBlocks2) {
|
||||
StringJoiner stringJoiner = new StringJoiner("||");
|
||||
for (TotemBlock totemBlock : totemBlocks3) {
|
||||
stringJoiner.add(totemBlock.toString());
|
||||
}
|
||||
stringBuilder.append(stringJoiner).append("\t");
|
||||
}
|
||||
stringBuilder.append("\n");
|
||||
}
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
public TotemModel deepClone() {
|
||||
return SerializationUtils.clone(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate the totem model 90 degrees clockwise.
|
||||
*
|
||||
* @return The rotated TotemModel.
|
||||
*/
|
||||
public TotemModel rotate90() {
|
||||
int tempX = this.coreX;
|
||||
this.coreX = this.coreZ;
|
||||
this.coreZ = this.model[0][0].length - 1 - tempX;
|
||||
this.model = rotate90(model);
|
||||
for (TotemBlock[][][] totemBlocks1 : model) {
|
||||
for (TotemBlock[][] totemBlocks2 : totemBlocks1) {
|
||||
for (TotemBlock[] totemBlocks3 : totemBlocks2) {
|
||||
for (TotemBlock totemBlock : totemBlocks3) {
|
||||
totemBlock.rotate90();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mirror the totem model horizontally.
|
||||
*
|
||||
* @return The mirrored TotemModel.
|
||||
*/
|
||||
public TotemModel mirrorHorizontally() {
|
||||
mirrorHorizontally(model);
|
||||
this.coreZ = model[0].length - this.coreZ - 1;
|
||||
for (TotemBlock[][][] totemBlocks1 : model) {
|
||||
for (TotemBlock[][] totemBlocks2 : totemBlocks1) {
|
||||
for (TotemBlock[] totemBlocks3 : totemBlocks2) {
|
||||
for (TotemBlock totemBlock : totemBlocks3) {
|
||||
totemBlock.mirror(Axis.X);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mirror the totem model vertically.
|
||||
*
|
||||
* @return The mirrored TotemModel.
|
||||
*/
|
||||
public TotemModel mirrorVertically() {
|
||||
mirrorVertically(model);
|
||||
this.coreX = model[0][0].length - this.coreX - 1;
|
||||
|
||||
for (TotemBlock[][][] totemBlocks1 : model) {
|
||||
for (TotemBlock[][] totemBlocks2 : totemBlocks1) {
|
||||
for (TotemBlock[] totemBlocks3 : totemBlocks2) {
|
||||
for (TotemBlock totemBlock : totemBlocks3) {
|
||||
totemBlock.mirror(Axis.Z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the provided location satisfies the pattern defined by the totem model.
|
||||
*
|
||||
* @param location The location to check.
|
||||
* @return True if the location satisfies the pattern, false otherwise.
|
||||
*/
|
||||
public boolean isPatternSatisfied(Location location) {
|
||||
Location startLoc = location.clone().subtract(0, coreY, 0);
|
||||
|
||||
int height = model.length;
|
||||
int width = model[0].length;
|
||||
int length = model[0][0].length;
|
||||
|
||||
for (int y = 0; y < height; y++) {
|
||||
Location loc = startLoc.clone().add(-coreX, y, -coreZ);
|
||||
for (int z = 0; z < width; z++) {
|
||||
outer:
|
||||
for (int x = 0; x < length; x++) {
|
||||
for (TotemBlock totemBlock : model[y][z][x]) {
|
||||
if (totemBlock.isRightBlock(loc.clone().add(x, 0, z).getBlock())) {
|
||||
continue outer;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate a 3D totem model 90 degrees clockwise.
|
||||
*
|
||||
* @param matrix The 3D totem model to rotate.
|
||||
* @return The rotated 3D totem model.
|
||||
*/
|
||||
private static TotemBlock[][][][] rotate90(TotemBlock[][][][] matrix) {
|
||||
int height = matrix.length;
|
||||
int rows = matrix[0].length;
|
||||
int cols = matrix[0][0].length;
|
||||
TotemBlock[][][][] rotated = new TotemBlock[height][cols][rows][];
|
||||
for (int h = 0; h < height; h++) {
|
||||
for (int r = 0; r < rows; r++) {
|
||||
for (int c = 0; c < cols; c++) {
|
||||
rotated[h][c][rows - 1 - r] = matrix[h][r][c];
|
||||
}
|
||||
}
|
||||
}
|
||||
return rotated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mirror a 3D totem model horizontally.
|
||||
*
|
||||
* @param matrix The 3D totem model to mirror.
|
||||
*/
|
||||
private static void mirrorHorizontally(TotemBlock[][][][] matrix) {
|
||||
int height = matrix.length;
|
||||
int rows = matrix[0].length;
|
||||
int cols = matrix[0][0].length;
|
||||
|
||||
for (int h = 0; h < height; h++) {
|
||||
for (int i = 0; i < rows / 2; i++) {
|
||||
for (int j = 0; j < cols; j++) {
|
||||
TotemBlock[] temp = matrix[h][i][j];
|
||||
matrix[h][i][j] = matrix[h][rows - i - 1][j];
|
||||
matrix[h][rows - i - 1][j] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mirror a 3D totem model vertically.
|
||||
*
|
||||
* @param matrix The 3D totem model to mirror.
|
||||
*/
|
||||
private static void mirrorVertically(TotemBlock[][][][] matrix) {
|
||||
int height = matrix.length;
|
||||
int rows = matrix[0].length;
|
||||
int cols = matrix[0][0].length;
|
||||
for (int h = 0; h < height; h++) {
|
||||
for (int i = 0; i < rows; i++) {
|
||||
for (int j = 0; j < cols / 2; j++) {
|
||||
TotemBlock[] temp = matrix[h][i][j];
|
||||
matrix[h][i][j] = matrix[h][i][cols - j - 1];
|
||||
matrix[h][i][cols - j - 1] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package net.momirealms.customfishing.api.mechanic.totem;
|
||||
|
||||
import net.momirealms.customfishing.common.plugin.scheduler.SchedulerTask;
|
||||
import org.bukkit.Location;
|
||||
|
||||
public interface TotemParticle {
|
||||
|
||||
/**
|
||||
* Start the particle task at specified location
|
||||
*
|
||||
* @param location location
|
||||
* @param radius totem radius
|
||||
* @return cancellable task
|
||||
*/
|
||||
SchedulerTask start(Location location, double radius);
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customfishing.api.mechanic.totem.block;
|
||||
|
||||
import net.momirealms.customfishing.api.mechanic.totem.block.property.TotemBlockProperty;
|
||||
import net.momirealms.customfishing.api.mechanic.totem.block.type.TypeCondition;
|
||||
import org.bukkit.Axis;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/**
|
||||
* Represents a TotemBlock that defines conditions and properties for a specific block type in a totem structure.
|
||||
*/
|
||||
public class TotemBlock implements Serializable {
|
||||
|
||||
private final TypeCondition typeCondition;
|
||||
private final TotemBlockProperty[] properties;
|
||||
|
||||
/**
|
||||
* Initializes a TotemBlock with the specified TypeCondition and properties.
|
||||
*
|
||||
* @param typeCondition The TypeCondition that specifies the block type.
|
||||
* @param properties An array of TotemBlockProperty objects representing additional block properties.
|
||||
*/
|
||||
public TotemBlock(TypeCondition typeCondition, TotemBlockProperty[] properties) {
|
||||
this.typeCondition = typeCondition;
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the TypeCondition associated with this TotemBlock.
|
||||
*
|
||||
* @return The TypeCondition defining the block type.
|
||||
*/
|
||||
public TypeCondition getTypeCondition() {
|
||||
return typeCondition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array of properties associated with this TotemBlock.
|
||||
*
|
||||
* @return An array of TotemBlockProperty objects representing block properties.
|
||||
*/
|
||||
public TotemBlockProperty[] getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given Block satisfies the TypeCondition and properties of this TotemBlock.
|
||||
*
|
||||
* @param block The Block to be checked against the conditions and properties.
|
||||
* @return `true` if the block satisfies all conditions and properties, otherwise `false`.
|
||||
*/
|
||||
public boolean isRightBlock(Block block) {
|
||||
if (!typeCondition.isMet(block)) {
|
||||
return false;
|
||||
}
|
||||
for (TotemBlockProperty property : properties) {
|
||||
if (!property.isPropertyMet(block)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotates the properties of this TotemBlock by 90 degrees.
|
||||
* This method should be called when the totem structure is rotated.
|
||||
*/
|
||||
public void rotate90() {
|
||||
for (TotemBlockProperty property : properties) {
|
||||
property.rotate90();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mirrors the properties of this TotemBlock horizontally or vertically.
|
||||
* This method should be called when the totem structure is mirrored.
|
||||
*
|
||||
* @param axis The Axis along which to mirror the properties (X or Z).
|
||||
*/
|
||||
public void mirror(Axis axis) {
|
||||
for (TotemBlockProperty property : properties) {
|
||||
property.mirror(axis);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw text representation of this TotemBlock, including its TypeCondition and properties.
|
||||
*
|
||||
* @return The raw text representation of this TotemBlock.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringJoiner stringJoiner = new StringJoiner(";");
|
||||
for (TotemBlockProperty property : properties) {
|
||||
stringJoiner.add(property.getRawText());
|
||||
}
|
||||
return typeCondition.getRawText() + "{" + stringJoiner + "}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customfishing.api.mechanic.totem.block.property;
|
||||
|
||||
import org.bukkit.Axis;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.Orientable;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Locale;
|
||||
|
||||
public class AxisImpl implements TotemBlockProperty, Serializable {
|
||||
|
||||
private Axis axis;
|
||||
|
||||
public AxisImpl(Axis axis) {
|
||||
this.axis = axis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TotemBlockProperty mirror(Axis axis) {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotates the block axis 90 degrees. (X -> Z, Z -> X)
|
||||
* @return The rotated block axis.
|
||||
*/
|
||||
@Override
|
||||
public TotemBlockProperty rotate90() {
|
||||
if (this.axis == Axis.X) {
|
||||
axis = Axis.Z;
|
||||
} else if (this.axis == Axis.Z) {
|
||||
axis = Axis.X;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the block has the property.
|
||||
* @param block The block to check.
|
||||
* @return True if the block has the property.
|
||||
*/
|
||||
@Override
|
||||
public boolean isPropertyMet(Block block) {
|
||||
if (block.getBlockData() instanceof Orientable orientable) {
|
||||
return orientable.getAxis().equals(this.axis);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRawText() {
|
||||
return "axis=" + axis.name().toLowerCase(Locale.ENGLISH);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customfishing.api.mechanic.totem.block.property;
|
||||
|
||||
import org.bukkit.Axis;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.Directional;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Locale;
|
||||
|
||||
public class FaceImpl implements TotemBlockProperty, Serializable {
|
||||
|
||||
private BlockFace blockFace;
|
||||
|
||||
public FaceImpl(BlockFace blockFace) {
|
||||
this.blockFace = blockFace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mirrors the block face if the axis is X or Z.
|
||||
* @param axis The axis to mirror.
|
||||
* @return The mirrored block face.
|
||||
*/
|
||||
@Override
|
||||
public TotemBlockProperty mirror(Axis axis) {
|
||||
if (axis == Axis.X) {
|
||||
if (blockFace == BlockFace.SOUTH || blockFace == BlockFace.NORTH) {
|
||||
return new FaceImpl(blockFace.getOppositeFace());
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
} else if (axis == Axis.Z) {
|
||||
if (blockFace == BlockFace.EAST || blockFace == BlockFace.WEST) {
|
||||
return new FaceImpl(blockFace.getOppositeFace());
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TotemBlockProperty rotate90() {
|
||||
switch (blockFace) {
|
||||
case UP, DOWN -> {
|
||||
return this;
|
||||
}
|
||||
case EAST -> blockFace = BlockFace.SOUTH;
|
||||
case SOUTH -> blockFace = BlockFace.WEST;
|
||||
case WEST -> blockFace = BlockFace.NORTH;
|
||||
case NORTH -> blockFace = BlockFace.EAST;
|
||||
default -> throw new IllegalArgumentException("Unsupported block facing: " + blockFace);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPropertyMet(Block block) {
|
||||
if (block.getBlockData() instanceof Directional directional) {
|
||||
return directional.getFacing().equals(this.blockFace);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRawText() {
|
||||
return "face=" + blockFace.name().toLowerCase(Locale.ENGLISH);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customfishing.api.mechanic.totem.block.property;
|
||||
|
||||
import org.bukkit.Axis;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.Bisected;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Locale;
|
||||
|
||||
public class HalfImpl implements TotemBlockProperty, Serializable {
|
||||
private final Bisected.Half half;
|
||||
|
||||
public HalfImpl(Bisected.Half half) {
|
||||
this.half = half;
|
||||
}
|
||||
|
||||
/**
|
||||
* half is not affected by mirroring.
|
||||
* @param axis The axis to mirror.
|
||||
* @return this
|
||||
*/
|
||||
@Override
|
||||
public TotemBlockProperty mirror(Axis axis) {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* half is not affected by rotation.
|
||||
* @return this
|
||||
*/
|
||||
@Override
|
||||
public TotemBlockProperty rotate90() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the block's half is the same as the half of this property.
|
||||
* @param block The block to check.
|
||||
* @return true if the block's half is the same as the half of this property.
|
||||
*/
|
||||
@Override
|
||||
public boolean isPropertyMet(Block block) {
|
||||
if (block.getBlockData() instanceof Bisected bisected) {
|
||||
return bisected.getHalf().equals(this.half);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw text of the half property.
|
||||
* @return The raw text of the half property.
|
||||
*/
|
||||
@Override
|
||||
public String getRawText() {
|
||||
return "half=" + half.name().toLowerCase(Locale.ENGLISH);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customfishing.api.mechanic.totem.block.property;
|
||||
|
||||
import org.bukkit.Axis;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
public interface TotemBlockProperty {
|
||||
|
||||
/**
|
||||
* Mirrors the block face if the axis is X or Z.
|
||||
* @param axis The axis to mirror.
|
||||
* @return The mirrored block face.
|
||||
*/
|
||||
TotemBlockProperty mirror(Axis axis);
|
||||
|
||||
/**
|
||||
* Rotates the block face 90 degrees.
|
||||
* @return The rotated block face.
|
||||
*/
|
||||
TotemBlockProperty rotate90();
|
||||
|
||||
/**
|
||||
* Checks if the block has the property.
|
||||
* @param block The block to check.
|
||||
* @return True if the block has the property.
|
||||
*/
|
||||
boolean isPropertyMet(Block block);
|
||||
|
||||
/**
|
||||
* Gets the raw text of the property.
|
||||
* @return The raw text of the property.
|
||||
*/
|
||||
String getRawText();
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customfishing.api.mechanic.totem.block.type;
|
||||
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Represents a TypeCondition that checks if a Block's type name ends with a specified string.
|
||||
*/
|
||||
public class EndWithType implements TypeCondition, Serializable {
|
||||
|
||||
private final String end;
|
||||
|
||||
public EndWithType(String end) {
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified Block's type name ends with the configured ending string.
|
||||
*
|
||||
* @param type The Block to check.
|
||||
* @return `true` if the Block's type name ends with the specified string, otherwise `false`.
|
||||
*/
|
||||
@Override
|
||||
public boolean isMet(Block type) {
|
||||
return type.getType().name().endsWith(end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the raw text representation of this TypeCondition.
|
||||
* The raw text includes the asterisk (*) followed by the configured ending string.
|
||||
*
|
||||
* @return The raw text representation of this TypeCondition.
|
||||
*/
|
||||
@Override
|
||||
public String getRawText() {
|
||||
return "*" + end;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customfishing.api.mechanic.totem.block.type;
|
||||
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Represents a TypeCondition that checks if a Block's type matches a specified type string.
|
||||
*/
|
||||
public class EqualType implements TypeCondition, Serializable {
|
||||
|
||||
private final String type;
|
||||
|
||||
public EqualType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified Block's type matches the configured type string.
|
||||
*
|
||||
* @param type The Block to check.
|
||||
* @return `true` if the Block's type matches the specified type string, otherwise `false`.
|
||||
*/
|
||||
@Override
|
||||
public boolean isMet(Block type) {
|
||||
return this.type.equals(BukkitCustomFishingPlugin.getInstance().getBlockManager().getBlockID(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the raw text representation of this TypeCondition, which is the configured type string.
|
||||
*
|
||||
* @return The raw text representation of this TypeCondition.
|
||||
*/
|
||||
@Override
|
||||
public String getRawText() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customfishing.api.mechanic.totem.block.type;
|
||||
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Represents a TypeCondition that checks if a Block's type starts with a specified prefix.
|
||||
*/
|
||||
public class StartWithType implements TypeCondition, Serializable {
|
||||
|
||||
private final String start;
|
||||
|
||||
public StartWithType(String start) {
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified Block's type starts with the configured prefix.
|
||||
*
|
||||
* @param type The Block to check.
|
||||
* @return `true` if the Block's type starts with the specified prefix, otherwise `false`.
|
||||
*/
|
||||
@Override
|
||||
public boolean isMet(Block type) {
|
||||
return type.getType().name().startsWith(start);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the raw text representation of this TypeCondition, which is the configured prefix followed by '*'.
|
||||
*
|
||||
* @return The raw text representation of this TypeCondition.
|
||||
*/
|
||||
@Override
|
||||
public String getRawText() {
|
||||
return start + "*";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customfishing.api.mechanic.totem.block.type;
|
||||
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
/**
|
||||
* Represents a condition used to check the type of a Block.
|
||||
*/
|
||||
public interface TypeCondition {
|
||||
|
||||
/**
|
||||
* Checks if the specified Block meets the condition.
|
||||
*
|
||||
* @param block The Block to check.
|
||||
* @return `true` if the condition is met, otherwise `false`.
|
||||
*/
|
||||
boolean isMet(Block block);
|
||||
|
||||
/**
|
||||
* Gets the raw text representation of this TypeCondition.
|
||||
*
|
||||
* @return The raw text representation of this TypeCondition.
|
||||
*/
|
||||
String getRawText();
|
||||
|
||||
/**
|
||||
* Gets a TypeCondition based on its raw text representation.
|
||||
*
|
||||
* @param raw The raw text representation of the TypeCondition.
|
||||
* @return A TypeCondition instance corresponding to the raw text.
|
||||
*/
|
||||
static TypeCondition getTypeCondition(String raw) {
|
||||
if (raw.startsWith("*")) {
|
||||
return new EndWithType(raw.substring(1));
|
||||
} else if (raw.endsWith("*")) {
|
||||
return new StartWithType(raw.substring(0, raw.length() -1));
|
||||
} else {
|
||||
return new EqualType(raw);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ package net.momirealms.customfishing.api.storage;
|
||||
|
||||
import net.momirealms.customfishing.api.storage.data.PlayerData;
|
||||
import net.momirealms.customfishing.api.storage.user.UserData;
|
||||
import net.momirealms.customfishing.common.plugin.feature.Reloadable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -26,7 +27,7 @@ import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public interface StorageManager {
|
||||
public interface StorageManager extends Reloadable {
|
||||
|
||||
@NotNull
|
||||
String getServerID();
|
||||
@@ -52,7 +53,7 @@ public interface StorageManager {
|
||||
* @param data The PlayerData to be converted.
|
||||
* @return The byte array representation of PlayerData.
|
||||
*/
|
||||
byte @NotNull [] toBytes(@NotNull PlayerData data);
|
||||
byte[] toBytes(@NotNull PlayerData data);
|
||||
|
||||
/**
|
||||
* Converts PlayerData to JSON format.
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
repositories {
|
||||
maven("https://oss.sonatype.org/content/repositories/snapshots")
|
||||
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":core"))
|
||||
implementation(project(":common"))
|
||||
implementation(project(":compatibility"))
|
||||
implementation(project(":api"))
|
||||
compileOnly("org.spigotmc:spigot-api:${rootProject.properties["paper_version"]}-R0.1-SNAPSHOT")
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
package net.momirealms;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Hello world!");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package net.momirealms.customfishing.bukkit;
|
||||
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public class BukkitBootstrap extends JavaPlugin {
|
||||
|
||||
private BukkitCustomFishingPlugin plugin;
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
this.plugin = new BukkitCustomFishingPluginImpl(this);
|
||||
this.plugin.load();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
this.plugin.enable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
this.plugin.disable();
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,9 @@
|
||||
name: CustomFishing
|
||||
version: '${version}'
|
||||
main: net.momirealms.customfishing.CustomFishingPluginImpl
|
||||
version: '${project_version}'
|
||||
main: net.momirealms.customfishing.bukkit.BukkitBootstrap
|
||||
api-version: 1.17
|
||||
authors: [ XiaoMoMi ]
|
||||
folia-supported: true
|
||||
depend:
|
||||
- ProtocolLib
|
||||
softdepend:
|
||||
- Vault
|
||||
- PlaceholderAPI
|
||||
@@ -13,4 +13,6 @@ public interface ConfigLoader {
|
||||
YamlDocument loadData(File file);
|
||||
|
||||
YamlDocument loadData(File file, char routeSeparator);
|
||||
|
||||
void saveResource(String filePath);
|
||||
}
|
||||
|
||||
@@ -236,13 +236,6 @@ public enum Dependency {
|
||||
"caffeine",
|
||||
Relocation.of("caffeine", "com{}github{}benmanes{}caffeine")
|
||||
),
|
||||
LETTUCE(
|
||||
"io{}lettuce",
|
||||
"lettuce-core",
|
||||
"maven",
|
||||
"lettuce-core",
|
||||
Relocation.of("lettuce", "io{}lettuce")
|
||||
),
|
||||
JEDIS(
|
||||
"redis{}clients",
|
||||
"jedis",
|
||||
|
||||
@@ -17,126 +17,25 @@
|
||||
|
||||
package net.momirealms.customfishing.common.helper;
|
||||
|
||||
import net.momirealms.customfishing.common.plugin.CustomFishingPlugin;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* This class implements the VersionManager interface and is responsible for managing version-related information.
|
||||
*/
|
||||
public class VersionHelper {
|
||||
|
||||
private final boolean isNewerThan1_19_3;
|
||||
private final boolean isNewerThan1_19_4;
|
||||
private final boolean isNewerThan1_20;
|
||||
private final boolean isNewerThan1_20_5;
|
||||
private final boolean isNewerThan1_19;
|
||||
private final String serverVersion;
|
||||
private final boolean isSpigot;
|
||||
private boolean hasRegionScheduler;
|
||||
private boolean isMojmap;
|
||||
private final String pluginVersion;
|
||||
|
||||
public VersionHelper(String serverVersion) {
|
||||
this.serverVersion = serverVersion;
|
||||
String[] split = serverVersion.split("\\.");
|
||||
int main_ver = Integer.parseInt(split[0]);
|
||||
// Determine if the server version is newer than 1_19_R2 and 1_20_R1
|
||||
if (main_ver >= 20) {
|
||||
isNewerThan1_20_5 = Integer.parseInt(split[1]) >= 5;
|
||||
isNewerThan1_19_3 = isNewerThan1_19_4 = true;
|
||||
isNewerThan1_20 = true;
|
||||
isNewerThan1_19 = true;
|
||||
} else if (main_ver == 19) {
|
||||
isNewerThan1_20 = isNewerThan1_20_5 = false;
|
||||
isNewerThan1_19_3 = Integer.parseInt(split[1]) >= 3;
|
||||
isNewerThan1_19_4 = Integer.parseInt(split[1]) >= 4;
|
||||
isNewerThan1_19 = true;
|
||||
} else {
|
||||
isNewerThan1_20 = isNewerThan1_20_5 = isNewerThan1_19 = isNewerThan1_19_3 = isNewerThan1_19_4 = false;
|
||||
}
|
||||
// Check if the server is Spigot
|
||||
String server_name = plugin.getServer().getName();
|
||||
this.isSpigot = server_name.equals("CraftBukkit");
|
||||
|
||||
// Check if the server is Folia
|
||||
try {
|
||||
Class.forName("io.papermc.paper.threadedregions.scheduler.AsyncScheduler");
|
||||
this.hasRegionScheduler = true;
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
|
||||
}
|
||||
|
||||
// Check if the server is Mojmap
|
||||
try {
|
||||
Class.forName("net.minecraft.network.protocol.game.ClientboundBossEventPacket");
|
||||
this.isMojmap = true;
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
|
||||
}
|
||||
|
||||
// Get the plugin version
|
||||
this.pluginVersion = plugin.getDescription().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVersionNewerThan1_19() {
|
||||
return isNewerThan1_19;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVersionNewerThan1_19_4() {
|
||||
return isNewerThan1_19_4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVersionNewerThan1_19_3() {
|
||||
return isNewerThan1_19_3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVersionNewerThan1_20() {
|
||||
return isNewerThan1_20;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNewerThan1_20_5() {
|
||||
return isNewerThan1_20_5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSpigot() {
|
||||
return isSpigot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPluginVersion() {
|
||||
return pluginVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasRegionScheduler() {
|
||||
return hasRegionScheduler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMojmap() {
|
||||
return isMojmap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerVersion() {
|
||||
return serverVersion;
|
||||
}
|
||||
|
||||
// Method to asynchronously check for plugin updates
|
||||
@Override
|
||||
public CompletableFuture<Boolean> checkUpdate() {
|
||||
public static final Function<CustomFishingPlugin, CompletableFuture<Boolean>> UPDATE_CHECKER = (plugin) -> {
|
||||
CompletableFuture<Boolean> updateFuture = new CompletableFuture<>();
|
||||
plugin.getScheduler().async(() -> {
|
||||
plugin.getScheduler().async().execute(() -> {
|
||||
try {
|
||||
URL url = new URL("https://api.polymart.org/v1/getResourceInfoSimple/?resource_id=2723&key=version");
|
||||
URLConnection conn = url.openConnection();
|
||||
@@ -144,7 +43,7 @@ public class VersionHelper {
|
||||
conn.setReadTimeout(60000);
|
||||
InputStream inputStream = conn.getInputStream();
|
||||
String newest = new BufferedReader(new InputStreamReader(inputStream)).readLine();
|
||||
String current = plugin.getVersionManager().getPluginVersion();
|
||||
String current = plugin.getPluginVersion();
|
||||
inputStream.close();
|
||||
if (!compareVer(newest, current)) {
|
||||
updateFuture.complete(false);
|
||||
@@ -152,15 +51,71 @@ public class VersionHelper {
|
||||
}
|
||||
updateFuture.complete(true);
|
||||
} catch (Exception exception) {
|
||||
LogUtils.warn("Error occurred when checking update.", exception);
|
||||
plugin.getPluginLogger().warn("Error occurred when checking update.", exception);
|
||||
updateFuture.complete(false);
|
||||
}
|
||||
});
|
||||
return updateFuture;
|
||||
};
|
||||
|
||||
private static float version;
|
||||
private static boolean mojmap;
|
||||
private static boolean folia;
|
||||
|
||||
public static void init(String serverVersion) {
|
||||
String[] split = serverVersion.split("\\.");
|
||||
version = Float.parseFloat(split[1] + "." + split[2]);
|
||||
checkMojMap();
|
||||
checkFolia();
|
||||
}
|
||||
|
||||
private static void checkMojMap() {
|
||||
// Check if the server is Mojmap
|
||||
try {
|
||||
Class.forName("net.minecraft.network.protocol.game.ClientboundBossEventPacket");
|
||||
mojmap = true;
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkFolia() {
|
||||
try {
|
||||
Class.forName("io.papermc.paper.threadedregions.RegionizedServer");
|
||||
folia = true;
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isVersionNewerThan1_19() {
|
||||
return version >= 19;
|
||||
}
|
||||
|
||||
public static boolean isVersionNewerThan1_19_4() {
|
||||
return version >= 19.4;
|
||||
}
|
||||
|
||||
public static boolean isVersionNewerThan1_19_3() {
|
||||
return version >= 19.3;
|
||||
}
|
||||
|
||||
public static boolean isVersionNewerThan1_20() {
|
||||
return version >= 20.0;
|
||||
}
|
||||
|
||||
public boolean isNewerThan1_20_5() {
|
||||
return version >= 20.5;
|
||||
}
|
||||
|
||||
public static boolean isFolia() {
|
||||
return folia;
|
||||
}
|
||||
|
||||
public static boolean isMojmap() {
|
||||
return mojmap;
|
||||
}
|
||||
|
||||
// Method to compare two version strings
|
||||
private boolean compareVer(String newV, String currentV) {
|
||||
private static boolean compareVer(String newV, String currentV) {
|
||||
if (newV == null || currentV == null || newV.isEmpty() || currentV.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -5,5 +5,112 @@ import net.kyori.adventure.text.TranslatableComponent;
|
||||
|
||||
public interface MessageConstants {
|
||||
|
||||
TranslatableComponent.Builder COMMAND_RELOAD = Component.translatable().key("argument.entity.notfound.player");
|
||||
TranslatableComponent.Builder COMMAND_PREFIX = Component.translatable().key("command.prefix");
|
||||
TranslatableComponent.Builder COMMAND_RELOAD_SUCCESS = Component.translatable().key("command.reload.success");
|
||||
TranslatableComponent.Builder COMMAND_ITEM_FAILURE_NOT_EXIST = Component.translatable().key("command.item.failure.not_exist");
|
||||
TranslatableComponent.Builder COMMAND_ITEM_GIVE_SUCCESS = Component.translatable().key("command.item.give.success");
|
||||
TranslatableComponent.Builder COMMAND_ITEM_GET_SUCCESS = Component.translatable().key("command.item.get.success");
|
||||
TranslatableComponent.Builder COMMAND_FISH_FINDER_POSSIBLE_LOOTS = Component.translatable().key("command.fish_finder.possible_loots");
|
||||
TranslatableComponent.Builder COMMAND_FISH_FINDER_NO_LOOT = Component.translatable().key("command.fish_finder.no_loot");
|
||||
TranslatableComponent.Builder COMMAND_FISH_FINDER_SPLIT_CHAR = Component.translatable().key("command.fish_finder.split_char");
|
||||
TranslatableComponent.Builder COMMAND_COMPETITION_FAILURE_NOT_EXIST = Component.translatable().key("command.competition.failure.not_exist");
|
||||
TranslatableComponent.Builder COMMAND_COMPETITION_FAILURE_NO_COMPETITION = Component.translatable().key("command.competition.failure.no_competition");
|
||||
TranslatableComponent.Builder COMMAND_COMPETITION_FAILURE_STOP_SUCCESS = Component.translatable().key("command.competition.failure.stop.success");
|
||||
TranslatableComponent.Builder COMMAND_COMPETITION_FAILURE_END_SUCCESS = Component.translatable().key("command.competition.failure.end.success");
|
||||
TranslatableComponent.Builder COMMAND_BAG_EDIT_FAILURE_UNSAFE = Component.translatable().key("command.bag.edit.failure.unsafe");
|
||||
TranslatableComponent.Builder COMMAND_BAG_EDIT_FAILURE_NEVER_PLAYED = Component.translatable().key("command.bag.edit.failure.never_played");
|
||||
TranslatableComponent.Builder COMMAND_BAG_OPEN_SUCCESS = Component.translatable().key("command.bag.edit.open.success");
|
||||
TranslatableComponent.Builder COMMAND_DATA_FAILURE_NOT_LOAD = Component.translatable().key("command.data.failure.not_load");
|
||||
TranslatableComponent.Builder COMMAND_MARKET_OPEN_SUCCESS = Component.translatable().key("command.market.open.success");
|
||||
TranslatableComponent.Builder GUI_SELECT_FILE = Component.translatable().key("gui.select_file");
|
||||
TranslatableComponent.Builder GUI_SELECT_ITEM = Component.translatable().key("gui.select_item");
|
||||
TranslatableComponent.Builder GUI_INVALID_KEY = Component.translatable().key("gui.invalid_key");
|
||||
TranslatableComponent.Builder GUI_NEW_VALUE = Component.translatable().key("gui.new_value");
|
||||
TranslatableComponent.Builder GUI_TEMP_NEW_KEY = Component.translatable().key("gui.temp_new_key");
|
||||
TranslatableComponent.Builder GUI_SET_NEW_KEY = Component.translatable().key("gui.set_new_key");
|
||||
TranslatableComponent.Builder GUI_EDIT_KEY = Component.translatable().key("gui.edit_key");
|
||||
TranslatableComponent.Builder GUI_DELETE_PROPERTY = Component.translatable().key("gui.delete_property");
|
||||
TranslatableComponent.Builder GUI_CLICK_CONFIRM = Component.translatable().key("gui.click_confirm");
|
||||
TranslatableComponent.Builder GUI_INVALID_NUMBER = Component.translatable().key("gui.invalid_number");
|
||||
TranslatableComponent.Builder GUI_ILLEGAL_FORMAT = Component.translatable().key("gui.illegal_format");
|
||||
TranslatableComponent.Builder GUI_SCROLL_UP = Component.translatable().key("gui.scroll_up");
|
||||
TranslatableComponent.Builder GUI_SCROLL_DOWN = Component.translatable().key("gui.scroll_down");
|
||||
TranslatableComponent.Builder GUI_CANNOT_SCROLL_UP = Component.translatable().key("gui.cannot_scroll_up");
|
||||
TranslatableComponent.Builder GUI_CANNOT_SCROLL_DOWN = Component.translatable().key("gui.cannot_scroll_down");
|
||||
TranslatableComponent.Builder GUI_NEXT_PAGE = Component.translatable().key("gui.next_page");
|
||||
TranslatableComponent.Builder GUI_GOTO_NEXT_PAGE = Component.translatable().key("gui.goto_next_page");
|
||||
TranslatableComponent.Builder GUI_CANNOT_GOTO_NEXT_PAGE = Component.translatable().key("gui.cannot_goto_next_page");
|
||||
TranslatableComponent.Builder GUI_PREVIOUS_PAGE = Component.translatable().key("gui.previous_page");
|
||||
TranslatableComponent.Builder GUI_GOTO_PREVIOUS_PAGE = Component.translatable().key("gui.goto_previous_page");
|
||||
TranslatableComponent.Builder GUI_CANNOT_GOTO_PREVIOUS_PAGE = Component.translatable().key("gui.cannot_goto_previous_page");
|
||||
TranslatableComponent.Builder GUI_BACK_TO_PARENT_PAGE = Component.translatable().key("gui.back_to_parent_page");
|
||||
TranslatableComponent.Builder GUI_BACK_TO_PARENT_FOLDER = Component.translatable().key("gui.back_to_parent_folder");
|
||||
TranslatableComponent.Builder GUI_CURRENT_VALUE = Component.translatable().key("gui.current_value");
|
||||
TranslatableComponent.Builder GUI_CLICK_TO_TOGGLE = Component.translatable().key("gui.click_to_toggle");
|
||||
TranslatableComponent.Builder GUI_LEFT_CLICK_EDIT = Component.translatable().key("gui.left_click_edit");
|
||||
TranslatableComponent.Builder GUI_RIGHT_CLICK_RESET = Component.translatable().key("gui.right_click_reset");
|
||||
TranslatableComponent.Builder GUI_RIGHT_CLICK_DELETE = Component.translatable().key("gui.right_click_delete");
|
||||
TranslatableComponent.Builder GUI_RIGHT_CLICK_CANCEL = Component.translatable().key("gui.right_click_cancel");
|
||||
TranslatableComponent.Builder GUI_LOOT_SHOW_IN_FINDER = Component.translatable().key("gui.loot_show_in_finder");
|
||||
TranslatableComponent.Builder GUI_LOOT_SCORE = Component.translatable().key("gui.loot_score");
|
||||
TranslatableComponent.Builder GUI_LOOT_NICK = Component.translatable().key("gui.loot_nick");
|
||||
TranslatableComponent.Builder GUI_LOOT_INSTANT_GAME = Component.translatable().key("gui.loot_instant_game");
|
||||
TranslatableComponent.Builder GUI_LOOT_DISABLE_STATISTICS = Component.translatable().key("gui.loot_disable_statistics");
|
||||
TranslatableComponent.Builder GUI_LOOT_DISABLE_GAME = Component.translatable().key("gui.loot_disable_game");
|
||||
TranslatableComponent.Builder GUI_ITEM_AMOUNT = Component.translatable().key("gui.item_amount");
|
||||
TranslatableComponent.Builder GUI_ITEM_CUSTOM_MODEL_DATA = Component.translatable().key("gui.item_custom_model_data");
|
||||
TranslatableComponent.Builder GUI_ITEM_DISPLAY_NAME = Component.translatable().key("gui.item_display_name");
|
||||
TranslatableComponent.Builder GUI_ITEM_CUSTOM_DURABILITY = Component.translatable().key("gui.item_custom_durability");
|
||||
TranslatableComponent.Builder GUI_ITEM_ENCHANTMENT = Component.translatable().key("gui.item_enchantment");
|
||||
TranslatableComponent.Builder GUI_ITEM_HEAD64 = Component.translatable().key("gui.item_head64");
|
||||
TranslatableComponent.Builder GUI_ITEM_FLAG = Component.translatable().key("gui.item_item_flag");
|
||||
TranslatableComponent.Builder GUI_ITEM_LORE = Component.translatable().key("gui.item_lore");
|
||||
TranslatableComponent.Builder GUI_ITEM_MATERIAL = Component.translatable().key("gui.item_material");
|
||||
TranslatableComponent.Builder GUI_ITEM_NBT = Component.translatable().key("gui.item_nbt");
|
||||
TranslatableComponent.Builder GUI_ITEM_PREVENT_GRAB = Component.translatable().key("gui.item_prevent_grab");
|
||||
TranslatableComponent.Builder GUI_ITEM_PRICE = Component.translatable().key("gui.item_price");
|
||||
TranslatableComponent.Builder GUI_ITEM_PRICE_BASE = Component.translatable().key("gui.item_price_base");
|
||||
TranslatableComponent.Builder GUI_ITEM_PRICE_BONUS = Component.translatable().key("gui.item_price_bonus");
|
||||
TranslatableComponent.Builder GUI_ITEM_RANDOM_DURABILITY = Component.translatable().key("gui.item_random_durability");
|
||||
TranslatableComponent.Builder GUI_ITEM_SIZE = Component.translatable().key("gui.item_size");
|
||||
TranslatableComponent.Builder GUI_ITEM_STACKABLE = Component.translatable().key("gui.item_stackable");
|
||||
TranslatableComponent.Builder GUI_ITEM_STORED_ENCHANTMENT = Component.translatable().key("gui.item_stored_enchantment");
|
||||
TranslatableComponent.Builder GUI_ITEM_TAG = Component.translatable().key("gui.item_tag");
|
||||
TranslatableComponent.Builder GUI_ITEM_UNBREAKABLE = Component.translatable().key("gui.item_unbreakable");
|
||||
TranslatableComponent.Builder GUI_PAGE_AMOUNT_TITLE = Component.translatable().key("gui.page_amount_title");
|
||||
TranslatableComponent.Builder GUI_PAGE_MODEL_DATA_TITLE = Component.translatable().key("gui.page_model_data_title");
|
||||
TranslatableComponent.Builder GUI_PAGE_DISPLAY_NAME_TITLE = Component.translatable().key("gui.page_display_name_title");
|
||||
TranslatableComponent.Builder GUI_PAGE_NEW_DISPLAY_NAME = Component.translatable().key("gui.page_new_display_name");
|
||||
TranslatableComponent.Builder GUI_PAGE_CUSTOM_DURABILITY_TITLE = Component.translatable().key("gui.page_custom_durability_title");
|
||||
TranslatableComponent.Builder GUI_PAGE_STORED_ENCHANTMENT_TITLE = Component.translatable().key("gui.page_stored_enchantment_title");
|
||||
TranslatableComponent.Builder GUI_PAGE_ENCHANTMENT_TITLE = Component.translatable().key("gui.page_enchantment_title");
|
||||
TranslatableComponent.Builder GUI_PAGE_SELECT_ONE_ENCHANTMENT = Component.translatable().key("gui.page_select_one_enchantment");
|
||||
TranslatableComponent.Builder GUI_PAGE_ADD_NEW_ENCHANTMENT = Component.translatable().key("gui.page_add_new_enchantment");
|
||||
TranslatableComponent.Builder GUI_PAGE_ITEM_FLAG_TITLE = Component.translatable().key("gui.page_item_flag_title");
|
||||
TranslatableComponent.Builder GUI_PAGE_LORE_TITLE = Component.translatable().key("gui.page_lore_title");
|
||||
TranslatableComponent.Builder GUI_PAGE_ADD_NEW_LORE = Component.translatable().key("gui.page_add_new_lore");
|
||||
TranslatableComponent.Builder GUI_PAGE_SELECT_ONE_LORE = Component.translatable().key("gui.page_select_one_lore");
|
||||
TranslatableComponent.Builder GUI_PAGE_MATERIAL_TITLE = Component.translatable().key("gui.page_material_title");
|
||||
TranslatableComponent.Builder GUI_PAGE_NBT_COMPOUND_KEY_TITLE = Component.translatable().key("gui.page_nbt_compound_key_title");
|
||||
TranslatableComponent.Builder GUI_PAGE_NBT_LIST_KEY_TITLE = Component.translatable().key("gui.page_nbt_list_key_title");
|
||||
TranslatableComponent.Builder GUI_PAGE_NBT_KEY_TITLE = Component.translatable().key("gui.page_nbt_key_title");
|
||||
TranslatableComponent.Builder GUI_PAGE_NBT_INVALID_KEY = Component.translatable().key("gui.page_nbt_invalid_key");
|
||||
TranslatableComponent.Builder GUI_PAGE_NBT_ADD_NEW_COMPOUND= Component.translatable().key("gui.page_nbt_add_new_compound");
|
||||
TranslatableComponent.Builder GUI_PAGE_NBT_ADD_NEW_LIST = Component.translatable().key("gui.page_nbt_add_new_list");
|
||||
TranslatableComponent.Builder GUI_PAGE_NBT_ADD_NEW_VALUE = Component.translatable().key("gui.page_nbt_add_new_value");
|
||||
TranslatableComponent.Builder GUI_PAGE_ADD_NEW_KEY = Component.translatable().key("gui.page_add_new_key");
|
||||
TranslatableComponent.Builder GUI_PAGE_NBT_PREVIEW = Component.translatable().key("gui.page_nbt_preview");
|
||||
TranslatableComponent.Builder GUI_PAGE_NBT_BACK_TO_COMPOUND = Component.translatable().key("gui.page_nbt_back_to_compound");
|
||||
TranslatableComponent.Builder GUI_PAGE_NBT_SET_VALUE_TITLE = Component.translatable().key("gui.page_nbt_set_value_title");
|
||||
TranslatableComponent.Builder GUI_PAGE_NBT_EDIT_TITLE = Component.translatable().key("gui.page_nbt_edit_title");
|
||||
TranslatableComponent.Builder GUI_PAGE_NICK_TITLE = Component.translatable().key("gui.page_nick_title");
|
||||
TranslatableComponent.Builder GUI_PAGE_NEW_NICK = Component.translatable().key("gui.page_new_nick");
|
||||
TranslatableComponent.Builder GUI_PAGE_PRICE_TITLE = Component.translatable().key("gui.page_price_title");
|
||||
TranslatableComponent.Builder GUI_PAGE_BASE_PRICE = Component.translatable().key("gui.page_base_price");
|
||||
TranslatableComponent.Builder GUI_PAGE_BASE_BONUS = Component.translatable().key("gui.page_base_bonus");
|
||||
TranslatableComponent.Builder GUI_PAGE_SCORE_TITLE = Component.translatable().key("gui.page_score_title");
|
||||
TranslatableComponent.Builder GUI_PAGE_SIZE_TITLE = Component.translatable().key("gui.page_size_title");
|
||||
TranslatableComponent.Builder GUI_PAGE_SIZE_MIN = Component.translatable().key("gui.page_size_min");
|
||||
TranslatableComponent.Builder GUI_PAGE_SIZE_MAX = Component.translatable().key("gui.page_size_max");
|
||||
TranslatableComponent.Builder GUI_PAGE_SIZE_MAX_NO_LESS_MIN = Component.translatable().key("gui.page_size_max_no_less_min");
|
||||
}
|
||||
|
||||
@@ -5,7 +5,123 @@ public class StandardLocales {
|
||||
public static String COMPETITION_NO_PLAYER = "No Player";
|
||||
public static String COMPETITION_NO_SCORE = "No Score";
|
||||
public static String COMPETITION_NO_RANK = "No Rank";
|
||||
|
||||
public static String GOAL_TOTAL_SIZE;
|
||||
public static String GOAL_CATCH_AMOUNT;
|
||||
public static String GOAL_TOTAL_SCORE;
|
||||
public static String GOAL_MAX_SIZE;
|
||||
|
||||
public static String FORMAT_SECOND = "s";
|
||||
public static String FORMAT_MINUTE = "m";
|
||||
public static String FORMAT_HOUR = "h";
|
||||
|
||||
public static String COMMAND_PREFIX;
|
||||
public static String COMMAND_RELOAD;
|
||||
public static String COMMAND_COMPETITION_NOT_EXISTS;
|
||||
public static String COMMAND_N0_COMPETITION_ONGOING;
|
||||
public static String COMMAND_END_COMPETITION;
|
||||
public static String COMMAND_STOP_COMPETITION;
|
||||
public static String COMMAND_ITEM_NOT_EXISTS;
|
||||
public static String COMMAND_GET_ITEM;
|
||||
public static String COMMAND_GIVE_ITEM;
|
||||
public static String COMMAND_NEVER_PLAYED;
|
||||
public static String COMMAND_UNSAFE_MODIFICATION;
|
||||
public static String COMMAND_DATA_NOT_LOAD;
|
||||
public static String COMMAND_MARKET_OPEN;
|
||||
public static String COMMAND_FISHING_BAG_OPEN;
|
||||
public static String COMMAND_POSSIBLE_LOOTS_SPLIT_CHAR;
|
||||
public static String COMMAND_POSSIBLE_LOOTS;
|
||||
|
||||
public static String GUI_SCROLL_DOWN;
|
||||
public static String GUI_SCROLL_UP;
|
||||
public static String GUI_CANNOT_SCROLL_UP;
|
||||
public static String GUI_CANNOT_SCROLL_DOWN;
|
||||
public static String GUI_NEXT_PAGE;
|
||||
public static String GUI_GOTO_NEXT_PAGE;
|
||||
public static String GUI_CANNOT_GOTO_NEXT_PAGE;
|
||||
public static String GUI_PREVIOUS_PAGE;
|
||||
public static String GUI_GOTO_PREVIOUS_PAGE;
|
||||
public static String GUI_CANNOT_GOTO_PREVIOUS_PAGE;
|
||||
public static String GUI_BACK_TO_PARENT_PAGE;
|
||||
public static String GUI_BACK_TO_PARENT_FOLDER;
|
||||
public static String GUI_CURRENT_VALUE;
|
||||
public static String GUI_CLICK_TO_TOGGLE;
|
||||
public static String GUI_LEFT_CLICK_EDIT;
|
||||
public static String GUI_RIGHT_CLICK_RESET;
|
||||
public static String GUI_RIGHT_CLICK_DELETE;
|
||||
public static String GUI_LOOT_SHOW_IN_FINDER;
|
||||
public static String GUI_LOOT_SCORE;
|
||||
public static String GUI_LOOT_NICK;
|
||||
public static String GUI_LOOT_INSTANT_GAME;
|
||||
public static String GUI_LOOT_DISABLE_STATS;
|
||||
public static String GUI_LOOT_DISABLE_GAME;
|
||||
public static String GUI_ITEM_AMOUNT;
|
||||
public static String GUI_ITEM_MODEL_DATA;
|
||||
public static String GUI_ITEM_DISPLAY_NAME;
|
||||
public static String GUI_ITEM_DURABILITY;
|
||||
public static String GUI_ITEM_ENCHANTMENT;
|
||||
public static String GUI_ITEM_HEAD64;
|
||||
public static String GUI_ITEM_FLAG;
|
||||
public static String GUI_ITEM_LORE;
|
||||
public static String GUI_ITEM_MATERIAL;
|
||||
public static String GUI_ITEM_NBT;
|
||||
public static String GUI_ITEM_PREVENT_GRAB;
|
||||
public static String GUI_ITEM_PRICE;
|
||||
public static String GUI_ITEM_PRICE_BASE;
|
||||
public static String GUI_ITEM_PRICE_BONUS;
|
||||
public static String GUI_ITEM_RANDOM_DURABILITY;
|
||||
public static String GUI_ITEM_SIZE;
|
||||
public static String GUI_ITEM_STACKABLE;
|
||||
public static String GUI_ITEM_STORED_ENCHANTMENT;
|
||||
public static String GUI_ITEM_TAG;
|
||||
public static String GUI_ITEM_UNBREAKABLE;
|
||||
public static String GUI_DELETE_PROPERTY;
|
||||
public static String GUI_NEW_VALUE;
|
||||
public static String GUI_CLICK_CONFIRM;
|
||||
public static String GUI_INVALID_NUMBER;
|
||||
public static String GUI_ILLEGAL_FORMAT;
|
||||
public static String GUI_TITLE_AMOUNT;
|
||||
public static String GUI_TITLE_MODEL_DATA;
|
||||
public static String GUI_TITLE_DISPLAY_NAME;
|
||||
public static String GUI_NEW_DISPLAY_NAME;
|
||||
public static String GUI_TITLE_CUSTOM_DURABILITY;
|
||||
public static String GUI_TITLE_ENCHANTMENT;
|
||||
public static String GUI_TITLE_STORED_ENCHANTMENT;
|
||||
public static String GUI_SELECT_ONE_ENCHANTMENT;
|
||||
public static String GUI_ADD_NEW_ENCHANTMENT;
|
||||
public static String GUI_TITLE_ITEM_FLAG;
|
||||
public static String GUI_TITLE_LORE;
|
||||
public static String GUI_ADD_NEW_LORE;
|
||||
public static String GUI_SELECT_ONE_LORE;
|
||||
public static String GUI_TITLE_MATERIAL;
|
||||
public static String GUI_TITLE_NBT_COMPOUND;
|
||||
public static String GUI_TITLE_NBT_LIST;
|
||||
public static String GUI_TITLE_NBT_KEY;
|
||||
public static String GUI_NBT_INVALID_KEY;
|
||||
public static String GUI_RIGHT_CLICK_CANCEL;
|
||||
public static String GUI_NBT_ADD_COMPOUND;
|
||||
public static String GUI_NBT_ADD_LIST;
|
||||
public static String GUI_NBT_ADD_VALUE;
|
||||
public static String GUI_NBT_PREVIEW;
|
||||
public static String GUI_NBT_BACK_TO_COMPOUND;
|
||||
public static String GUI_NBT_SET_VALUE_TITLE;
|
||||
public static String GUI_NBT_EDIT_TITLE;
|
||||
public static String GUI_NICK_TITLE;
|
||||
public static String GUI_NICK_NEW;
|
||||
public static String GUI_PRICE_TITLE;
|
||||
public static String GUI_PRICE_BASE;
|
||||
public static String GUI_PRICE_BONUS;
|
||||
public static String GUI_SCORE_TITLE;
|
||||
public static String GUI_SIZE_TITLE;
|
||||
public static String GUI_SIZE_MIN;
|
||||
public static String GUI_SIZE_MAX;
|
||||
public static String GUI_SIZE_MAX_NO_LESS;
|
||||
public static String GUI_SELECT_FILE;
|
||||
public static String GUI_SELECT_ITEM;
|
||||
public static String GUI_ADD_NEW_KEY;
|
||||
public static String GUI_DUPE_INVALID_KEY;
|
||||
public static String GUI_SEARCH;
|
||||
public static String GUI_TEMP_NEW_KEY;
|
||||
public static String GUI_SET_NEW_KEY;
|
||||
public static String GUI_EDIT_KEY;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import java.util.stream.Stream;
|
||||
public class TranslationManager {
|
||||
|
||||
public static final Locale DEFAULT_LOCALE = Locale.ENGLISH;
|
||||
private static final List<String> locales = List.of("en");
|
||||
private static final List<String> locales = List.of("en", "zh_cn");
|
||||
|
||||
private final CustomFishingPlugin plugin;
|
||||
private final Set<Locale> installed = ConcurrentHashMap.newKeySet();
|
||||
@@ -40,7 +40,7 @@ public class TranslationManager {
|
||||
}
|
||||
|
||||
for (String lang : locales) {
|
||||
this.plugin.getConfigManager().loadConfig("translations/" + lang + ".yml");
|
||||
this.plugin.getConfigManager().saveResource("translations/" + lang + ".yml");
|
||||
}
|
||||
|
||||
this.registry = MiniMessageTranslationRegistry.create(Key.key("customfishing", "main"), AdventureHelper.getMiniMessage());
|
||||
|
||||
@@ -8,6 +8,7 @@ repositories {
|
||||
maven("https://repo.oraxen.com/releases/") // oraxen
|
||||
maven("https://repo.auxilor.io/repository/maven-public/") // eco
|
||||
maven("https://nexus.betonquest.org/repository/betonquest/") // betonquest
|
||||
maven("https://repo.dmulloy2.net/repository/public/") // betonquest needs packet wrapper?
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -48,7 +49,7 @@ dependencies {
|
||||
compileOnly("net.Indyuce:MMOItems-API:6.10-SNAPSHOT")
|
||||
compileOnly("io.lumine:MythicLib-dist:1.6.2-SNAPSHOT")
|
||||
compileOnly("pers.neige.neigeitems:NeigeItems:1.17.13")
|
||||
compileOnly("io.th0rgal:oraxen:1.175.0")
|
||||
compileOnly("io.th0rgal:oraxen:1.168.0")
|
||||
// entity
|
||||
compileOnly("io.lumine:Mythic-Dist:5.6.2")
|
||||
// eco
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
|
||||
package net.momirealms.customfishing.bukkit.integration.item;
|
||||
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import net.momirealms.customfishing.api.integration.ItemProvider;
|
||||
import net.momirealms.customfishing.api.mechanic.context.Context;
|
||||
import net.momirealms.customfishing.common.util.Key;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -38,7 +38,13 @@ public class CustomFishingItemProvider implements ItemProvider {
|
||||
@Override
|
||||
public ItemStack buildItem(@NotNull Player player, @NotNull String id) {
|
||||
String[] split = id.split(":", 2);
|
||||
ItemStack itemStack = BukkitCustomFishingPlugin.getInstance().getItemManager().buildInternal(Context.player(player), Key.key(split[0], split[1]));
|
||||
String finalID;
|
||||
if (split.length != 2) {
|
||||
finalID = split[0];
|
||||
} else {
|
||||
finalID = split[1];
|
||||
}
|
||||
ItemStack itemStack = BukkitCustomFishingPlugin.getInstance().getItemManager().buildInternal(Context.player(player), finalID);
|
||||
return requireNonNull(itemStack);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,144 +1,144 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customfishing.bukkit.integration.papi;
|
||||
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import net.momirealms.customfishing.api.mechanic.competition.FishingCompetition;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class CompetitionPapi extends PlaceholderExpansion {
|
||||
|
||||
private final BukkitCustomFishingPlugin plugin;
|
||||
|
||||
public CompetitionPapi(BukkitCustomFishingPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void load() {
|
||||
super.register();
|
||||
}
|
||||
|
||||
public void unload() {
|
||||
super.unregister();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getIdentifier() {
|
||||
return "cfcompetition";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getAuthor() {
|
||||
return "XiaoMoMi";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getVersion() {
|
||||
return "2.0";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean persist() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String onRequest(OfflinePlayer player, @NotNull String params) {
|
||||
switch (params) {
|
||||
case "goingon" -> {
|
||||
return String.valueOf(plugin.getCompetitionManager().getOnGoingCompetition() != null);
|
||||
}
|
||||
case "nextseconds" -> {
|
||||
return String.valueOf(plugin.getCompetitionManager().getNextCompetitionInSeconds());
|
||||
}
|
||||
case "nextsecond" -> {
|
||||
return plugin.getCompetitionManager().getNextCompetitionInSeconds() % 60 + CFLocale.FORMAT_Second;
|
||||
}
|
||||
case "nextminute" -> {
|
||||
int sec = plugin.getCompetitionManager().getNextCompetitionInSeconds();
|
||||
int min = (sec % 3600) / 60;
|
||||
return sec < 60 ? "" : min + CFLocale.FORMAT_Minute;
|
||||
}
|
||||
case "nexthour" -> {
|
||||
int sec = plugin.getCompetitionManager().getNextCompetitionInSeconds();
|
||||
int h = (sec % (3600 * 24)) / 3600;
|
||||
return sec < 3600 ? "" : h + CFLocale.FORMAT_Hour;
|
||||
}
|
||||
case "nextday" -> {
|
||||
int sec = plugin.getCompetitionManager().getNextCompetitionInSeconds();
|
||||
int day = sec / (3600 * 24);
|
||||
return day == 0 ? "" : day + CFLocale.FORMAT_Day;
|
||||
}
|
||||
case "rank" -> {
|
||||
FishingCompetition competition = plugin.getCompetitionManager().getOnGoingCompetition();
|
||||
if (competition == null) return "";
|
||||
else return String.valueOf(competition.getRanking().getPlayerRank(player.getName()));
|
||||
}
|
||||
case "goal" -> {
|
||||
FishingCompetition competition = plugin.getCompetitionManager().getOnGoingCompetition();
|
||||
if (competition == null) return "";
|
||||
else return competition.getGoal().name();
|
||||
}
|
||||
case "seconds" -> {
|
||||
FishingCompetition competition = plugin.getCompetitionManager().getOnGoingCompetition();
|
||||
if (competition == null) return "";
|
||||
return competition.getCachedPlaceholder("{seconds}");
|
||||
}
|
||||
case "second" -> {
|
||||
FishingCompetition competition = plugin.getCompetitionManager().getOnGoingCompetition();
|
||||
if (competition == null) return "";
|
||||
return competition.getCachedPlaceholder("{second}");
|
||||
}
|
||||
case "minute" -> {
|
||||
FishingCompetition competition = plugin.getCompetitionManager().getOnGoingCompetition();
|
||||
if (competition == null) return "";
|
||||
return competition.getCachedPlaceholder("{minute}");
|
||||
}
|
||||
case "hour" -> {
|
||||
FishingCompetition competition = plugin.getCompetitionManager().getOnGoingCompetition();
|
||||
if (competition == null) return "";
|
||||
return competition.getCachedPlaceholder("{hour}");
|
||||
}
|
||||
}
|
||||
|
||||
String[] split = params.split("_", 2);
|
||||
switch (split[0]) {
|
||||
case "score" -> {
|
||||
FishingCompetition competition = plugin.getCompetitionManager().getOnGoingCompetition();
|
||||
if (competition == null) return "";
|
||||
if (split.length == 1) {
|
||||
return String.format("%.2f", competition.getRanking().getPlayerScore(player.getName()));
|
||||
} else {
|
||||
return String.format("%.2f", competition.getRanking().getScoreAt(Integer.parseInt(split[1])));
|
||||
}
|
||||
}
|
||||
case "player" -> {
|
||||
FishingCompetition competition = plugin.getCompetitionManager().getOnGoingCompetition();
|
||||
if (competition == null) return "";
|
||||
if (split.length == 1) return "Invalid format";
|
||||
return Optional.ofNullable(competition.getRanking().getPlayerAt(Integer.parseInt(split[1]))).orElse("");
|
||||
}
|
||||
}
|
||||
return "null";
|
||||
}
|
||||
}
|
||||
///*
|
||||
// * Copyright (C) <2022> <XiaoMoMi>
|
||||
// *
|
||||
// * This program is free software: you can redistribute it and/or modify
|
||||
// * it under the terms of the GNU General Public License as published by
|
||||
// * the Free Software Foundation, either version 3 of the License, or
|
||||
// * any later version.
|
||||
// *
|
||||
// * This program is distributed in the hope that it will be useful,
|
||||
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// * GNU General Public License for more details.
|
||||
// *
|
||||
// * You should have received a copy of the GNU General Public License
|
||||
// * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// */
|
||||
//
|
||||
//package net.momirealms.customfishing.bukkit.integration.papi;
|
||||
//
|
||||
//import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
//import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
//import net.momirealms.customfishing.api.mechanic.competition.FishingCompetition;
|
||||
//import org.bukkit.OfflinePlayer;
|
||||
//import org.jetbrains.annotations.NotNull;
|
||||
//import org.jetbrains.annotations.Nullable;
|
||||
//
|
||||
//import java.util.Optional;
|
||||
//
|
||||
//public class CompetitionPapi extends PlaceholderExpansion {
|
||||
//
|
||||
// private final BukkitCustomFishingPlugin plugin;
|
||||
//
|
||||
// public CompetitionPapi(BukkitCustomFishingPlugin plugin) {
|
||||
// this.plugin = plugin;
|
||||
// }
|
||||
//
|
||||
// public void load() {
|
||||
// super.register();
|
||||
// }
|
||||
//
|
||||
// public void unload() {
|
||||
// super.unregister();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public @NotNull String getIdentifier() {
|
||||
// return "cfcompetition";
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public @NotNull String getAuthor() {
|
||||
// return "XiaoMoMi";
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public @NotNull String getVersion() {
|
||||
// return "2.0";
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean persist() {
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public @Nullable String onRequest(OfflinePlayer player, @NotNull String params) {
|
||||
// switch (params) {
|
||||
// case "goingon" -> {
|
||||
// return String.valueOf(plugin.getCompetitionManager().getOnGoingCompetition() != null);
|
||||
// }
|
||||
// case "nextseconds" -> {
|
||||
// return String.valueOf(plugin.getCompetitionManager().getNextCompetitionInSeconds());
|
||||
// }
|
||||
// case "nextsecond" -> {
|
||||
// return plugin.getCompetitionManager().getNextCompetitionInSeconds() % 60 + CFLocale.FORMAT_Second;
|
||||
// }
|
||||
// case "nextminute" -> {
|
||||
// int sec = plugin.getCompetitionManager().getNextCompetitionInSeconds();
|
||||
// int min = (sec % 3600) / 60;
|
||||
// return sec < 60 ? "" : min + CFLocale.FORMAT_Minute;
|
||||
// }
|
||||
// case "nexthour" -> {
|
||||
// int sec = plugin.getCompetitionManager().getNextCompetitionInSeconds();
|
||||
// int h = (sec % (3600 * 24)) / 3600;
|
||||
// return sec < 3600 ? "" : h + CFLocale.FORMAT_Hour;
|
||||
// }
|
||||
// case "nextday" -> {
|
||||
// int sec = plugin.getCompetitionManager().getNextCompetitionInSeconds();
|
||||
// int day = sec / (3600 * 24);
|
||||
// return day == 0 ? "" : day + CFLocale.FORMAT_Day;
|
||||
// }
|
||||
// case "rank" -> {
|
||||
// FishingCompetition competition = plugin.getCompetitionManager().getOnGoingCompetition();
|
||||
// if (competition == null) return "";
|
||||
// else return String.valueOf(competition.getRanking().getPlayerRank(player.getName()));
|
||||
// }
|
||||
// case "goal" -> {
|
||||
// FishingCompetition competition = plugin.getCompetitionManager().getOnGoingCompetition();
|
||||
// if (competition == null) return "";
|
||||
// else return competition.getGoal().name();
|
||||
// }
|
||||
// case "seconds" -> {
|
||||
// FishingCompetition competition = plugin.getCompetitionManager().getOnGoingCompetition();
|
||||
// if (competition == null) return "";
|
||||
// return competition.getCachedPlaceholder("{seconds}");
|
||||
// }
|
||||
// case "second" -> {
|
||||
// FishingCompetition competition = plugin.getCompetitionManager().getOnGoingCompetition();
|
||||
// if (competition == null) return "";
|
||||
// return competition.getCachedPlaceholder("{second}");
|
||||
// }
|
||||
// case "minute" -> {
|
||||
// FishingCompetition competition = plugin.getCompetitionManager().getOnGoingCompetition();
|
||||
// if (competition == null) return "";
|
||||
// return competition.getCachedPlaceholder("{minute}");
|
||||
// }
|
||||
// case "hour" -> {
|
||||
// FishingCompetition competition = plugin.getCompetitionManager().getOnGoingCompetition();
|
||||
// if (competition == null) return "";
|
||||
// return competition.getCachedPlaceholder("{hour}");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// String[] split = params.split("_", 2);
|
||||
// switch (split[0]) {
|
||||
// case "score" -> {
|
||||
// FishingCompetition competition = plugin.getCompetitionManager().getOnGoingCompetition();
|
||||
// if (competition == null) return "";
|
||||
// if (split.length == 1) {
|
||||
// return String.format("%.2f", competition.getRanking().getPlayerScore(player.getName()));
|
||||
// } else {
|
||||
// return String.format("%.2f", competition.getRanking().getScoreAt(Integer.parseInt(split[1])));
|
||||
// }
|
||||
// }
|
||||
// case "player" -> {
|
||||
// FishingCompetition competition = plugin.getCompetitionManager().getOnGoingCompetition();
|
||||
// if (competition == null) return "";
|
||||
// if (split.length == 1) return "Invalid format";
|
||||
// return Optional.ofNullable(competition.getRanking().getPlayerAt(Integer.parseInt(split[1]))).orElse("");
|
||||
// }
|
||||
// }
|
||||
// return "null";
|
||||
// }
|
||||
//}
|
||||
|
||||
@@ -1,126 +1,126 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customfishing.bukkit.integration.papi;
|
||||
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class CustomFishingPapi extends PlaceholderExpansion {
|
||||
|
||||
private final BukkitCustomFishingPlugin plugin;
|
||||
|
||||
public CustomFishingPapi(BukkitCustomFishingPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void load() {
|
||||
super.register();
|
||||
}
|
||||
|
||||
public void unload() {
|
||||
super.unregister();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getIdentifier() {
|
||||
return "customfishing";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getAuthor() {
|
||||
return "XiaoMoMi";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getVersion() {
|
||||
return "2.0";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean persist() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String onRequest(OfflinePlayer offlinePlayer, @NotNull String params) {
|
||||
String[] split = params.split("_");
|
||||
|
||||
Player player = offlinePlayer.getPlayer();
|
||||
if (player == null)
|
||||
return "";
|
||||
|
||||
switch (split[0]) {
|
||||
case "market" -> {
|
||||
if (split.length < 2)
|
||||
return null;
|
||||
switch (split[1]) {
|
||||
case "limit" -> {
|
||||
if (split.length < 3) {
|
||||
return String.format("%.2f", plugin.getMarketManager().earningLimit(player));
|
||||
} else {
|
||||
Player another = Bukkit.getPlayer(split[2]);
|
||||
if (another == null) {
|
||||
return "";
|
||||
}
|
||||
return String.format("%.2f", plugin.getMarketManager().earningLimit(another));
|
||||
}
|
||||
}
|
||||
case "earnings" -> {
|
||||
OnlineUserData user;
|
||||
if (split.length < 3) {
|
||||
user = plugin.getStorageManager().getOnlineUser(player.getUniqueId());
|
||||
} else {
|
||||
Player another = Bukkit.getPlayer(split[2]);
|
||||
if (another == null) {
|
||||
return "";
|
||||
}
|
||||
user = plugin.getStorageManager().getOnlineUser(another.getUniqueId());
|
||||
}
|
||||
if (user == null)
|
||||
return "";
|
||||
return String.format("%.2f", user.getEarningData().earnings);
|
||||
}
|
||||
case "canearn" -> {
|
||||
if (split.length < 3) {
|
||||
OnlineUserData user = plugin.getStorageManager().getOnlineUser(player.getUniqueId());
|
||||
if (user == null)
|
||||
return "";
|
||||
return String.format("%.2f", plugin.getMarketManager().earningLimit(player) - user.getEarningData().earnings);
|
||||
} else {
|
||||
Player another = Bukkit.getPlayer(split[2]);
|
||||
if (another == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
OnlineUserData user = plugin.getStorageManager().getOnlineUser(another.getUniqueId());
|
||||
if (user == null)
|
||||
return "";
|
||||
return String.format("%.2f", plugin.getMarketManager().earningLimit(another) - user.getEarningData().earnings);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
///*
|
||||
// * Copyright (C) <2022> <XiaoMoMi>
|
||||
// *
|
||||
// * This program is free software: you can redistribute it and/or modify
|
||||
// * it under the terms of the GNU General Public License as published by
|
||||
// * the Free Software Foundation, either version 3 of the License, or
|
||||
// * any later version.
|
||||
// *
|
||||
// * This program is distributed in the hope that it will be useful,
|
||||
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// * GNU General Public License for more details.
|
||||
// *
|
||||
// * You should have received a copy of the GNU General Public License
|
||||
// * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// */
|
||||
//
|
||||
//package net.momirealms.customfishing.bukkit.integration.papi;
|
||||
//
|
||||
//import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
//import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
//import org.bukkit.Bukkit;
|
||||
//import org.bukkit.OfflinePlayer;
|
||||
//import org.bukkit.entity.Player;
|
||||
//import org.jetbrains.annotations.NotNull;
|
||||
//import org.jetbrains.annotations.Nullable;
|
||||
//
|
||||
//public class CustomFishingPapi extends PlaceholderExpansion {
|
||||
//
|
||||
// private final BukkitCustomFishingPlugin plugin;
|
||||
//
|
||||
// public CustomFishingPapi(BukkitCustomFishingPlugin plugin) {
|
||||
// this.plugin = plugin;
|
||||
// }
|
||||
//
|
||||
// public void load() {
|
||||
// super.register();
|
||||
// }
|
||||
//
|
||||
// public void unload() {
|
||||
// super.unregister();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public @NotNull String getIdentifier() {
|
||||
// return "customfishing";
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public @NotNull String getAuthor() {
|
||||
// return "XiaoMoMi";
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public @NotNull String getVersion() {
|
||||
// return "2.0";
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean persist() {
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public @Nullable String onRequest(OfflinePlayer offlinePlayer, @NotNull String params) {
|
||||
// String[] split = params.split("_");
|
||||
//
|
||||
// Player player = offlinePlayer.getPlayer();
|
||||
// if (player == null)
|
||||
// return "";
|
||||
//
|
||||
// switch (split[0]) {
|
||||
// case "market" -> {
|
||||
// if (split.length < 2)
|
||||
// return null;
|
||||
// switch (split[1]) {
|
||||
// case "limit" -> {
|
||||
// if (split.length < 3) {
|
||||
// return String.format("%.2f", plugin.getMarketManager().earningLimit(player));
|
||||
// } else {
|
||||
// Player another = Bukkit.getPlayer(split[2]);
|
||||
// if (another == null) {
|
||||
// return "";
|
||||
// }
|
||||
// return String.format("%.2f", plugin.getMarketManager().earningLimit(another));
|
||||
// }
|
||||
// }
|
||||
// case "earnings" -> {
|
||||
// OnlineUserData user;
|
||||
// if (split.length < 3) {
|
||||
// user = plugin.getStorageManager().getOnlineUser(player.getUniqueId());
|
||||
// } else {
|
||||
// Player another = Bukkit.getPlayer(split[2]);
|
||||
// if (another == null) {
|
||||
// return "";
|
||||
// }
|
||||
// user = plugin.getStorageManager().getOnlineUser(another.getUniqueId());
|
||||
// }
|
||||
// if (user == null)
|
||||
// return "";
|
||||
// return String.format("%.2f", user.getEarningData().earnings);
|
||||
// }
|
||||
// case "canearn" -> {
|
||||
// if (split.length < 3) {
|
||||
// OnlineUserData user = plugin.getStorageManager().getOnlineUser(player.getUniqueId());
|
||||
// if (user == null)
|
||||
// return "";
|
||||
// return String.format("%.2f", plugin.getMarketManager().earningLimit(player) - user.getEarningData().earnings);
|
||||
// } else {
|
||||
// Player another = Bukkit.getPlayer(split[2]);
|
||||
// if (another == null) {
|
||||
// return "";
|
||||
// }
|
||||
//
|
||||
// OnlineUserData user = plugin.getStorageManager().getOnlineUser(another.getUniqueId());
|
||||
// if (user == null)
|
||||
// return "";
|
||||
// return String.format("%.2f", plugin.getMarketManager().earningLimit(another) - user.getEarningData().earnings);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
//}
|
||||
|
||||
@@ -1,112 +1,112 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customfishing.bukkit.integration.papi;
|
||||
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class StatisticsPapi extends PlaceholderExpansion {
|
||||
|
||||
private final BukkitCustomFishingPlugin plugin;
|
||||
|
||||
public StatisticsPapi(BukkitCustomFishingPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void load() {
|
||||
super.register();
|
||||
}
|
||||
|
||||
public void unload() {
|
||||
super.unregister();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getIdentifier() {
|
||||
return "fishingstats";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getAuthor() {
|
||||
return "XiaoMoMi";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getVersion() {
|
||||
return "2.0";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean persist() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String onRequest(OfflinePlayer player, @NotNull String params) {
|
||||
OnlineUserData onlineUser = plugin.getStorageManager().getOnlineUser(player.getUniqueId());
|
||||
if (onlineUser == null) return "Data not loaded";
|
||||
Statistics statistics = onlineUser.getStatistics();
|
||||
String[] split = params.split("_", 2);
|
||||
switch (split[0]) {
|
||||
case "total" -> {
|
||||
return String.valueOf(statistics.getTotalCatchAmount());
|
||||
}
|
||||
case "hascaught" -> {
|
||||
if (split.length == 1) return "Invalid format";
|
||||
return String.valueOf(statistics.getLootAmount(split[1]) != 0);
|
||||
}
|
||||
case "amount" -> {
|
||||
if (split.length == 1) return "Invalid format";
|
||||
return String.valueOf(statistics.getLootAmount(split[1]));
|
||||
}
|
||||
case "size-record" -> {
|
||||
return String.format("%.2f", statistics.getSizeRecord(split[1]));
|
||||
}
|
||||
case "category" -> {
|
||||
if (split.length == 1) return "Invalid format";
|
||||
String[] categorySplit = split[1].split("_", 2);
|
||||
if (categorySplit.length == 1) return "Invalid format";
|
||||
List<String> category = plugin.getStatisticsManager().getCategory(categorySplit[1]);
|
||||
if (category == null) return "Category Not Exists";
|
||||
if (categorySplit[0].equals("total")) {
|
||||
int total = 0;
|
||||
for (String loot : category) {
|
||||
total += statistics.getLootAmount(loot);
|
||||
}
|
||||
return String.valueOf(total);
|
||||
} else if (categorySplit[0].equals("progress")) {
|
||||
int size = category.size();
|
||||
int unlocked = 0;
|
||||
for (String loot : category) {
|
||||
if (statistics.getLootAmount(loot) != 0) unlocked++;
|
||||
}
|
||||
double percent = ((double) unlocked * 100) / size;
|
||||
String progress = String.format("%.1f", percent);
|
||||
return progress.equals("100.0") ? "100" : progress;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "null";
|
||||
}
|
||||
}
|
||||
///*
|
||||
// * Copyright (C) <2022> <XiaoMoMi>
|
||||
// *
|
||||
// * This program is free software: you can redistribute it and/or modify
|
||||
// * it under the terms of the GNU General Public License as published by
|
||||
// * the Free Software Foundation, either version 3 of the License, or
|
||||
// * any later version.
|
||||
// *
|
||||
// * This program is distributed in the hope that it will be useful,
|
||||
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// * GNU General Public License for more details.
|
||||
// *
|
||||
// * You should have received a copy of the GNU General Public License
|
||||
// * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// */
|
||||
//
|
||||
//package net.momirealms.customfishing.bukkit.integration.papi;
|
||||
//
|
||||
//import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
//import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
//import org.bukkit.OfflinePlayer;
|
||||
//import org.jetbrains.annotations.NotNull;
|
||||
//import org.jetbrains.annotations.Nullable;
|
||||
//
|
||||
//import java.util.List;
|
||||
//
|
||||
//public class StatisticsPapi extends PlaceholderExpansion {
|
||||
//
|
||||
// private final BukkitCustomFishingPlugin plugin;
|
||||
//
|
||||
// public StatisticsPapi(BukkitCustomFishingPlugin plugin) {
|
||||
// this.plugin = plugin;
|
||||
// }
|
||||
//
|
||||
// public void load() {
|
||||
// super.register();
|
||||
// }
|
||||
//
|
||||
// public void unload() {
|
||||
// super.unregister();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public @NotNull String getIdentifier() {
|
||||
// return "fishingstats";
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public @NotNull String getAuthor() {
|
||||
// return "XiaoMoMi";
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public @NotNull String getVersion() {
|
||||
// return "2.0";
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean persist() {
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public @Nullable String onRequest(OfflinePlayer player, @NotNull String params) {
|
||||
// OnlineUserData onlineUser = plugin.getStorageManager().getOnlineUser(player.getUniqueId());
|
||||
// if (onlineUser == null) return "Data not loaded";
|
||||
// Statistics statistics = onlineUser.getStatistics();
|
||||
// String[] split = params.split("_", 2);
|
||||
// switch (split[0]) {
|
||||
// case "total" -> {
|
||||
// return String.valueOf(statistics.getTotalCatchAmount());
|
||||
// }
|
||||
// case "hascaught" -> {
|
||||
// if (split.length == 1) return "Invalid format";
|
||||
// return String.valueOf(statistics.getLootAmount(split[1]) != 0);
|
||||
// }
|
||||
// case "amount" -> {
|
||||
// if (split.length == 1) return "Invalid format";
|
||||
// return String.valueOf(statistics.getLootAmount(split[1]));
|
||||
// }
|
||||
// case "size-record" -> {
|
||||
// return String.format("%.2f", statistics.getSizeRecord(split[1]));
|
||||
// }
|
||||
// case "category" -> {
|
||||
// if (split.length == 1) return "Invalid format";
|
||||
// String[] categorySplit = split[1].split("_", 2);
|
||||
// if (categorySplit.length == 1) return "Invalid format";
|
||||
// List<String> category = plugin.getStatisticsManager().getCategory(categorySplit[1]);
|
||||
// if (category == null) return "Category Not Exists";
|
||||
// if (categorySplit[0].equals("total")) {
|
||||
// int total = 0;
|
||||
// for (String loot : category) {
|
||||
// total += statistics.getLootAmount(loot);
|
||||
// }
|
||||
// return String.valueOf(total);
|
||||
// } else if (categorySplit[0].equals("progress")) {
|
||||
// int size = category.size();
|
||||
// int unlocked = 0;
|
||||
// for (String loot : category) {
|
||||
// if (statistics.getLootAmount(loot) != 0) unlocked++;
|
||||
// }
|
||||
// double percent = ((double) unlocked * 100) / size;
|
||||
// String progress = String.format("%.1f", percent);
|
||||
// return progress.equals("100.0") ? "100" : progress;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return "null";
|
||||
// }
|
||||
//}
|
||||
|
||||
@@ -47,6 +47,8 @@ dependencies {
|
||||
compileOnly("org.incendo:cloud-core:${rootProject.properties["cloud_core_version"]}")
|
||||
compileOnly("org.incendo:cloud-minecraft-extras:${rootProject.properties["cloud_minecraft_extras_version"]}")
|
||||
compileOnly("org.incendo:cloud-paper:${rootProject.properties["cloud_paper_version"]}")
|
||||
// expression
|
||||
compileOnly("net.objecthunter:exp4j:${rootProject.properties["exp4j_version"]}")
|
||||
}
|
||||
|
||||
tasks {
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
package net.momirealms.customfishing.bukkit;
|
||||
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import net.momirealms.customfishing.api.mechanic.config.ConfigManager;
|
||||
import net.momirealms.customfishing.api.mechanic.misc.cooldown.CoolDownManager;
|
||||
import net.momirealms.customfishing.api.mechanic.misc.placeholder.BukkitPlaceholderManager;
|
||||
import net.momirealms.customfishing.bukkit.action.BukkitActionManager;
|
||||
import net.momirealms.customfishing.bukkit.bag.BukkitBagManager;
|
||||
import net.momirealms.customfishing.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.customfishing.bukkit.competition.BukkitCompetitionManager;
|
||||
import net.momirealms.customfishing.bukkit.config.BukkitConfigManager;
|
||||
import net.momirealms.customfishing.bukkit.effect.BukkitEffectManager;
|
||||
import net.momirealms.customfishing.bukkit.entity.BukkitEntityManager;
|
||||
import net.momirealms.customfishing.bukkit.event.BukkitEventManager;
|
||||
import net.momirealms.customfishing.bukkit.hook.BukkitHookManager;
|
||||
import net.momirealms.customfishing.bukkit.integration.BukkitIntegrationManager;
|
||||
import net.momirealms.customfishing.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.customfishing.bukkit.loot.BukkitLootManager;
|
||||
import net.momirealms.customfishing.bukkit.market.BukkitMarketManager;
|
||||
import net.momirealms.customfishing.bukkit.requirement.BukkitRequirementManager;
|
||||
import net.momirealms.customfishing.bukkit.sender.BukkitSenderFactory;
|
||||
import net.momirealms.customfishing.bukkit.statistic.BukkitStatisticsManager;
|
||||
import net.momirealms.customfishing.bukkit.storage.BukkitStorageManager;
|
||||
import net.momirealms.customfishing.common.dependency.Dependency;
|
||||
import net.momirealms.customfishing.common.dependency.DependencyManagerImpl;
|
||||
import net.momirealms.customfishing.common.helper.VersionHelper;
|
||||
import net.momirealms.customfishing.common.locale.TranslationManager;
|
||||
import net.momirealms.customfishing.common.plugin.classpath.ClassPathAppender;
|
||||
import net.momirealms.customfishing.common.plugin.classpath.ReflectionClassPathAppender;
|
||||
import net.momirealms.customfishing.common.plugin.logging.JavaPluginLogger;
|
||||
import net.momirealms.customfishing.common.plugin.logging.PluginLogger;
|
||||
import org.bstats.bukkit.Metrics;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
public class BukkitCustomFishingPluginImpl extends BukkitCustomFishingPlugin {
|
||||
|
||||
private final ClassPathAppender classPathAppender;
|
||||
private final PluginLogger logger;
|
||||
|
||||
public BukkitCustomFishingPluginImpl(Plugin boostrap) {
|
||||
super(boostrap);
|
||||
VersionHelper.init(getServerVersion());
|
||||
this.classPathAppender = new ReflectionClassPathAppender(this);
|
||||
this.logger = new JavaPluginLogger(getBoostrap().getLogger());
|
||||
this.eventManager = new BukkitEventManager(this);
|
||||
this.configManager = new BukkitConfigManager(this);
|
||||
this.requirementManager = new BukkitRequirementManager(this);
|
||||
this.actionManager = new BukkitActionManager(this);
|
||||
this.senderFactory = new BukkitSenderFactory(this);
|
||||
this.placeholderManager = new BukkitPlaceholderManager(this);
|
||||
this.itemManager = new BukkitItemManager(this);
|
||||
this.integrationManager = new BukkitIntegrationManager(this);
|
||||
this.competitionManager = new BukkitCompetitionManager(this);
|
||||
this.marketManager = new BukkitMarketManager(this);
|
||||
this.storageManager = new BukkitStorageManager(this);
|
||||
this.lootManager = new BukkitLootManager(this);
|
||||
this.coolDownManager = new CoolDownManager(this);
|
||||
this.entityManager = new BukkitEntityManager(this);
|
||||
this.blockManager = new BukkitBlockManager(this);
|
||||
this.statisticsManager = new BukkitStatisticsManager(this);
|
||||
this.effectManager = new BukkitEffectManager(this);
|
||||
this.hookManager = new BukkitHookManager(this);
|
||||
this.bagManager = new BukkitBagManager(this);
|
||||
this.dependencyManager = new DependencyManagerImpl(this);
|
||||
this.translationManager = new TranslationManager(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
this.dependencyManager.loadDependencies(
|
||||
List.of(Dependency.BOOSTED_YAML,
|
||||
Dependency.BSTATS_BASE,
|
||||
Dependency.BSTATS_BUKKIT,
|
||||
Dependency.CAFFEINE,
|
||||
Dependency.CLOUD_CORE,
|
||||
Dependency.CLOUD_SERVICES,
|
||||
Dependency.CLOUD_BUKKIT,
|
||||
Dependency.CLOUD_PAPER,
|
||||
Dependency.CLOUD_BRIGADIER,
|
||||
Dependency.CLOUD_MINECRAFT_EXTRAS,
|
||||
Dependency.GSON,
|
||||
Dependency.COMMONS_POOL_2,
|
||||
Dependency.JEDIS,
|
||||
Dependency.EXP4J,
|
||||
Dependency.MYSQL_DRIVER,
|
||||
Dependency.MARIADB_DRIVER,
|
||||
Dependency.SQLITE_DRIVER,
|
||||
Dependency.H2_DRIVER,
|
||||
Dependency.MONGODB_DRIVER_CORE,
|
||||
Dependency.MONGODB_DRIVER_SYNC,
|
||||
Dependency.MONGODB_DRIVER_BSON,
|
||||
Dependency.HIKARI_CP)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
this.reload();
|
||||
if (ConfigManager.metrics()) new Metrics((JavaPlugin) getBoostrap(), 16648);
|
||||
if (ConfigManager.checkUpdate()) {
|
||||
VersionHelper.UPDATE_CHECKER.apply(this).thenAccept(result -> {
|
||||
if (!result) this.getPluginLogger().info("You are using the latest version.");
|
||||
else this.getPluginLogger().warn("Update is available: https://polymart.org/resource/2723");
|
||||
});
|
||||
}
|
||||
this.integrationManager.load();
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
this.eventManager.reload();
|
||||
this.configManager.reload();
|
||||
this.requirementManager.reload();
|
||||
this.actionManager.reload();
|
||||
this.placeholderManager.reload();
|
||||
this.itemManager.reload();
|
||||
this.competitionManager.reload();
|
||||
this.marketManager.reload();
|
||||
this.storageManager.reload();
|
||||
this.lootManager.reload();
|
||||
this.coolDownManager.reload();
|
||||
this.entityManager.reload();
|
||||
this.blockManager.reload();
|
||||
this.statisticsManager.reload();
|
||||
this.effectManager.reload();
|
||||
this.hookManager.reload();
|
||||
this.bagManager.reload();
|
||||
this.translationManager.reload();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
this.eventManager.disable();
|
||||
this.configManager.disable();
|
||||
this.requirementManager.disable();
|
||||
this.actionManager.disable();
|
||||
this.placeholderManager.disable();
|
||||
this.itemManager.disable();
|
||||
this.competitionManager.disable();
|
||||
this.marketManager.disable();
|
||||
this.storageManager.disable();
|
||||
this.lootManager.disable();
|
||||
this.coolDownManager.disable();
|
||||
this.entityManager.disable();
|
||||
this.blockManager.disable();
|
||||
this.statisticsManager.disable();
|
||||
this.effectManager.disable();
|
||||
this.hookManager.disable();
|
||||
this.bagManager.disable();
|
||||
this.integrationManager.disable();
|
||||
this.initialized = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getResourceStream(String filePath) {
|
||||
return getBoostrap().getResource(filePath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginLogger getPluginLogger() {
|
||||
return logger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassPathAppender getClassPathAppender() {
|
||||
return classPathAppender;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getDataDirectory() {
|
||||
return getBoostrap().getDataFolder().toPath().toAbsolutePath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerVersion() {
|
||||
return Bukkit.getServer().getBukkitVersion().split("-")[0];
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public String getPluginVersion() {
|
||||
return getBoostrap().getDescription().getVersion();
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,6 @@ import net.momirealms.customfishing.api.mechanic.misc.value.MathValue;
|
||||
import net.momirealms.customfishing.api.mechanic.misc.value.TextValue;
|
||||
import net.momirealms.customfishing.api.mechanic.requirement.Requirement;
|
||||
import net.momirealms.customfishing.bukkit.integration.VaultHook;
|
||||
import net.momirealms.customfishing.bukkit.util.ItemUtils;
|
||||
import net.momirealms.customfishing.bukkit.util.LocationUtils;
|
||||
import net.momirealms.customfishing.bukkit.util.PlayerUtils;
|
||||
import net.momirealms.customfishing.common.helper.AdventureHelper;
|
||||
@@ -52,6 +51,16 @@ public class BukkitActionManager implements ActionManager<Player> {
|
||||
public BukkitActionManager(BukkitCustomFishingPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.registerBuiltInActions();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
this.actionFactoryMap.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
this.loadExpansions();
|
||||
}
|
||||
|
||||
@@ -393,11 +402,11 @@ public class BukkitActionManager implements ActionManager<Player> {
|
||||
if (Math.random() > chance) return;
|
||||
Player player = context.getHolder();
|
||||
ItemStack itemStack = player.getInventory().getItem(slot);
|
||||
if (amount > 0) {
|
||||
ItemUtils.increaseDurability(itemStack, amount, true);
|
||||
} else {
|
||||
ItemUtils.decreaseDurability(context.getHolder(), itemStack, -amount, true);
|
||||
}
|
||||
// if (amount > 0) {
|
||||
// ItemUtils.increaseDurability(itemStack, amount, true);
|
||||
// } else {
|
||||
// ItemUtils.decreaseDurability(context.getHolder(), itemStack, -amount, true);
|
||||
// }
|
||||
};
|
||||
} else {
|
||||
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at durability action which should be Section");
|
||||
|
||||
@@ -65,7 +65,7 @@ public class BukkitBlockManager implements BlockManager, Listener {
|
||||
private final HashMap<String, BlockStateModifierFactory> stateFactories = new HashMap<>();
|
||||
private BlockProvider[] blockDetectArray;
|
||||
|
||||
public BukkitBlockManager(BukkitCustomFishingPluginImpl plugin) {
|
||||
public BukkitBlockManager(BukkitCustomFishingPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.registerInbuiltProperties();
|
||||
this.registerBlockProvider(new BlockProvider() {
|
||||
@@ -88,13 +88,6 @@ public class BukkitBlockManager implements BlockManager, Listener {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerBlock(@NotNull String id, @NotNull BlockConfig block) {
|
||||
if (blocks.containsKey(id)) return false;
|
||||
blocks.put(id, block);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin.getBoostrap());
|
||||
@@ -122,6 +115,13 @@ public class BukkitBlockManager implements BlockManager, Listener {
|
||||
this.blockDetectArray = list.toArray(new BlockProvider[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerBlock(@NotNull BlockConfig block) {
|
||||
if (blocks.containsKey(block.id())) return false;
|
||||
blocks.put(block.id(), block);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Event handler for the EntityChangeBlockEvent.
|
||||
* This method is triggered when an entity changes a block, typically when a block falls or lands.
|
||||
@@ -230,8 +230,8 @@ public class BukkitBlockManager implements BlockManager, Listener {
|
||||
PersistentDataType.STRING,
|
||||
id + ";" + context.getHolder().getName()
|
||||
);
|
||||
Vector vector = playerLocation.subtract(hookLocation).toVector().multiply((config.horizontalVector().evaluate(context)) - 1);
|
||||
vector = vector.setY((vector.getY() + 0.2) * config.verticalVector().evaluate(context));
|
||||
Vector vector = playerLocation.subtract(hookLocation).toVector().multiply(1.2 - 1);
|
||||
vector = vector.setY((vector.getY() + 0.2) * 1.2);
|
||||
fallingBlock.setVelocity(vector);
|
||||
return fallingBlock;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ public class ReloadCommand extends BukkitCommandFeature<CommandSender> {
|
||||
.flag(manager.flagBuilder("silent"))
|
||||
.handler(context -> {
|
||||
BukkitCustomFishingPlugin.getInstance().reload();
|
||||
handleFeedback(context.sender(), MessageConstants.COMMAND_RELOAD);
|
||||
handleFeedback(context.sender(), MessageConstants.COMMAND_RELOAD_SUCCESS);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -27,9 +27,9 @@ import java.util.*;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public class BukkitConfigLoader extends ConfigManager {
|
||||
public class BukkitConfigManager extends ConfigManager {
|
||||
|
||||
public BukkitConfigLoader(BukkitCustomFishingPlugin plugin) {
|
||||
public BukkitConfigManager(BukkitCustomFishingPlugin plugin) {
|
||||
super(plugin);
|
||||
this.registerBuiltInItemProperties();
|
||||
this.registerBuiltInBaseEffectParser();
|
||||
@@ -438,4 +438,11 @@ public class BukkitConfigLoader extends ConfigManager {
|
||||
return builder -> builder.statisticsKeys(keys);
|
||||
}, "statistics");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveResource(String filePath) {
|
||||
if (!new File(plugin.getDataFolder(), filePath).exists()) {
|
||||
plugin.getBoostrap().saveResource(filePath, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,9 +76,9 @@ public class BukkitEntityManager implements EntityManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerEntity(String id, EntityConfig entity) {
|
||||
if (entities.containsKey(id)) return false;
|
||||
this.entities.put(id, entity);
|
||||
public boolean registerEntity(EntityConfig entity) {
|
||||
if (entities.containsKey(entity.id())) return false;
|
||||
this.entities.put(entity.id(), entity);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -99,17 +99,17 @@ public class BukkitEntityManager implements EntityManager {
|
||||
EntityConfig config = requireNonNull(entities.get(id), "Entity " + id + " not found");
|
||||
Location hookLocation = requireNonNull(context.arg(ContextKeys.HOOK_LOCATION));
|
||||
Location playerLocation = requireNonNull(context.getHolder().getLocation());
|
||||
String entityID = config.getEntityID();
|
||||
String entityID = config.entityID();
|
||||
Entity entity;
|
||||
if (entityID.contains(":")) {
|
||||
String[] split = entityID.split(":", 2);
|
||||
EntityProvider provider = requireNonNull(entityProviders.get(split[0]), "EntityProvider " + split[0] + " doesn't exist");
|
||||
entity = requireNonNull(provider.spawn(hookLocation, split[1], config.getPropertyMap()), "Entity " + entityID + " doesn't exist");
|
||||
entity = requireNonNull(provider.spawn(hookLocation, split[1], config.propertyMap()), "Entity " + entityID + " doesn't exist");
|
||||
} else {
|
||||
entity = entityProviders.get("vanilla").spawn(hookLocation, entityID, config.getPropertyMap());
|
||||
entity = entityProviders.get("vanilla").spawn(hookLocation, entityID, config.propertyMap());
|
||||
}
|
||||
Vector vector = playerLocation.subtract(hookLocation).toVector().multiply((config.getHorizontalVector()) - 1);
|
||||
vector = vector.setY((vector.getY() + 0.2) * config.getVerticalVector());
|
||||
Vector vector = playerLocation.subtract(hookLocation).toVector().multiply(config.horizontalVector().evaluate(context) - 1);
|
||||
vector = vector.setY((vector.getY() + 0.2) * config.verticalVector().evaluate(context));
|
||||
entity.setVelocity(vector);
|
||||
return entity;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,9 @@ package net.momirealms.customfishing.bukkit.gui.icon;
|
||||
import net.momirealms.customfishing.bukkit.adventure.ShadedAdventureComponentWrapper;
|
||||
import net.momirealms.customfishing.bukkit.gui.Icon;
|
||||
import net.momirealms.customfishing.bukkit.gui.page.file.FileSelector;
|
||||
import net.momirealms.customfishing.common.helper.AdventureHelper;
|
||||
import net.momirealms.customfishing.common.locale.MessageConstants;
|
||||
import net.momirealms.customfishing.common.locale.TranslationManager;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
@@ -44,10 +47,8 @@ public class BackToFolderItem extends AbstractItem implements Icon {
|
||||
public ItemProvider getItemProvider() {
|
||||
if (file != null && (file.getPath().startsWith("plugins\\CustomFishing\\contents") || file.getPath().startsWith("plugins/CustomFishing/contents"))) {
|
||||
return new ItemBuilder(Material.ORANGE_STAINED_GLASS_PANE)
|
||||
.setDisplayName(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
CFLocale.GUI_BACK_TO_PARENT_FOLDER
|
||||
)))
|
||||
.setLore(List.of(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
.setDisplayName(new ShadedAdventureComponentWrapper(TranslationManager.render(MessageConstants.GUI_BACK_TO_PARENT_FOLDER.build())))
|
||||
.setLore(List.of(new ShadedAdventureComponentWrapper(AdventureHelper.miniMessage(
|
||||
"<#FFA500>-> " + file.getName()
|
||||
))));
|
||||
} else {
|
||||
|
||||
@@ -19,6 +19,8 @@ package net.momirealms.customfishing.bukkit.gui.icon;
|
||||
|
||||
import net.momirealms.customfishing.bukkit.adventure.ShadedAdventureComponentWrapper;
|
||||
import net.momirealms.customfishing.bukkit.gui.ParentPage;
|
||||
import net.momirealms.customfishing.common.locale.MessageConstants;
|
||||
import net.momirealms.customfishing.common.locale.TranslationManager;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
@@ -39,9 +41,7 @@ public class BackToPageItem extends AbstractItem {
|
||||
@Override
|
||||
public ItemProvider getItemProvider() {
|
||||
return new ItemBuilder(Material.ORANGE_STAINED_GLASS_PANE)
|
||||
.setDisplayName(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
CFLocale.GUI_BACK_TO_PARENT_PAGE
|
||||
)));
|
||||
.setDisplayName(new ShadedAdventureComponentWrapper(TranslationManager.render(MessageConstants.GUI_BACK_TO_PARENT_PAGE.build())));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -17,8 +17,11 @@
|
||||
|
||||
package net.momirealms.customfishing.bukkit.gui.icon;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.customfishing.bukkit.adventure.ShadedAdventureComponentWrapper;
|
||||
import net.momirealms.customfishing.bukkit.gui.Icon;
|
||||
import net.momirealms.customfishing.common.locale.MessageConstants;
|
||||
import net.momirealms.customfishing.common.locale.TranslationManager;
|
||||
import org.bukkit.Material;
|
||||
import xyz.xenondevs.invui.gui.PagedGui;
|
||||
import xyz.xenondevs.invui.item.ItemProvider;
|
||||
@@ -34,15 +37,13 @@ public class NextPageItem extends PageItem implements Icon {
|
||||
@Override
|
||||
public ItemProvider getItemProvider(PagedGui<?> gui) {
|
||||
ItemBuilder builder = new ItemBuilder(Material.GREEN_STAINED_GLASS_PANE);
|
||||
builder.setDisplayName(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
CFLocale.GUI_NEXT_PAGE
|
||||
)))
|
||||
.addLoreLines(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
gui.hasNextPage()
|
||||
? CFLocale.GUI_GOTO_NEXT_PAGE
|
||||
.replace("{0}", String.valueOf(gui.getCurrentPage() + 2))
|
||||
.replace("{1}", String.valueOf(gui.getPageAmount()))
|
||||
: CFLocale.GUI_CANNOT_GOTO_NEXT_PAGE
|
||||
builder.setDisplayName(new ShadedAdventureComponentWrapper(TranslationManager.render(MessageConstants.GUI_NEXT_PAGE.build())))
|
||||
.addLoreLines(new ShadedAdventureComponentWrapper(TranslationManager.render( gui.hasNextPage()
|
||||
? MessageConstants.GUI_GOTO_NEXT_PAGE.arguments(
|
||||
Component.text(gui.getCurrentPage() + 2),
|
||||
Component.text(gui.getPageAmount())
|
||||
).build() :
|
||||
MessageConstants.GUI_CANNOT_GOTO_NEXT_PAGE.build()
|
||||
)));
|
||||
return builder;
|
||||
}
|
||||
|
||||
@@ -17,8 +17,11 @@
|
||||
|
||||
package net.momirealms.customfishing.bukkit.gui.icon;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.customfishing.bukkit.adventure.ShadedAdventureComponentWrapper;
|
||||
import net.momirealms.customfishing.bukkit.gui.Icon;
|
||||
import net.momirealms.customfishing.common.locale.MessageConstants;
|
||||
import net.momirealms.customfishing.common.locale.TranslationManager;
|
||||
import org.bukkit.Material;
|
||||
import xyz.xenondevs.invui.gui.PagedGui;
|
||||
import xyz.xenondevs.invui.item.ItemProvider;
|
||||
@@ -34,16 +37,13 @@ public class PreviousPageItem extends PageItem implements Icon {
|
||||
@Override
|
||||
public ItemProvider getItemProvider(PagedGui<?> gui) {
|
||||
ItemBuilder builder = new ItemBuilder(Material.RED_STAINED_GLASS_PANE);
|
||||
builder.setDisplayName(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
CFLocale.GUI_PREVIOUS_PAGE
|
||||
)))
|
||||
.addLoreLines(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
gui.hasPreviousPage()
|
||||
? CFLocale.GUI_GOTO_PREVIOUS_PAGE
|
||||
.replace("{0}", String.valueOf(gui.getCurrentPage()))
|
||||
.replace("{1}", String.valueOf(gui.getPageAmount()))
|
||||
: CFLocale.GUI_CANNOT_GOTO_PREVIOUS_PAGE
|
||||
)));
|
||||
builder.setDisplayName(new ShadedAdventureComponentWrapper(TranslationManager.render(MessageConstants.GUI_PREVIOUS_PAGE.build())))
|
||||
.addLoreLines(new ShadedAdventureComponentWrapper(TranslationManager.render( gui.hasPreviousPage()
|
||||
? MessageConstants.GUI_GOTO_PREVIOUS_PAGE.arguments(
|
||||
Component.text(gui.getCurrentPage()),
|
||||
Component.text(gui.getPageAmount())
|
||||
).build()
|
||||
: MessageConstants.GUI_CANNOT_GOTO_PREVIOUS_PAGE.build())));
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,9 +17,12 @@
|
||||
|
||||
package net.momirealms.customfishing.bukkit.gui.icon.property.item;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.customfishing.bukkit.adventure.ShadedAdventureComponentWrapper;
|
||||
import net.momirealms.customfishing.bukkit.gui.SectionPage;
|
||||
import net.momirealms.customfishing.bukkit.gui.page.property.AmountEditor;
|
||||
import net.momirealms.customfishing.common.locale.MessageConstants;
|
||||
import net.momirealms.customfishing.common.locale.TranslationManager;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
@@ -40,24 +43,19 @@ public class AmountItem extends AbstractItem {
|
||||
@Override
|
||||
public ItemProvider getItemProvider() {
|
||||
ItemBuilder itemBuilder = new ItemBuilder(Material.IRON_NUGGET)
|
||||
.setDisplayName(new ShadedAdventureComponentWrapper(AdventureHelper.getComponentFromMiniMessage(
|
||||
CFLocale.GUI_ITEM_AMOUNT
|
||||
)))
|
||||
.setDisplayName(new ShadedAdventureComponentWrapper(TranslationManager.render(MessageConstants.GUI_ITEM_AMOUNT.build())))
|
||||
.setAmount(itemPage.getSection().getInt("amount", 1));
|
||||
if (itemPage.getSection().contains("amount")) {
|
||||
itemBuilder.addLoreLines(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
CFLocale.GUI_CURRENT_VALUE + itemPage.getSection().getInt("amount")
|
||||
itemBuilder.addLoreLines(new ShadedAdventureComponentWrapper(TranslationManager.render(
|
||||
MessageConstants.GUI_CURRENT_VALUE.arguments(
|
||||
Component.text(itemPage.getSection().getInt("amount"))
|
||||
).build()
|
||||
)))
|
||||
.addLoreLines("");
|
||||
itemBuilder.addLoreLines(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
CFLocale.GUI_LEFT_CLICK_EDIT
|
||||
))).addLoreLines(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
CFLocale.GUI_RIGHT_CLICK_RESET
|
||||
)));
|
||||
itemBuilder.addLoreLines(new ShadedAdventureComponentWrapper(TranslationManager.render(MessageConstants.GUI_LEFT_CLICK_EDIT.build())))
|
||||
.addLoreLines(new ShadedAdventureComponentWrapper(TranslationManager.render(MessageConstants.GUI_RIGHT_CLICK_RESET.build())));
|
||||
} else {
|
||||
itemBuilder.addLoreLines(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
CFLocale.GUI_LEFT_CLICK_EDIT
|
||||
)));
|
||||
itemBuilder.addLoreLines(new ShadedAdventureComponentWrapper(TranslationManager.render(MessageConstants.GUI_LEFT_CLICK_EDIT.build())));
|
||||
}
|
||||
return itemBuilder;
|
||||
}
|
||||
|
||||
@@ -17,9 +17,12 @@
|
||||
|
||||
package net.momirealms.customfishing.bukkit.gui.icon.property.item;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.customfishing.bukkit.adventure.ShadedAdventureComponentWrapper;
|
||||
import net.momirealms.customfishing.bukkit.gui.SectionPage;
|
||||
import net.momirealms.customfishing.bukkit.gui.page.property.CustomModelDataEditor;
|
||||
import net.momirealms.customfishing.common.locale.MessageConstants;
|
||||
import net.momirealms.customfishing.common.locale.TranslationManager;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
@@ -40,23 +43,20 @@ public class CMDItem extends AbstractItem {
|
||||
@Override
|
||||
public ItemProvider getItemProvider() {
|
||||
ItemBuilder itemBuilder = new ItemBuilder(Material.GLOW_INK_SAC)
|
||||
.setDisplayName(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
CFLocale.GUI_ITEM_MODEL_DATA
|
||||
.setDisplayName(new ShadedAdventureComponentWrapper(TranslationManager.render(
|
||||
MessageConstants.GUI_ITEM_CUSTOM_MODEL_DATA.build()
|
||||
)));
|
||||
if (itemPage.getSection().contains("custom-model-data")) {
|
||||
itemBuilder.addLoreLines(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
CFLocale.GUI_CURRENT_VALUE + itemPage.getSection().getInt("custom-model-data")
|
||||
itemBuilder.addLoreLines(new ShadedAdventureComponentWrapper(TranslationManager.render(
|
||||
MessageConstants.GUI_CURRENT_VALUE.arguments(
|
||||
Component.text(itemPage.getSection().getInt("custom-model-data"))
|
||||
).build()
|
||||
)))
|
||||
.addLoreLines("");
|
||||
itemBuilder.addLoreLines(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
CFLocale.GUI_LEFT_CLICK_EDIT
|
||||
))).addLoreLines(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
CFLocale.GUI_RIGHT_CLICK_RESET
|
||||
)));
|
||||
itemBuilder.addLoreLines(new ShadedAdventureComponentWrapper(TranslationManager.render(MessageConstants.GUI_LEFT_CLICK_EDIT.build())))
|
||||
.addLoreLines(new ShadedAdventureComponentWrapper(TranslationManager.render(MessageConstants.GUI_RIGHT_CLICK_RESET.build())));
|
||||
} else {
|
||||
itemBuilder.addLoreLines(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
CFLocale.GUI_LEFT_CLICK_EDIT
|
||||
)));
|
||||
itemBuilder.addLoreLines(new ShadedAdventureComponentWrapper(TranslationManager.render(MessageConstants.GUI_LEFT_CLICK_EDIT.build())));
|
||||
}
|
||||
return itemBuilder;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ package net.momirealms.customfishing.bukkit.gui.icon.property.item;
|
||||
import net.momirealms.customfishing.bukkit.adventure.ShadedAdventureComponentWrapper;
|
||||
import net.momirealms.customfishing.bukkit.gui.SectionPage;
|
||||
import net.momirealms.customfishing.bukkit.gui.page.property.NBTEditor;
|
||||
import net.momirealms.customfishing.bukkit.util.ConfigUtils;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
|
||||
@@ -23,6 +23,8 @@ import net.momirealms.customfishing.bukkit.gui.icon.BackToFolderItem;
|
||||
import net.momirealms.customfishing.bukkit.gui.icon.ScrollDownItem;
|
||||
import net.momirealms.customfishing.bukkit.gui.icon.ScrollUpItem;
|
||||
import net.momirealms.customfishing.bukkit.gui.page.item.ItemSelector;
|
||||
import net.momirealms.customfishing.common.locale.MessageConstants;
|
||||
import net.momirealms.customfishing.common.locale.TranslationManager;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
@@ -79,19 +81,10 @@ public class FileSelector {
|
||||
|
||||
Window window = Window.single()
|
||||
.setViewer(player)
|
||||
.setTitle(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
CFLocale.GUI_SELECT_FILE
|
||||
)))
|
||||
.setTitle(new ShadedAdventureComponentWrapper(TranslationManager.render(MessageConstants.GUI_SELECT_FILE.build())))
|
||||
.setGui(gui)
|
||||
.build();
|
||||
|
||||
// gui.playAnimation(new SequentialAnimation(1, true), slotElement -> {
|
||||
// if (slotElement instanceof SlotElement.ItemSlotElement itemSlotElement) {
|
||||
// return !(itemSlotElement.getItem() instanceof Icon);
|
||||
// }
|
||||
// return true;
|
||||
// });
|
||||
|
||||
window.open();
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ package net.momirealms.customfishing.bukkit.gui.page.property;
|
||||
import net.momirealms.customfishing.bukkit.adventure.ShadedAdventureComponentWrapper;
|
||||
import net.momirealms.customfishing.bukkit.gui.SectionPage;
|
||||
import net.momirealms.customfishing.bukkit.gui.icon.BackGroundItem;
|
||||
import net.momirealms.customfishing.bukkit.util.ConfigUtils;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package net.momirealms.customfishing.bukkit.hook;
|
||||
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import net.momirealms.customfishing.api.mechanic.hook.HookConfig;
|
||||
import net.momirealms.customfishing.api.mechanic.hook.HookManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class BukkitHookManager implements HookManager {
|
||||
|
||||
private BukkitCustomFishingPlugin plugin;
|
||||
|
||||
public BukkitHookManager(BukkitCustomFishingPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerHook(HookConfig hook) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Optional<HookConfig> getHook(String id) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,6 @@ import net.momirealms.customfishing.api.mechanic.context.Context;
|
||||
import net.momirealms.customfishing.api.mechanic.context.ContextKeys;
|
||||
import net.momirealms.customfishing.api.mechanic.item.CustomFishingItem;
|
||||
import net.momirealms.customfishing.api.mechanic.item.ItemManager;
|
||||
import net.momirealms.customfishing.bukkit.util.ItemUtils;
|
||||
import net.momirealms.customfishing.bukkit.util.LocationUtils;
|
||||
import net.momirealms.customfishing.common.item.Item;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
@@ -47,9 +47,18 @@ public class BukkitRequirementManager implements RequirementManager<Player> {
|
||||
public BukkitRequirementManager(BukkitCustomFishingPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.registerBuiltInRequirements();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
this.loadExpansions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
this.requirementFactoryMap.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerRequirement(@NotNull String type, @NotNull RequirementFactory<Player> requirementFactory) {
|
||||
if (this.requirementFactoryMap.containsKey(type)) return false;
|
||||
|
||||
@@ -1,63 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customfishing.bukkit.requirement;
|
||||
|
||||
import net.momirealms.customfishing.api.common.Pair;
|
||||
import net.momirealms.customfishing.api.mechanic.requirement.Requirement;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class ConditionalElement {
|
||||
|
||||
private final List<Pair<String, WeightModifier>> modifierList;
|
||||
private final HashMap<String, ConditionalElement> subLoots;
|
||||
private final Requirement[] requirements;
|
||||
|
||||
public ConditionalElement(
|
||||
Requirement[] requirements,
|
||||
List<Pair<String, WeightModifier>> modifierList,
|
||||
HashMap<String, ConditionalElement> subElements
|
||||
) {
|
||||
this.modifierList = modifierList;
|
||||
this.requirements = requirements;
|
||||
this.subLoots = subElements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines the weight modifiers for this element.
|
||||
*
|
||||
* @param player The player for whom the modifiers are applied.
|
||||
* @param weightMap The map of weight modifiers.
|
||||
*/
|
||||
synchronized public void combine(Player player, HashMap<String, Double> weightMap) {
|
||||
for (Pair<String, WeightModifier> modifierPair : this.modifierList) {
|
||||
double previous = weightMap.getOrDefault(modifierPair.left(), 0d);
|
||||
weightMap.put(modifierPair.left(), modifierPair.right().modify(player, previous));
|
||||
}
|
||||
}
|
||||
|
||||
public Requirement[] getRequirements() {
|
||||
return requirements;
|
||||
}
|
||||
|
||||
public HashMap<String, ConditionalElement> getSubElements() {
|
||||
return subLoots;
|
||||
}
|
||||
}
|
||||
///*
|
||||
// * Copyright (C) <2022> <XiaoMoMi>
|
||||
// *
|
||||
// * This program is free software: you can redistribute it and/or modify
|
||||
// * it under the terms of the GNU General Public License as published by
|
||||
// * the Free Software Foundation, either version 3 of the License, or
|
||||
// * any later version.
|
||||
// *
|
||||
// * This program is distributed in the hope that it will be useful,
|
||||
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// * GNU General Public License for more details.
|
||||
// *
|
||||
// * You should have received a copy of the GNU General Public License
|
||||
// * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// */
|
||||
//
|
||||
//package net.momirealms.customfishing.bukkit.requirement;
|
||||
//
|
||||
//import net.momirealms.customfishing.api.mechanic.requirement.Requirement;
|
||||
//import org.bukkit.entity.Player;
|
||||
//
|
||||
//import java.util.HashMap;
|
||||
//import java.util.List;
|
||||
//
|
||||
//public class ConditionalElement {
|
||||
//
|
||||
// private final List<Pair<String, WeightModifier>> modifierList;
|
||||
// private final HashMap<String, ConditionalElement> subLoots;
|
||||
// private final Requirement[] requirements;
|
||||
//
|
||||
// public ConditionalElement(
|
||||
// Requirement[] requirements,
|
||||
// List<Pair<String, WeightModifier>> modifierList,
|
||||
// HashMap<String, ConditionalElement> subElements
|
||||
// ) {
|
||||
// this.modifierList = modifierList;
|
||||
// this.requirements = requirements;
|
||||
// this.subLoots = subElements;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Combines the weight modifiers for this element.
|
||||
// *
|
||||
// * @param player The player for whom the modifiers are applied.
|
||||
// * @param weightMap The map of weight modifiers.
|
||||
// */
|
||||
// synchronized public void combine(Player player, HashMap<String, Double> weightMap) {
|
||||
// for (Pair<String, WeightModifier> modifierPair : this.modifierList) {
|
||||
// double previous = weightMap.getOrDefault(modifierPair.left(), 0d);
|
||||
// weightMap.put(modifierPair.left(), modifierPair.right().modify(player, previous));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public Requirement[] getRequirements() {
|
||||
// return requirements;
|
||||
// }
|
||||
//
|
||||
// public HashMap<String, ConditionalElement> getSubElements() {
|
||||
// return subLoots;
|
||||
// }
|
||||
//}
|
||||
|
||||
@@ -74,6 +74,7 @@ public class BukkitStorageManager implements StorageManager, Listener {
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin.getBoostrap());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
YamlDocument config = plugin.getConfigManager().loadConfig("database.yml");
|
||||
this.serverID = config.getString("unique-server-id", "default");
|
||||
@@ -132,6 +133,7 @@ public class BukkitStorageManager implements StorageManager, Listener {
|
||||
/**
|
||||
* Disables the storage manager and cleans up resources.
|
||||
*/
|
||||
@Override
|
||||
public void disable() {
|
||||
HandlerList.unregisterAll(this);
|
||||
this.dataSource.updateManyPlayersData(onlineUserMap.values(), true);
|
||||
|
||||
@@ -1,86 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customfishing.bukkit.totem;
|
||||
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import net.momirealms.customfishing.api.mechanic.action.Action;
|
||||
import net.momirealms.customfishing.api.mechanic.action.ActionTrigger;
|
||||
import net.momirealms.customfishing.api.mechanic.totem.TotemConfig;
|
||||
import net.momirealms.customfishing.api.mechanic.totem.TotemParticle;
|
||||
import net.momirealms.customfishing.api.scheduler.CancellableTask;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class ActivatedTotem {
|
||||
|
||||
private final List<CancellableTask> subTasks;
|
||||
private final Location coreLocation;
|
||||
private final TotemConfig totemConfig;
|
||||
private final long expireTime;
|
||||
private final EffectCarrier effectCarrier;
|
||||
|
||||
public ActivatedTotem(Location coreLocation, TotemConfig config) {
|
||||
this.subTasks = new ArrayList<>();
|
||||
this.expireTime = System.currentTimeMillis() + config.getDuration() * 1000L;
|
||||
this.coreLocation = coreLocation.clone().add(0.5,0,0.5);
|
||||
this.totemConfig = config;
|
||||
this.effectCarrier = BukkitCustomFishingPlugin.get().getEffectManager().getEffectCarrier("totem", config.getKey());
|
||||
for (TotemParticle particleSetting : config.getParticleSettings()) {
|
||||
this.subTasks.add(particleSetting.start(coreLocation, config.getRadius()));
|
||||
}
|
||||
}
|
||||
|
||||
public TotemConfig getTotemConfig() {
|
||||
return totemConfig;
|
||||
}
|
||||
|
||||
public Location getCoreLocation() {
|
||||
return coreLocation;
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
for (CancellableTask task : subTasks) {
|
||||
task.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
public long getExpireTime() {
|
||||
return expireTime;
|
||||
}
|
||||
|
||||
public void doTimerAction() {
|
||||
HashMap<String, String> args = new HashMap<>();
|
||||
args.put("{time_left}", String.valueOf((expireTime - System.currentTimeMillis())/1000));
|
||||
PlayerContext playerContext = new PlayerContext(coreLocation, null, args);
|
||||
if (effectCarrier != null) {
|
||||
Action[] actions = effectCarrier.getActions(ActionTrigger.TIMER);
|
||||
if (actions != null) {
|
||||
for (Action action : actions) {
|
||||
action.trigger(playerContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public EffectCarrier getEffectCarrier() {
|
||||
return effectCarrier;
|
||||
}
|
||||
}
|
||||
///*
|
||||
// * Copyright (C) <2022> <XiaoMoMi>
|
||||
// *
|
||||
// * This program is free software: you can redistribute it and/or modify
|
||||
// * it under the terms of the GNU General Public License as published by
|
||||
// * the Free Software Foundation, either version 3 of the License, or
|
||||
// * any later version.
|
||||
// *
|
||||
// * This program is distributed in the hope that it will be useful,
|
||||
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// * GNU General Public License for more details.
|
||||
// *
|
||||
// * You should have received a copy of the GNU General Public License
|
||||
// * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// */
|
||||
//
|
||||
//package net.momirealms.customfishing.bukkit.totem;
|
||||
//
|
||||
//import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
//import net.momirealms.customfishing.api.mechanic.action.Action;
|
||||
//import net.momirealms.customfishing.api.mechanic.action.ActionTrigger;
|
||||
//import net.momirealms.customfishing.api.mechanic.totem.TotemConfig;
|
||||
//import net.momirealms.customfishing.api.mechanic.totem.TotemParticle;
|
||||
//import net.momirealms.customfishing.common.plugin.scheduler.SchedulerTask;
|
||||
//import org.bukkit.Location;
|
||||
//
|
||||
//import java.util.ArrayList;
|
||||
//import java.util.HashMap;
|
||||
//import java.util.List;
|
||||
//
|
||||
//public class ActivatedTotem {
|
||||
//
|
||||
// private final List<SchedulerTask> subTasks;
|
||||
// private final Location coreLocation;
|
||||
// private final TotemConfig totemConfig;
|
||||
// private final long expireTime;
|
||||
// private final EffectCarrier effectCarrier;
|
||||
//
|
||||
// public ActivatedTotem(Location coreLocation, TotemConfig config) {
|
||||
// this.subTasks = new ArrayList<>();
|
||||
// this.expireTime = System.currentTimeMillis() + config.getDuration() * 1000L;
|
||||
// this.coreLocation = coreLocation.clone().add(0.5,0,0.5);
|
||||
// this.totemConfig = config;
|
||||
// this.effectCarrier = BukkitCustomFishingPlugin.get().getEffectManager().getEffectCarrier("totem", config.getKey());
|
||||
// for (TotemParticle particleSetting : config.getParticleSettings()) {
|
||||
// this.subTasks.add(particleSetting.start(coreLocation, config.getRadius()));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public TotemConfig getTotemConfig() {
|
||||
// return totemConfig;
|
||||
// }
|
||||
//
|
||||
// public Location getCoreLocation() {
|
||||
// return coreLocation;
|
||||
// }
|
||||
//
|
||||
// public void cancel() {
|
||||
// for (CancellableTask task : subTasks) {
|
||||
// task.cancel();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public long getExpireTime() {
|
||||
// return expireTime;
|
||||
// }
|
||||
//
|
||||
// public void doTimerAction() {
|
||||
// HashMap<String, String> args = new HashMap<>();
|
||||
// args.put("{time_left}", String.valueOf((expireTime - System.currentTimeMillis())/1000));
|
||||
// PlayerContext playerContext = new PlayerContext(coreLocation, null, args);
|
||||
// if (effectCarrier != null) {
|
||||
// Action[] actions = effectCarrier.getActions(ActionTrigger.TIMER);
|
||||
// if (actions != null) {
|
||||
// for (Action action : actions) {
|
||||
// action.trigger(playerContext);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public EffectCarrier getEffectCarrier() {
|
||||
// return effectCarrier;
|
||||
// }
|
||||
//}
|
||||
|
||||
@@ -18,11 +18,6 @@
|
||||
package net.momirealms.customfishing.bukkit.totem;
|
||||
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import net.momirealms.customfishing.api.common.Pair;
|
||||
import net.momirealms.customfishing.api.common.SimpleLocation;
|
||||
import net.momirealms.customfishing.api.event.TotemActivateEvent;
|
||||
import net.momirealms.customfishing.api.mechanic.action.Action;
|
||||
import net.momirealms.customfishing.api.mechanic.action.ActionTrigger;
|
||||
import net.momirealms.customfishing.api.mechanic.totem.TotemConfig;
|
||||
import net.momirealms.customfishing.api.mechanic.totem.TotemManager;
|
||||
import net.momirealms.customfishing.api.mechanic.totem.TotemModel;
|
||||
@@ -32,16 +27,16 @@ import net.momirealms.customfishing.api.mechanic.totem.block.property.FaceImpl;
|
||||
import net.momirealms.customfishing.api.mechanic.totem.block.property.HalfImpl;
|
||||
import net.momirealms.customfishing.api.mechanic.totem.block.property.TotemBlockProperty;
|
||||
import net.momirealms.customfishing.api.mechanic.totem.block.type.TypeCondition;
|
||||
import net.momirealms.customfishing.api.scheduler.CancellableTask;
|
||||
import net.momirealms.customfishing.api.util.SimpleLocation;
|
||||
import net.momirealms.customfishing.bukkit.totem.particle.DustParticleSetting;
|
||||
import net.momirealms.customfishing.bukkit.totem.particle.ParticleSetting;
|
||||
import net.momirealms.customfishing.bukkit.util.LocationUtils;
|
||||
import net.momirealms.customfishing.common.plugin.scheduler.SchedulerTask;
|
||||
import net.momirealms.customfishing.common.util.Pair;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.Bisected;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.HandlerList;
|
||||
@@ -49,7 +44,6 @@ import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
@@ -58,382 +52,352 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class BukkitTotemManager implements TotemManager, Listener {
|
||||
|
||||
private final BukkitCustomFishingPlugin plugin;
|
||||
private final HashMap<String, List<TotemConfig>> totemConfigMap;
|
||||
private final List<String> allMaterials;
|
||||
private final ConcurrentHashMap<SimpleLocation, ActivatedTotem> activatedTotems;
|
||||
private CancellableTask timerCheckTask;
|
||||
|
||||
public BukkitTotemManager(BukkitCustomFishingPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.totemConfigMap = new HashMap<>();
|
||||
this.allMaterials = Arrays.stream(Material.values()).map(Enum::name).toList();
|
||||
this.activatedTotems = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
public void load() {
|
||||
this.loadConfig();
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin);
|
||||
this.timerCheckTask = plugin.getScheduler().runTaskAsyncTimer(() -> {
|
||||
long time = System.currentTimeMillis();
|
||||
ArrayList<SimpleLocation> removed = new ArrayList<>();
|
||||
for (Map.Entry<SimpleLocation, ActivatedTotem> entry : activatedTotems.entrySet()) {
|
||||
if (time > entry.getValue().getExpireTime()) {
|
||||
removed.add(entry.getKey());
|
||||
entry.getValue().cancel();
|
||||
} else {
|
||||
entry.getValue().doTimerAction();
|
||||
}
|
||||
}
|
||||
for (SimpleLocation simpleLocation : removed) {
|
||||
activatedTotems.remove(simpleLocation);
|
||||
}
|
||||
}, 1, 1, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public void unload() {
|
||||
this.totemConfigMap.clear();
|
||||
for (ActivatedTotem activatedTotem : activatedTotems.values()) {
|
||||
activatedTotem.cancel();
|
||||
}
|
||||
activatedTotems.clear();
|
||||
HandlerList.unregisterAll(this);
|
||||
if (this.timerCheckTask != null && !this.timerCheckTask.isCancelled())
|
||||
this.timerCheckTask.cancel();
|
||||
}
|
||||
|
||||
public void disable() {
|
||||
unload();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the EffectCarrier associated with an activated totem located near the specified location.
|
||||
*
|
||||
* @param location The location to search for activated totems.
|
||||
* @return The EffectCarrier associated with the nearest activated totem or null if none are found.
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public EffectCarrier getTotemEffect(Location location) {
|
||||
for (ActivatedTotem activatedTotem : activatedTotems.values()) {
|
||||
if (LocationUtils.getDistance(activatedTotem.getCoreLocation(), location) < activatedTotem.getTotemConfig().getRadius()) {
|
||||
return activatedTotem.getEffectCarrier();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBreakTotemCore(BlockBreakEvent event) {
|
||||
if (event.isCancelled())
|
||||
return;
|
||||
Location location = event.getBlock().getLocation();
|
||||
SimpleLocation simpleLocation = SimpleLocation.getByBukkitLocation(location);
|
||||
ActivatedTotem activatedTotem = activatedTotems.remove(simpleLocation);
|
||||
if (activatedTotem != null)
|
||||
activatedTotem.cancel();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInteractBlock(PlayerInteractEvent event) {
|
||||
if (event.isBlockInHand())
|
||||
return;
|
||||
if (event.useItemInHand() == Event.Result.DENY)
|
||||
return;
|
||||
if (event.getAction() != org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK)
|
||||
return;
|
||||
if (event.getHand() != EquipmentSlot.HAND)
|
||||
return;
|
||||
Block block = event.getClickedBlock();
|
||||
assert block != null;
|
||||
String id = plugin.getBlockManager().getAnyPluginBlockID(block);
|
||||
List<TotemConfig> configs = totemConfigMap.get(id);
|
||||
if (configs == null)
|
||||
return;
|
||||
TotemConfig config = null;
|
||||
for (TotemConfig temp : configs) {
|
||||
if (temp.isRightPattern(block.getLocation())) {
|
||||
config = temp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (config == null)
|
||||
return;
|
||||
String totemKey = config.getKey();
|
||||
EffectCarrier carrier = plugin.getEffectManager().getEffectCarrier("totem", totemKey);
|
||||
if (carrier == null)
|
||||
return;
|
||||
PlayerContext playerContext = new PlayerContext(block.getLocation(), event.getPlayer(), new HashMap<>());
|
||||
if (!carrier.isConditionMet(playerContext))
|
||||
return;
|
||||
|
||||
TotemActivateEvent totemActivateEvent = new TotemActivateEvent(event.getPlayer(), block.getLocation(), config);
|
||||
Bukkit.getPluginManager().callEvent(totemActivateEvent);
|
||||
if (totemActivateEvent.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Action[] actions = carrier.getActionMap().get(ActionTrigger.ACTIVATE);
|
||||
if (actions != null)
|
||||
for (Action action : actions) {
|
||||
action.trigger(playerContext);
|
||||
}
|
||||
Location location = block.getLocation();
|
||||
ActivatedTotem activatedTotem = new ActivatedTotem(location, config);
|
||||
SimpleLocation simpleLocation = SimpleLocation.getByBukkitLocation(location);
|
||||
|
||||
ActivatedTotem previous = this.activatedTotems.put(simpleLocation, activatedTotem);
|
||||
if (previous != null) {
|
||||
previous.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
private void loadConfig() {
|
||||
Deque<File> fileDeque = new ArrayDeque<>();
|
||||
for (String type : List.of("totem")) {
|
||||
File typeFolder = new File(plugin.getDataFolder() + File.separator + "contents" + File.separator + type);
|
||||
if (!typeFolder.exists()) {
|
||||
if (!typeFolder.mkdirs()) return;
|
||||
plugin.saveResource("contents" + File.separator + type + File.separator + "default.yml", false);
|
||||
}
|
||||
fileDeque.push(typeFolder);
|
||||
while (!fileDeque.isEmpty()) {
|
||||
File file = fileDeque.pop();
|
||||
File[] files = file.listFiles();
|
||||
if (files == null) continue;
|
||||
for (File subFile : files) {
|
||||
if (subFile.isDirectory()) {
|
||||
fileDeque.push(subFile);
|
||||
} else if (subFile.isFile() && subFile.getName().endsWith(".yml")) {
|
||||
this.loadSingleFile(subFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void loadSingleFile(File file) {
|
||||
YamlConfiguration config = YamlConfiguration.loadConfiguration(file);
|
||||
for (Map.Entry<String, Object> entry : config.getValues(false).entrySet()) {
|
||||
if (entry.getValue() instanceof ConfigurationSection section) {
|
||||
TotemConfig totemConfig = new TotemConfig.Builder(entry.getKey())
|
||||
.setTotemModels(getTotemModels(section.getConfigurationSection("pattern")))
|
||||
.setParticleSettings(getParticleSettings(section.getConfigurationSection("particles")))
|
||||
.setRequirements(plugin.getRequirementManager().parseRequirements(section.getConfigurationSection("requirements"), true))
|
||||
.setRadius(section.getDouble("radius", 8))
|
||||
.setDuration(section.getInt("duration", 300))
|
||||
.build();
|
||||
|
||||
HashSet<String> coreMaterials = new HashSet<>();
|
||||
for (TotemBlock totemBlock : totemConfig.getTotemCore()) {
|
||||
String text = totemBlock.getTypeCondition().getRawText();
|
||||
if (text.startsWith("*")) {
|
||||
String sub = text.substring(1);
|
||||
coreMaterials.addAll(allMaterials.stream().filter(it -> it.endsWith(sub)).toList());
|
||||
} else if (text.endsWith("*")) {
|
||||
String sub = text.substring(0, text.length() - 1);
|
||||
coreMaterials.addAll(allMaterials.stream().filter(it -> it.startsWith(sub)).toList());
|
||||
} else {
|
||||
coreMaterials.add(text);
|
||||
}
|
||||
}
|
||||
for (String material : coreMaterials) {
|
||||
putTotemConfigToMap(material, totemConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void putTotemConfigToMap(String material, TotemConfig totemConfig) {
|
||||
List<TotemConfig> configs = this.totemConfigMap.getOrDefault(material, new ArrayList<>());
|
||||
configs.add(totemConfig);
|
||||
this.totemConfigMap.put(material, configs);
|
||||
}
|
||||
|
||||
public ParticleSetting[] getParticleSettings(ConfigurationSection section) {
|
||||
List<ParticleSetting> particleSettings = new ArrayList<>();
|
||||
if (section != null)
|
||||
for (Map.Entry<String, Object> entry : section.getValues(false).entrySet()) {
|
||||
if (entry.getValue() instanceof ConfigurationSection innerSection) {
|
||||
particleSettings.add(getParticleSetting(innerSection));
|
||||
}
|
||||
}
|
||||
return particleSettings.toArray(new ParticleSetting[0]);
|
||||
}
|
||||
|
||||
public ParticleSetting getParticleSetting(ConfigurationSection section) {
|
||||
Particle particle = Particle.valueOf(section.getString("type","REDSTONE"));
|
||||
String formulaHorizontal = section.getString("polar-coordinates-formula.horizontal");
|
||||
String formulaVertical = section.getString("polar-coordinates-formula.vertical");
|
||||
List<Pair<Double, Double>> ranges = section.getStringList("theta.range")
|
||||
.stream().map(it -> {
|
||||
String[] split = it.split("~");
|
||||
return Pair.of(Double.parseDouble(split[0]) * Math.PI / 180, Double.parseDouble(split[1]) * Math.PI / 180);
|
||||
}).toList();
|
||||
|
||||
double interval = section.getDouble("theta.draw-interval", 3d);
|
||||
int delay = section.getInt("task.delay", 0);
|
||||
int period = section.getInt("task.period", 0);
|
||||
if (particle == Particle.REDSTONE) {
|
||||
String color = section.getString("options.color","0,0,0");
|
||||
String[] colorSplit = color.split(",");
|
||||
return new DustParticleSetting(
|
||||
formulaHorizontal,
|
||||
formulaVertical,
|
||||
particle,
|
||||
interval,
|
||||
ranges,
|
||||
delay,
|
||||
period,
|
||||
new Particle.DustOptions(
|
||||
Color.fromRGB(
|
||||
Integer.parseInt(colorSplit[0]),
|
||||
Integer.parseInt(colorSplit[1]),
|
||||
Integer.parseInt(colorSplit[2])
|
||||
),
|
||||
(float) section.getDouble("options.scale", 1)
|
||||
)
|
||||
);
|
||||
} else if (particle == Particle.DUST_COLOR_TRANSITION) {
|
||||
String color = section.getString("options.from","0,0,0");
|
||||
String[] colorSplit = color.split(",");
|
||||
String toColor = section.getString("options.to","255,255,255");
|
||||
String[] toColorSplit = toColor.split(",");
|
||||
return new DustParticleSetting(
|
||||
formulaHorizontal,
|
||||
formulaVertical,
|
||||
particle,
|
||||
interval,
|
||||
ranges,
|
||||
delay,
|
||||
period,
|
||||
new Particle.DustTransition(
|
||||
Color.fromRGB(
|
||||
Integer.parseInt(colorSplit[0]),
|
||||
Integer.parseInt(colorSplit[1]),
|
||||
Integer.parseInt(colorSplit[2])
|
||||
),
|
||||
Color.fromRGB(
|
||||
Integer.parseInt(toColorSplit[0]),
|
||||
Integer.parseInt(toColorSplit[1]),
|
||||
Integer.parseInt(toColorSplit[2])
|
||||
),
|
||||
(float) section.getDouble("options.scale", 1)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
return new ParticleSetting(
|
||||
formulaHorizontal,
|
||||
formulaVertical,
|
||||
particle,
|
||||
interval,
|
||||
ranges,
|
||||
delay,
|
||||
period
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public TotemModel[] getTotemModels(ConfigurationSection section) {
|
||||
TotemModel originalModel = parseModel(section);
|
||||
List<TotemModel> modelList = new ArrayList<>();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
originalModel = originalModel.deepClone().rotate90();
|
||||
modelList.add(originalModel);
|
||||
if (i % 2 == 0) {
|
||||
modelList.add(originalModel.mirrorVertically());
|
||||
} else {
|
||||
modelList.add(originalModel.mirrorHorizontally());
|
||||
}
|
||||
}
|
||||
return modelList.toArray(new TotemModel[0]);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public TotemModel parseModel(ConfigurationSection section) {
|
||||
ConfigurationSection layerSection = section.getConfigurationSection("layer");
|
||||
List<TotemBlock[][][]> totemBlocksList = new ArrayList<>();
|
||||
if (layerSection != null) {
|
||||
var set = layerSection.getValues(false).entrySet();
|
||||
TotemBlock[][][][] totemBlocks = new TotemBlock[set.size()][][][];
|
||||
for (Map.Entry<String, Object> entry : set) {
|
||||
if (entry.getValue() instanceof List<?> list) {
|
||||
totemBlocks[Integer.parseInt(entry.getKey())-1] = parseLayer((List<String>) list);
|
||||
}
|
||||
}
|
||||
totemBlocksList.addAll(List.of(totemBlocks));
|
||||
}
|
||||
|
||||
String[] core = section.getString("core","1,1,1").split(",");
|
||||
int x = Integer.parseInt(core[2]) - 1;
|
||||
int z = Integer.parseInt(core[1]) - 1;
|
||||
int y = Integer.parseInt(core[0]) - 1;
|
||||
return new TotemModel(
|
||||
x,y,z,
|
||||
totemBlocksList.toArray(new TotemBlock[0][][][])
|
||||
);
|
||||
}
|
||||
|
||||
public TotemBlock[][][] parseLayer(List<String> lines) {
|
||||
List<TotemBlock[][]> totemBlocksList = new ArrayList<>();
|
||||
for (String line : lines) {
|
||||
totemBlocksList.add(parseSingleLine(line));
|
||||
}
|
||||
return totemBlocksList.toArray(new TotemBlock[0][][]);
|
||||
}
|
||||
|
||||
public TotemBlock[][] parseSingleLine(String line) {
|
||||
List<TotemBlock[]> totemBlocksList = new ArrayList<>();
|
||||
String[] splits = line.split("\\s+");
|
||||
for (String split : splits) {
|
||||
totemBlocksList.add(parseSingleElement(split));
|
||||
}
|
||||
return totemBlocksList.toArray(new TotemBlock[0][]);
|
||||
}
|
||||
|
||||
public TotemBlock[] parseSingleElement(String element) {
|
||||
String[] orBlocks = element.split("\\|\\|");
|
||||
List<TotemBlock> totemBlockList = new ArrayList<>();
|
||||
for (String block : orBlocks) {
|
||||
int index = block.indexOf("{");
|
||||
List<TotemBlockProperty> propertyList = new ArrayList<>();
|
||||
if (index == -1) {
|
||||
index = block.length();
|
||||
} else {
|
||||
String propertyStr = block.substring(index+1, block.length()-1);
|
||||
String[] properties = propertyStr.split(";");
|
||||
for (String property : properties) {
|
||||
String[] split = property.split("=");
|
||||
if (split.length < 2) continue;
|
||||
String key = split[0];
|
||||
String value = split[1];
|
||||
switch (key) {
|
||||
// Block face
|
||||
case "face" -> {
|
||||
BlockFace blockFace = BlockFace.valueOf(value.toUpperCase(Locale.ENGLISH));
|
||||
propertyList.add(new FaceImpl(blockFace));
|
||||
}
|
||||
// Block axis
|
||||
case "axis" -> {
|
||||
Axis axis = Axis.valueOf(value.toUpperCase(Locale.ENGLISH));
|
||||
propertyList.add(new AxisImpl(axis));
|
||||
}
|
||||
// Slab, Stair half
|
||||
case "half" -> {
|
||||
Bisected.Half half = Bisected.Half.valueOf(value.toUpperCase(Locale.ENGLISH));
|
||||
propertyList.add(new HalfImpl(half));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
String type = block.substring(0, index);
|
||||
TotemBlock totemBlock = new TotemBlock(
|
||||
TypeCondition.getTypeCondition(type),
|
||||
propertyList.toArray(new TotemBlockProperty[0])
|
||||
);
|
||||
totemBlockList.add(totemBlock);
|
||||
}
|
||||
return totemBlockList.toArray(new TotemBlock[0]);
|
||||
}
|
||||
// private final BukkitCustomFishingPlugin plugin;
|
||||
// private final HashMap<String, List<TotemConfig>> totemConfigMap;
|
||||
// private final List<String> allMaterials;
|
||||
// private final ConcurrentHashMap<SimpleLocation, ActivatedTotem> activatedTotems;
|
||||
// private SchedulerTask timerCheckTask;
|
||||
//
|
||||
// public BukkitTotemManager(BukkitCustomFishingPlugin plugin) {
|
||||
// this.plugin = plugin;
|
||||
// this.totemConfigMap = new HashMap<>();
|
||||
// this.allMaterials = Arrays.stream(Material.values()).map(Enum::name).toList();
|
||||
// this.activatedTotems = new ConcurrentHashMap<>();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void load() {
|
||||
// this.loadConfig();
|
||||
// Bukkit.getPluginManager().registerEvents(this, plugin.getBoostrap());
|
||||
// this.timerCheckTask = plugin.getScheduler().asyncRepeating(() -> {
|
||||
// long time = System.currentTimeMillis();
|
||||
// ArrayList<SimpleLocation> removed = new ArrayList<>();
|
||||
// for (Map.Entry<SimpleLocation, ActivatedTotem> entry : activatedTotems.entrySet()) {
|
||||
// if (time > entry.getValue().getExpireTime()) {
|
||||
// removed.add(entry.getKey());
|
||||
// entry.getValue().cancel();
|
||||
// } else {
|
||||
// entry.getValue().doTimerAction();
|
||||
// }
|
||||
// }
|
||||
// for (SimpleLocation simpleLocation : removed) {
|
||||
// activatedTotems.remove(simpleLocation);
|
||||
// }
|
||||
// }, 1, 1, TimeUnit.SECONDS);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void unload() {
|
||||
// HandlerList.unregisterAll(this);
|
||||
// for (ActivatedTotem activatedTotem : this.activatedTotems.values())
|
||||
// activatedTotem.cancel();
|
||||
// this.activatedTotems.clear();
|
||||
// if (this.timerCheckTask != null)
|
||||
// this.timerCheckTask.cancel();
|
||||
// this.totemConfigMap.clear();
|
||||
// }
|
||||
//
|
||||
//// /**
|
||||
//// * Get the EffectCarrier associated with an activated totem located near the specified location.
|
||||
//// *
|
||||
//// * @param location The location to search for activated totems.
|
||||
//// * @return The EffectCarrier associated with the nearest activated totem or null if none are found.
|
||||
//// */
|
||||
//// @Override
|
||||
//// @Nullable
|
||||
//// public EffectCarrier getTotemEffect(Location location) {
|
||||
//// for (ActivatedTotem activatedTotem : activatedTotems.values()) {
|
||||
//// if (LocationUtils.getDistance(activatedTotem.getCoreLocation(), location) < activatedTotem.getTotemConfig().radius()) {
|
||||
//// return activatedTotem.getEffectCarrier();
|
||||
//// }
|
||||
//// }
|
||||
//// return null;
|
||||
//// }
|
||||
//
|
||||
// @EventHandler
|
||||
// public void onBreakTotemCore(BlockBreakEvent event) {
|
||||
// if (event.isCancelled())
|
||||
// return;
|
||||
// Location location = event.getBlock().getLocation();
|
||||
// SimpleLocation simpleLocation = SimpleLocation.of(location);
|
||||
// ActivatedTotem activatedTotem = activatedTotems.remove(simpleLocation);
|
||||
// if (activatedTotem != null)
|
||||
// activatedTotem.cancel();
|
||||
// }
|
||||
//
|
||||
// @EventHandler
|
||||
// public void onInteractBlock(PlayerInteractEvent event) {
|
||||
// if (event.isBlockInHand())
|
||||
// return;
|
||||
// if (event.useItemInHand() == Event.Result.DENY)
|
||||
// return;
|
||||
// if (event.getAction() != org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK)
|
||||
// return;
|
||||
// if (event.getHand() != EquipmentSlot.HAND)
|
||||
// return;
|
||||
// Block block = event.getClickedBlock();
|
||||
// assert block != null;
|
||||
// String id = plugin.getBlockManager().getBlockID(block);
|
||||
// List<TotemConfig> configs = totemConfigMap.get(id);
|
||||
// if (configs == null)
|
||||
// return;
|
||||
// TotemConfig config = null;
|
||||
// for (TotemConfig temp : configs) {
|
||||
// if (temp.isRightPattern(block.getLocation())) {
|
||||
// config = temp;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// if (config == null)
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// @SuppressWarnings("DuplicatedCode")
|
||||
// private void loadConfig() {
|
||||
// Deque<File> fileDeque = new ArrayDeque<>();
|
||||
// for (String type : List.of("totem")) {
|
||||
// File typeFolder = new File(plugin.getDataFolder() + File.separator + "contents" + File.separator + type);
|
||||
// if (!typeFolder.exists()) {
|
||||
// if (!typeFolder.mkdirs()) return;
|
||||
// plugin.getBoostrap().saveResource("contents" + File.separator + type + File.separator + "default.yml", false);
|
||||
// }
|
||||
// fileDeque.push(typeFolder);
|
||||
// while (!fileDeque.isEmpty()) {
|
||||
// File file = fileDeque.pop();
|
||||
// File[] files = file.listFiles();
|
||||
// if (files == null) continue;
|
||||
// for (File subFile : files) {
|
||||
// if (subFile.isDirectory()) {
|
||||
// fileDeque.push(subFile);
|
||||
// } else if (subFile.isFile() && subFile.getName().endsWith(".yml")) {
|
||||
// this.loadSingleFile(subFile);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private void loadSingleFile(File file) {
|
||||
//// YamlConfiguration config = YamlConfiguration.loadConfiguration(file);
|
||||
//// for (Map.Entry<String, Object> entry : config.getValues(false).entrySet()) {
|
||||
//// if (entry.getValue() instanceof ConfigurationSection section) {
|
||||
//// TotemConfig totemConfig = new TotemConfig.Builder(entry.getKey())
|
||||
//// .setTotemModels(getTotemModels(section.getConfigurationSection("pattern")))
|
||||
//// .setParticleSettings(getParticleSettings(section.getConfigurationSection("particles")))
|
||||
//// .setRequirements(plugin.getRequirementManager().parseRequirements(section.getConfigurationSection("requirements"), true))
|
||||
//// .setRadius(section.getDouble("radius", 8))
|
||||
//// .setDuration(section.getInt("duration", 300))
|
||||
//// .build();
|
||||
////
|
||||
//// HashSet<String> coreMaterials = new HashSet<>();
|
||||
//// for (TotemBlock totemBlock : totemConfig.getTotemCore()) {
|
||||
//// String text = totemBlock.getTypeCondition().getRawText();
|
||||
//// if (text.startsWith("*")) {
|
||||
//// String sub = text.substring(1);
|
||||
//// coreMaterials.addAll(allMaterials.stream().filter(it -> it.endsWith(sub)).toList());
|
||||
//// } else if (text.endsWith("*")) {
|
||||
//// String sub = text.substring(0, text.length() - 1);
|
||||
//// coreMaterials.addAll(allMaterials.stream().filter(it -> it.startsWith(sub)).toList());
|
||||
//// } else {
|
||||
//// coreMaterials.add(text);
|
||||
//// }
|
||||
//// }
|
||||
//// for (String material : coreMaterials) {
|
||||
//// putTotemConfigToMap(material, totemConfig);
|
||||
//// }
|
||||
//// }
|
||||
//// }
|
||||
// }
|
||||
//
|
||||
// private void putTotemConfigToMap(String material, TotemConfig totemConfig) {
|
||||
// List<TotemConfig> configs = this.totemConfigMap.getOrDefault(material, new ArrayList<>());
|
||||
// configs.add(totemConfig);
|
||||
// this.totemConfigMap.put(material, configs);
|
||||
// }
|
||||
//
|
||||
//// public ParticleSetting[] getParticleSettings(ConfigurationSection section) {
|
||||
//// List<ParticleSetting> particleSettings = new ArrayList<>();
|
||||
//// if (section != null)
|
||||
//// for (Map.Entry<String, Object> entry : section.getValues(false).entrySet()) {
|
||||
//// if (entry.getValue() instanceof ConfigurationSection innerSection) {
|
||||
//// particleSettings.add(getParticleSetting(innerSection));
|
||||
//// }
|
||||
//// }
|
||||
//// return particleSettings.toArray(new ParticleSetting[0]);
|
||||
//// }
|
||||
//
|
||||
//// public ParticleSetting getParticleSetting(ConfigurationSection section) {
|
||||
//// Particle particle = Particle.valueOf(section.getString("type","REDSTONE"));
|
||||
//// String formulaHorizontal = section.getString("polar-coordinates-formula.horizontal");
|
||||
//// String formulaVertical = section.getString("polar-coordinates-formula.vertical");
|
||||
//// List<Pair<Double, Double>> ranges = section.getStringList("theta.range")
|
||||
//// .stream().map(it -> {
|
||||
//// String[] split = it.split("~");
|
||||
//// return Pair.of(Double.parseDouble(split[0]) * Math.PI / 180, Double.parseDouble(split[1]) * Math.PI / 180);
|
||||
//// }).toList();
|
||||
////
|
||||
//// double interval = section.getDouble("theta.draw-interval", 3d);
|
||||
//// int delay = section.getInt("task.delay", 0);
|
||||
//// int period = section.getInt("task.period", 0);
|
||||
//// if (particle == Particle.REDSTONE) {
|
||||
//// String color = section.getString("options.color","0,0,0");
|
||||
//// String[] colorSplit = color.split(",");
|
||||
//// return new DustParticleSetting(
|
||||
//// formulaHorizontal,
|
||||
//// formulaVertical,
|
||||
//// particle,
|
||||
//// interval,
|
||||
//// ranges,
|
||||
//// delay,
|
||||
//// period,
|
||||
//// new Particle.DustOptions(
|
||||
//// Color.fromRGB(
|
||||
//// Integer.parseInt(colorSplit[0]),
|
||||
//// Integer.parseInt(colorSplit[1]),
|
||||
//// Integer.parseInt(colorSplit[2])
|
||||
//// ),
|
||||
//// (float) section.getDouble("options.scale", 1)
|
||||
//// )
|
||||
//// );
|
||||
//// } else if (particle == Particle.DUST_COLOR_TRANSITION) {
|
||||
//// String color = section.getString("options.from","0,0,0");
|
||||
//// String[] colorSplit = color.split(",");
|
||||
//// String toColor = section.getString("options.to","255,255,255");
|
||||
//// String[] toColorSplit = toColor.split(",");
|
||||
//// return new DustParticleSetting(
|
||||
//// formulaHorizontal,
|
||||
//// formulaVertical,
|
||||
//// particle,
|
||||
//// interval,
|
||||
//// ranges,
|
||||
//// delay,
|
||||
//// period,
|
||||
//// new Particle.DustTransition(
|
||||
//// Color.fromRGB(
|
||||
//// Integer.parseInt(colorSplit[0]),
|
||||
//// Integer.parseInt(colorSplit[1]),
|
||||
//// Integer.parseInt(colorSplit[2])
|
||||
//// ),
|
||||
//// Color.fromRGB(
|
||||
//// Integer.parseInt(toColorSplit[0]),
|
||||
//// Integer.parseInt(toColorSplit[1]),
|
||||
//// Integer.parseInt(toColorSplit[2])
|
||||
//// ),
|
||||
//// (float) section.getDouble("options.scale", 1)
|
||||
//// )
|
||||
//// );
|
||||
//// } else {
|
||||
//// return new ParticleSetting(
|
||||
//// formulaHorizontal,
|
||||
//// formulaVertical,
|
||||
//// particle,
|
||||
//// interval,
|
||||
//// ranges,
|
||||
//// delay,
|
||||
//// period
|
||||
//// );
|
||||
//// }
|
||||
//// }
|
||||
//
|
||||
// public TotemModel[] getTotemModels(ConfigurationSection section) {
|
||||
// TotemModel originalModel = parseModel(section);
|
||||
// List<TotemModel> modelList = new ArrayList<>();
|
||||
// for (int i = 0; i < 4; i++) {
|
||||
// originalModel = originalModel.deepClone().rotate90();
|
||||
// modelList.add(originalModel);
|
||||
// if (i % 2 == 0) {
|
||||
// modelList.add(originalModel.mirrorVertically());
|
||||
// } else {
|
||||
// modelList.add(originalModel.mirrorHorizontally());
|
||||
// }
|
||||
// }
|
||||
// return modelList.toArray(new TotemModel[0]);
|
||||
// }
|
||||
//
|
||||
// @SuppressWarnings("unchecked")
|
||||
// public TotemModel parseModel(ConfigurationSection section) {
|
||||
// ConfigurationSection layerSection = section.getConfigurationSection("layer");
|
||||
// List<TotemBlock[][][]> totemBlocksList = new ArrayList<>();
|
||||
// if (layerSection != null) {
|
||||
// var set = layerSection.getValues(false).entrySet();
|
||||
// TotemBlock[][][][] totemBlocks = new TotemBlock[set.size()][][][];
|
||||
// for (Map.Entry<String, Object> entry : set) {
|
||||
// if (entry.getValue() instanceof List<?> list) {
|
||||
// totemBlocks[Integer.parseInt(entry.getKey())-1] = parseLayer((List<String>) list);
|
||||
// }
|
||||
// }
|
||||
// totemBlocksList.addAll(List.of(totemBlocks));
|
||||
// }
|
||||
//
|
||||
// String[] core = section.getString("core","1,1,1").split(",");
|
||||
// int x = Integer.parseInt(core[2]) - 1;
|
||||
// int z = Integer.parseInt(core[1]) - 1;
|
||||
// int y = Integer.parseInt(core[0]) - 1;
|
||||
// return new TotemModel(
|
||||
// x,y,z,
|
||||
// totemBlocksList.toArray(new TotemBlock[0][][][])
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// public TotemBlock[][][] parseLayer(List<String> lines) {
|
||||
// List<TotemBlock[][]> totemBlocksList = new ArrayList<>();
|
||||
// for (String line : lines) {
|
||||
// totemBlocksList.add(parseSingleLine(line));
|
||||
// }
|
||||
// return totemBlocksList.toArray(new TotemBlock[0][][]);
|
||||
// }
|
||||
//
|
||||
// public TotemBlock[][] parseSingleLine(String line) {
|
||||
// List<TotemBlock[]> totemBlocksList = new ArrayList<>();
|
||||
// String[] splits = line.split("\\s+");
|
||||
// for (String split : splits) {
|
||||
// totemBlocksList.add(parseSingleElement(split));
|
||||
// }
|
||||
// return totemBlocksList.toArray(new TotemBlock[0][]);
|
||||
// }
|
||||
//
|
||||
// public TotemBlock[] parseSingleElement(String element) {
|
||||
// String[] orBlocks = element.split("\\|\\|");
|
||||
// List<TotemBlock> totemBlockList = new ArrayList<>();
|
||||
// for (String block : orBlocks) {
|
||||
// int index = block.indexOf("{");
|
||||
// List<TotemBlockProperty> propertyList = new ArrayList<>();
|
||||
// if (index == -1) {
|
||||
// index = block.length();
|
||||
// } else {
|
||||
// String propertyStr = block.substring(index+1, block.length()-1);
|
||||
// String[] properties = propertyStr.split(";");
|
||||
// for (String property : properties) {
|
||||
// String[] split = property.split("=");
|
||||
// if (split.length < 2) continue;
|
||||
// String key = split[0];
|
||||
// String value = split[1];
|
||||
// switch (key) {
|
||||
// // Block face
|
||||
// case "face" -> {
|
||||
// BlockFace blockFace = BlockFace.valueOf(value.toUpperCase(Locale.ENGLISH));
|
||||
// propertyList.add(new FaceImpl(blockFace));
|
||||
// }
|
||||
// // Block axis
|
||||
// case "axis" -> {
|
||||
// Axis axis = Axis.valueOf(value.toUpperCase(Locale.ENGLISH));
|
||||
// propertyList.add(new AxisImpl(axis));
|
||||
// }
|
||||
// // Slab, Stair half
|
||||
// case "half" -> {
|
||||
// Bisected.Half half = Bisected.Half.valueOf(value.toUpperCase(Locale.ENGLISH));
|
||||
// propertyList.add(new HalfImpl(half));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// String type = block.substring(0, index);
|
||||
// TotemBlock totemBlock = new TotemBlock(
|
||||
// TypeCondition.getTypeCondition(type),
|
||||
// propertyList.toArray(new TotemBlockProperty[0])
|
||||
// );
|
||||
// totemBlockList.add(totemBlock);
|
||||
// }
|
||||
// return totemBlockList.toArray(new TotemBlock[0]);
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
package net.momirealms.customfishing.bukkit.totem.particle;
|
||||
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import net.momirealms.customfishing.api.common.Pair;
|
||||
import net.momirealms.customfishing.api.scheduler.CancellableTask;
|
||||
import net.momirealms.customfishing.common.plugin.scheduler.SchedulerTask;
|
||||
import net.momirealms.customfishing.common.util.Pair;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.World;
|
||||
@@ -46,7 +46,7 @@ public class DustParticleSetting extends ParticleSetting {
|
||||
}
|
||||
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
public CancellableTask start(Location location, double radius) {
|
||||
public SchedulerTask start(Location location, double radius) {
|
||||
World world = location.getWorld();
|
||||
return BukkitCustomFishingPlugin.get().getScheduler().runTaskAsyncTimer(() -> {
|
||||
for (Pair<Double, Double> range : ranges) {
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
package net.momirealms.customfishing.bukkit.totem.particle;
|
||||
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import net.momirealms.customfishing.api.common.Pair;
|
||||
import net.momirealms.customfishing.api.mechanic.totem.TotemParticle;
|
||||
import net.momirealms.customfishing.api.scheduler.CancellableTask;
|
||||
import net.momirealms.customfishing.common.plugin.scheduler.SchedulerTask;
|
||||
import net.momirealms.customfishing.common.util.Pair;
|
||||
import net.objecthunter.exp4j.Expression;
|
||||
import net.objecthunter.exp4j.ExpressionBuilder;
|
||||
import org.bukkit.Location;
|
||||
@@ -63,9 +63,9 @@ public class ParticleSetting implements TotemParticle {
|
||||
}
|
||||
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
public CancellableTask start(Location location, double radius) {
|
||||
public SchedulerTask start(Location location, double radius) {
|
||||
World world = location.getWorld();
|
||||
return BukkitCustomFishingPlugin.get().getScheduler().runTaskAsyncTimer(() -> {
|
||||
return BukkitCustomFishingPlugin.getInstance().getScheduler().asyncRepeating(() -> {
|
||||
for (Pair<Double, Double> range : ranges) {
|
||||
for (double theta = range.left(); theta <= range.right(); theta += interval) {
|
||||
double r = expressionHorizontal.setVariable("theta", theta).setVariable("radius", radius).evaluate();
|
||||
|
||||
@@ -1,221 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customfishing.bukkit.util;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.events.PacketContainer;
|
||||
import com.comphenix.protocol.wrappers.*;
|
||||
import com.google.common.collect.Lists;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Utility class for managing armor stands and sending related packets.
|
||||
*/
|
||||
public class ArmorStandUtils {
|
||||
|
||||
private ArmorStandUtils() {}
|
||||
|
||||
/**
|
||||
* Creates a destroy packet for removing an armor stand entity.
|
||||
*
|
||||
* @param id The ID of the armor stand entity to destroy
|
||||
* @return The PacketContainer representing the destroy packet
|
||||
*/
|
||||
public static PacketContainer getDestroyPacket(int id) {
|
||||
PacketContainer destroyPacket = new PacketContainer(PacketType.Play.Server.ENTITY_DESTROY);
|
||||
destroyPacket.getIntLists().write(0, List.of(id));
|
||||
return destroyPacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a spawn packet for an armor stand entity at the specified location.
|
||||
*
|
||||
* @param id The ID of the armor stand entity to spawn
|
||||
* @param location The location where the armor stand entity should be spawned
|
||||
* @return The PacketContainer representing the spawn packet
|
||||
*/
|
||||
public static PacketContainer getSpawnPacket(int id, Location location) {
|
||||
PacketContainer entityPacket = new PacketContainer(PacketType.Play.Server.SPAWN_ENTITY);
|
||||
try {
|
||||
entityPacket.getModifier().write(0, id);
|
||||
entityPacket.getModifier().write(1, UUID.randomUUID());
|
||||
entityPacket.getEntityTypeModifier().write(0, EntityType.ARMOR_STAND);
|
||||
entityPacket.getDoubles().write(0, location.getX());
|
||||
entityPacket.getDoubles().write(1, location.getY());
|
||||
entityPacket.getDoubles().write(2, location.getZ());
|
||||
if (BukkitCustomFishingPlugin.get().getVersionManager().isVersionNewerThan1_19()) {
|
||||
entityPacket.getBytes().write(0, (byte) ((location.getYaw() % 360) * 128 / 180));
|
||||
} else {
|
||||
entityPacket.getIntegers().write(5, (int) ((location.getYaw() % 360) * 128 / 180));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return entityPacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a metadata packet for updating the metadata of an armor stand entity.
|
||||
*
|
||||
* @param id The ID of the armor stand entity
|
||||
* @return The PacketContainer representing the metadata packet
|
||||
*/
|
||||
public static PacketContainer getMetaPacket(int id) {
|
||||
PacketContainer metaPacket = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
|
||||
metaPacket.getIntegers().write(0, id);
|
||||
if (BukkitCustomFishingPlugin.get().getVersionManager().isVersionNewerThan1_19_3()) {
|
||||
WrappedDataWatcher wrappedDataWatcher = createDataWatcher();
|
||||
setValueList(metaPacket, wrappedDataWatcher);
|
||||
} else {
|
||||
metaPacket.getWatchableCollectionModifier().write(0, createDataWatcher().getWatchableObjects());
|
||||
}
|
||||
return metaPacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value list in a PacketContainer's DataWatcher from a WrappedDataWatcher.
|
||||
*
|
||||
* @param metaPacket The PacketContainer representing the metadata packet
|
||||
* @param wrappedDataWatcher The WrappedDataWatcher containing the value list
|
||||
*/
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
private static void setValueList(PacketContainer metaPacket, WrappedDataWatcher wrappedDataWatcher) {
|
||||
List<WrappedDataValue> wrappedDataValueList = Lists.newArrayList();
|
||||
wrappedDataWatcher.getWatchableObjects().stream().filter(Objects::nonNull).forEach(entry -> {
|
||||
final WrappedDataWatcher.WrappedDataWatcherObject dataWatcherObject = entry.getWatcherObject();
|
||||
wrappedDataValueList.add(new WrappedDataValue(dataWatcherObject.getIndex(), dataWatcherObject.getSerializer(), entry.getRawValue()));
|
||||
});
|
||||
metaPacket.getDataValueCollectionModifier().write(0, wrappedDataValueList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a metadata packet for updating the metadata of an armor stand entity with a custom Component.
|
||||
*
|
||||
* @param id The ID of the armor stand entity
|
||||
* @param component The Component to set as metadata
|
||||
* @return The PacketContainer representing the metadata packet
|
||||
*/
|
||||
public static PacketContainer getMetaPacket(int id, Component component) {
|
||||
PacketContainer metaPacket = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
|
||||
metaPacket.getIntegers().write(0, id);
|
||||
if (BukkitCustomFishingPlugin.get().getVersionManager().isVersionNewerThan1_19_3()) {
|
||||
WrappedDataWatcher wrappedDataWatcher = createDataWatcher(component);
|
||||
setValueList(metaPacket, wrappedDataWatcher);
|
||||
} else {
|
||||
metaPacket.getWatchableCollectionModifier().write(0, createDataWatcher(component).getWatchableObjects());
|
||||
}
|
||||
return metaPacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DataWatcher for an invisible armor stand entity.
|
||||
*
|
||||
* @return The created DataWatcher
|
||||
*/
|
||||
public static WrappedDataWatcher createDataWatcher() {
|
||||
WrappedDataWatcher wrappedDataWatcher = new WrappedDataWatcher();
|
||||
WrappedDataWatcher.Serializer serializer1 = WrappedDataWatcher.Registry.get(Boolean.class);
|
||||
WrappedDataWatcher.Serializer serializer2 = WrappedDataWatcher.Registry.get(Byte.class);
|
||||
wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(3, serializer1), false);
|
||||
byte flag = 0x20;
|
||||
wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(0, serializer2), flag);
|
||||
return wrappedDataWatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DataWatcher for an invisible armor stand entity with a custom Component.
|
||||
*
|
||||
* @param component The Component to set in the DataWatcher
|
||||
* @return The created DataWatcher
|
||||
*/
|
||||
public static WrappedDataWatcher createDataWatcher(Component component) {
|
||||
WrappedDataWatcher wrappedDataWatcher = new WrappedDataWatcher();
|
||||
WrappedDataWatcher.Serializer serializer1 = WrappedDataWatcher.Registry.get(Boolean.class);
|
||||
WrappedDataWatcher.Serializer serializer2 = WrappedDataWatcher.Registry.get(Byte.class);
|
||||
wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(2, WrappedDataWatcher.Registry.getChatComponentSerializer(true)), Optional.of(WrappedChatComponent.fromJson(GsonComponentSerializer.gson().serialize(component)).getHandle()));
|
||||
wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(3, serializer1), true);
|
||||
wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(15, serializer2), (byte) 0x01);
|
||||
byte flag = 0x20;
|
||||
wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(0, serializer2), flag);
|
||||
return wrappedDataWatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an equipment packet for equipping an armor stand with an ItemStack.
|
||||
*
|
||||
* @param id The ID of the armor stand entity
|
||||
* @param itemStack The ItemStack to equip
|
||||
* @return The PacketContainer representing the equipment packet
|
||||
*/
|
||||
public static PacketContainer getEquipPacket(int id, ItemStack itemStack) {
|
||||
PacketContainer equipPacket = new PacketContainer(PacketType.Play.Server.ENTITY_EQUIPMENT);
|
||||
equipPacket.getIntegers().write(0, id);
|
||||
List<Pair<EnumWrappers.ItemSlot, ItemStack>> pairs = new ArrayList<>();
|
||||
pairs.add(new Pair<>(EnumWrappers.ItemSlot.HEAD, itemStack));
|
||||
equipPacket.getSlotStackPairLists().write(0, pairs);
|
||||
return equipPacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a fake armor stand entity with item on head to a player at the specified location.
|
||||
*
|
||||
* @param player The player to send the entity to
|
||||
* @param location The location where the entity should appear
|
||||
* @param itemStack The ItemStack to represent the entity
|
||||
* @param seconds The duration (in seconds) the entity should be displayed
|
||||
*/
|
||||
public static void sendFakeItem(Player player, Location location, ItemStack itemStack, int seconds) {
|
||||
int id = new Random().nextInt(Integer.MAX_VALUE);
|
||||
if (BukkitCustomFishingPlugin.get().getVersionManager().isVersionNewerThan1_19_4()) {
|
||||
BukkitCustomFishingPluginImpl.sendPackets(player, getSpawnPacket(id, location.clone().subtract(0,1,0)), getMetaPacket(id), getEquipPacket(id, itemStack));
|
||||
} else {
|
||||
BukkitCustomFishingPluginImpl.sendPacket(player, getSpawnPacket(id, location.clone().subtract(0,1,0)));
|
||||
BukkitCustomFishingPluginImpl.sendPacket(player, getMetaPacket(id));
|
||||
BukkitCustomFishingPluginImpl.sendPacket(player, getEquipPacket(id, itemStack));
|
||||
}
|
||||
BukkitCustomFishingPlugin.get().getScheduler().runTaskAsyncLater(() -> BukkitCustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, getDestroyPacket(id)), seconds * 50L, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a hologram (armor stand with custom text) to a player at the specified location.
|
||||
*
|
||||
* @param player The player to send the hologram to
|
||||
* @param location The location where the hologram should appear
|
||||
* @param component The Component representing the hologram's text
|
||||
* @param seconds The duration (in seconds) the hologram should be displayed
|
||||
*/
|
||||
public static void sendHologram(Player player, Location location, Component component, int seconds) {
|
||||
int id = new Random().nextInt(Integer.MAX_VALUE);
|
||||
if (BukkitCustomFishingPlugin.get().getVersionManager().isVersionNewerThan1_19_4()) {
|
||||
BukkitCustomFishingPluginImpl.sendPackets(player, getSpawnPacket(id, location.clone().subtract(0,1,0)), getMetaPacket(id, component));
|
||||
} else {
|
||||
BukkitCustomFishingPluginImpl.sendPacket(player, getSpawnPacket(id, location.clone().subtract(0,1,0)));
|
||||
BukkitCustomFishingPluginImpl.sendPacket(player, getMetaPacket(id, component));
|
||||
}
|
||||
BukkitCustomFishingPlugin.get().getScheduler().runTaskAsyncLater(() -> BukkitCustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, getDestroyPacket(id)), seconds * 50L, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
@@ -1,256 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customfishing.bukkit.util;
|
||||
|
||||
import net.momirealms.customfishing.api.mechanic.misc.placeholder.BukkitPlaceholderManager;
|
||||
import net.momirealms.customfishing.api.mechanic.misc.value.MathValue;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Utility class for configuration-related operations.
|
||||
*/
|
||||
public class ConfigUtils {
|
||||
|
||||
private ConfigUtils() {}
|
||||
|
||||
|
||||
/**
|
||||
* Splits a string into a pair of integers using the "~" delimiter.
|
||||
*
|
||||
* @param value The input string
|
||||
* @return A Pair of integers
|
||||
*/
|
||||
public static Pair<Integer, Integer> splitStringIntegerArgs(String value, String regex) {
|
||||
String[] split = value.split(regex);
|
||||
return Pair.of(Integer.parseInt(split[0]), Integer.parseInt(split[1]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a list of strings in the format "key:value" into a list of Pairs with keys and doubles.
|
||||
*
|
||||
* @param list The input list of strings
|
||||
* @return A list of Pairs containing keys and doubles
|
||||
*/
|
||||
public static List<Pair<String, Double>> getWeights(List<String> list) {
|
||||
List<Pair<String, Double>> result = new ArrayList<>(list.size());
|
||||
for (String member : list) {
|
||||
String[] split = member.split(":",2);
|
||||
String key = split[0];
|
||||
result.add(Pair.of(key, Double.parseDouble(split[1])));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a list of enchantment pairs from a configuration section.
|
||||
*
|
||||
* @param section The configuration section to extract enchantment data from.
|
||||
* @return A list of enchantment pairs.
|
||||
*/
|
||||
@NotNull
|
||||
public static List<Pair<String, Short>> getEnchantmentPair(ConfigurationSection section) {
|
||||
List<Pair<String, Short>> list = new ArrayList<>();
|
||||
if (section == null) return list;
|
||||
for (Map.Entry<String, Object> entry : section.getValues(false).entrySet()) {
|
||||
if (entry.getValue() instanceof Integer integer) {
|
||||
list.add(Pair.of(entry.getKey(), Short.parseShort(String.valueOf(Math.max(1, Math.min(Short.MAX_VALUE, integer))))));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static List<Pair<Integer, MathValue>> getEnchantAmountPair(ConfigurationSection section) {
|
||||
List<Pair<Integer, MathValue>> list = new ArrayList<>();
|
||||
if (section == null) return list;
|
||||
for (Map.Entry<String, Object> entry : section.getValues(false).entrySet()) {
|
||||
list.add(Pair.of(Integer.parseInt(entry.getKey()), getValue(entry.getValue())));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static List<Pair<Pair<String, Short>, MathValue>> getEnchantPoolPair(ConfigurationSection section) {
|
||||
List<Pair<Pair<String, Short>, MathValue>> list = new ArrayList<>();
|
||||
if (section == null) return list;
|
||||
for (Map.Entry<String, Object> entry : section.getValues(false).entrySet()) {
|
||||
list.add(Pair.of(getEnchantmentPair(entry.getKey()), getValue(entry.getValue())));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static Pair<String, Short> getEnchantmentPair(String value) {
|
||||
int last = value.lastIndexOf(":");
|
||||
if (last == -1 || last == 0 || last == value.length() - 1) {
|
||||
throw new IllegalArgumentException("Invalid format of the input enchantment");
|
||||
}
|
||||
return Pair.of(value.substring(0, last), Short.parseShort(value.substring(last + 1)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of enchantment tuples from a configuration section.
|
||||
*
|
||||
* @param section The configuration section to extract enchantment data from.
|
||||
* @return A list of enchantment tuples.
|
||||
*/
|
||||
@NotNull
|
||||
public static List<Tuple<Double, String, Short>> getEnchantmentTuple(ConfigurationSection section) {
|
||||
List<Tuple<Double, String, Short>> list = new ArrayList<>();
|
||||
if (section == null) return list;
|
||||
for (Map.Entry<String, Object> entry : section.getValues(false).entrySet()) {
|
||||
if (entry.getValue() instanceof ConfigurationSection inner) {
|
||||
Tuple<Double, String, Short> tuple = Tuple.of(
|
||||
inner.getDouble("chance"),
|
||||
inner.getString("enchant"),
|
||||
Short.valueOf(String.valueOf(inner.getInt("level")))
|
||||
);
|
||||
list.add(tuple);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static String getString(Object o) {
|
||||
if (o instanceof String s) {
|
||||
return s;
|
||||
} else if (o instanceof Integer i) {
|
||||
return String.valueOf(i);
|
||||
} else if (o instanceof Double d) {
|
||||
return String.valueOf(d);
|
||||
}
|
||||
throw new IllegalArgumentException("Illegal string format: " + o);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads data from a YAML configuration file and creates it if it doesn't exist.
|
||||
*
|
||||
* @param file The file path
|
||||
* @return The YamlConfiguration
|
||||
*/
|
||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||
public static YamlConfiguration readData(File file) {
|
||||
if (!file.exists()) {
|
||||
try {
|
||||
file.getParentFile().mkdirs();
|
||||
file.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
LogUtils.warn("Failed to generate data files!</red>");
|
||||
}
|
||||
}
|
||||
return YamlConfiguration.loadConfiguration(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a WeightModifier from a string representation.
|
||||
*
|
||||
* @param text The input string
|
||||
* @return A WeightModifier based on the provided text
|
||||
* @throws IllegalArgumentException if the weight format is invalid
|
||||
*/
|
||||
public static WeightModifier getModifier(String text) {
|
||||
if (text.length() == 0) {
|
||||
throw new IllegalArgumentException("Weight format is invalid.");
|
||||
}
|
||||
switch (text.charAt(0)) {
|
||||
case '/' -> {
|
||||
double arg = Double.parseDouble(text.substring(1));
|
||||
return (player, weight) -> weight / arg;
|
||||
}
|
||||
case '*' -> {
|
||||
double arg = Double.parseDouble(text.substring(1));
|
||||
return (player, weight) -> weight * arg;
|
||||
}
|
||||
case '-' -> {
|
||||
double arg = Double.parseDouble(text.substring(1));
|
||||
return (player, weight) -> weight - arg;
|
||||
}
|
||||
case '%' -> {
|
||||
double arg = Double.parseDouble(text.substring(1));
|
||||
return (player, weight) -> weight % arg;
|
||||
}
|
||||
case '+' -> {
|
||||
double arg = Double.parseDouble(text.substring(1));
|
||||
return (player, weight) -> weight + arg;
|
||||
}
|
||||
case '=' -> {
|
||||
String formula = text.substring(1);
|
||||
return (player, weight) -> getExpressionValue(player, formula, Map.of("{0}", String.valueOf(weight)));
|
||||
}
|
||||
default -> throw new IllegalArgumentException("Invalid weight: " + text);
|
||||
}
|
||||
}
|
||||
|
||||
public static double getExpressionValue(Player player, String formula, Map<String, String> vars) {
|
||||
formula = BukkitPlaceholderManager.getInstance().parse(player, formula, vars);
|
||||
return new ExpressionBuilder(formula).build().evaluate();
|
||||
}
|
||||
|
||||
public static ArrayList<String> getReadableSection(Map<String, Object> map) {
|
||||
ArrayList<String> list = new ArrayList<>();
|
||||
mapToReadableStringList(map, list, 0, false);
|
||||
return list;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void mapToReadableStringList(Map<String, Object> map, List<String> readableList, int loop_times, boolean isMapList) {
|
||||
boolean first = true;
|
||||
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
||||
Object nbt = entry.getValue();
|
||||
if (nbt instanceof List<?> list) {
|
||||
if (isMapList && first) {
|
||||
first = false;
|
||||
readableList.add(" ".repeat(loop_times - 1) + "<white>- <gold>" + entry.getKey() + ":");
|
||||
} else {
|
||||
readableList.add(" ".repeat(loop_times) + "<gold>" + entry.getKey() + ":");
|
||||
}
|
||||
for (Object value : list) {
|
||||
if (value instanceof Map<?,?> nbtMap) {
|
||||
mapToReadableStringList((Map<String, Object>) nbtMap, readableList, loop_times + 2, true);
|
||||
} else {
|
||||
readableList.add(" ".repeat(loop_times + 1) + "<white>- " + value);
|
||||
}
|
||||
}
|
||||
} else if (nbt instanceof Map<?,?> innerMap) {
|
||||
if (isMapList && first) {
|
||||
first = false;
|
||||
readableList.add(" ".repeat(loop_times - 1) + "<white>- <gold>" + entry.getKey() + ":");
|
||||
} else {
|
||||
readableList.add(" ".repeat(loop_times) + "<gold>" + entry.getKey() + ":");
|
||||
}
|
||||
mapToReadableStringList((Map<String, Object>) innerMap, readableList, loop_times + 1, false);
|
||||
} else {
|
||||
if (isMapList && first) {
|
||||
first = false;
|
||||
readableList.add(" ".repeat(loop_times - 1) + "<white>- <gold>" + entry.getKey() + ": <white>" + nbt.toString());
|
||||
} else {
|
||||
readableList.add(" ".repeat(loop_times) + "<gold>" + entry.getKey() + ": <white>" + nbt.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customfishing.bukkit.util;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.events.PacketContainer;
|
||||
import com.comphenix.protocol.wrappers.WrappedDataValue;
|
||||
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
|
||||
import com.google.common.collect.Lists;
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Utility class for managing fake item entities using PacketContainers.
|
||||
*/
|
||||
public class FakeItemUtils {
|
||||
|
||||
private FakeItemUtils() {}
|
||||
|
||||
/**
|
||||
* Creates a destroy packet for removing a fake item entity.
|
||||
*
|
||||
* @param id The ID of the fake item entity to destroy
|
||||
* @return The PacketContainer representing the destroy packet
|
||||
*/
|
||||
public static PacketContainer getDestroyPacket(int id) {
|
||||
PacketContainer destroyPacket = new PacketContainer(PacketType.Play.Server.ENTITY_DESTROY);
|
||||
destroyPacket.getIntLists().write(0, List.of(id));
|
||||
return destroyPacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a spawn packet for a fake item entity at the specified location.
|
||||
*
|
||||
* @param id The ID of the fake item entity to spawn
|
||||
* @param location The location where the fake item entity should be spawned
|
||||
* @return The PacketContainer representing the spawn packet
|
||||
*/
|
||||
public static PacketContainer getSpawnPacket(int id, Location location) {
|
||||
PacketContainer entityPacket = new PacketContainer(PacketType.Play.Server.SPAWN_ENTITY);
|
||||
entityPacket.getModifier().write(0, id);
|
||||
entityPacket.getModifier().write(1, UUID.randomUUID());
|
||||
entityPacket.getEntityTypeModifier().write(0, EntityType.DROPPED_ITEM);
|
||||
entityPacket.getDoubles().write(0, location.getX());
|
||||
entityPacket.getDoubles().write(1, location.getY() - 0.5);
|
||||
entityPacket.getDoubles().write(2, location.getZ());
|
||||
return entityPacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a metadata packet for updating the metadata of a fake item entity.
|
||||
*
|
||||
* @param id The ID of the fake item entity
|
||||
* @param itemStack The ItemStack to update the metadata with
|
||||
* @return The PacketContainer representing the metadata packet
|
||||
*/
|
||||
public static PacketContainer getMetaPacket(int id, ItemStack itemStack) {
|
||||
PacketContainer metaPacket = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
|
||||
metaPacket.getIntegers().write(0, id);
|
||||
if (BukkitCustomFishingPlugin.getInstance().getVersionManager().isVersionNewerThan1_19_3()) {
|
||||
WrappedDataWatcher wrappedDataWatcher = createDataWatcher(itemStack);
|
||||
setValueList(metaPacket, wrappedDataWatcher);
|
||||
} else {
|
||||
metaPacket.getWatchableCollectionModifier().write(0, createDataWatcher(itemStack).getWatchableObjects());
|
||||
}
|
||||
return metaPacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a teleport packet for moving a fake item entity to the specified location.
|
||||
*
|
||||
* @param id The ID of the fake item entity to teleport
|
||||
* @param location The location to teleport the fake item entity to
|
||||
* @return The PacketContainer representing the teleport packet
|
||||
*/
|
||||
public static PacketContainer getTpPacket(int id, Location location) {
|
||||
PacketContainer tpPacket = new PacketContainer(PacketType.Play.Server.ENTITY_TELEPORT);
|
||||
tpPacket.getModifier().write(0, id);
|
||||
tpPacket.getDoubles().write(0, location.getX());
|
||||
tpPacket.getDoubles().write(1, location.getY() - 0.5);
|
||||
tpPacket.getDoubles().write(2, location.getZ());
|
||||
return tpPacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a velocity packet for applying velocity to a fake item entity.
|
||||
*
|
||||
* @param id The ID of the fake item entity
|
||||
* @param vector The velocity vector to apply
|
||||
* @return The PacketContainer representing the velocity packet
|
||||
*/
|
||||
public static PacketContainer getVelocityPacket(int id, Vector vector) {
|
||||
PacketContainer entityPacket = new PacketContainer(PacketType.Play.Server.ENTITY_VELOCITY);
|
||||
entityPacket.getModifier().write(0, id);
|
||||
entityPacket.getIntegers().write(1, (int) (vector.getX() * 8000));
|
||||
entityPacket.getIntegers().write(2, (int) (vector.getY() * 8000));
|
||||
entityPacket.getIntegers().write(3, (int) (vector.getZ() * 8000));
|
||||
return entityPacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DataWatcher for a given ItemStack.
|
||||
*
|
||||
* @param itemStack The ItemStack to create the DataWatcher for
|
||||
* @return The created DataWatcher
|
||||
*/
|
||||
public static WrappedDataWatcher createDataWatcher(ItemStack itemStack) {
|
||||
WrappedDataWatcher wrappedDataWatcher = new WrappedDataWatcher();
|
||||
wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(8, WrappedDataWatcher.Registry.getItemStackSerializer(false)), itemStack);
|
||||
wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(5, WrappedDataWatcher.Registry.get(Boolean.class)), true);
|
||||
return wrappedDataWatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value list in a PacketContainer's DataWatcher from a WrappedDataWatcher.
|
||||
*
|
||||
* @param metaPacket The PacketContainer representing the metadata packet
|
||||
* @param wrappedDataWatcher The WrappedDataWatcher containing the value list
|
||||
*/
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
private static void setValueList(PacketContainer metaPacket, WrappedDataWatcher wrappedDataWatcher) {
|
||||
List<WrappedDataValue> wrappedDataValueList = Lists.newArrayList();
|
||||
wrappedDataWatcher.getWatchableObjects().stream().filter(Objects::nonNull).forEach(entry -> {
|
||||
final WrappedDataWatcher.WrappedDataWatcherObject dataWatcherObject = entry.getWatcherObject();
|
||||
wrappedDataValueList.add(new WrappedDataValue(dataWatcherObject.getIndex(), dataWatcherObject.getSerializer(), entry.getRawValue()));
|
||||
});
|
||||
metaPacket.getDataValueCollectionModifier().write(0, wrappedDataValueList);
|
||||
}
|
||||
}
|
||||
@@ -1,502 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customfishing.bukkit.util;
|
||||
|
||||
import de.tr7zw.changeme.nbtapi.NBTCompound;
|
||||
import de.tr7zw.changeme.nbtapi.NBTItem;
|
||||
import de.tr7zw.changeme.nbtapi.NBTList;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.ScoreComponent;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import net.momirealms.customfishing.api.common.Pair;
|
||||
import net.momirealms.customfishing.api.mechanic.hook.HookConfigImpl;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerItemDamageEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.inventory.meta.Damageable;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.util.io.BukkitObjectInputStream;
|
||||
import org.bukkit.util.io.BukkitObjectOutputStream;
|
||||
import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Utility class for various item-related operations.
|
||||
*/
|
||||
public class ItemUtils {
|
||||
|
||||
private ItemUtils() {}
|
||||
|
||||
/**
|
||||
* Updates the lore of an NBTItem based on its custom NBT tags.
|
||||
*
|
||||
* @param nbtItem The NBTItem to update
|
||||
* @return The updated NBTItem
|
||||
*/
|
||||
public static NBTItem updateNBTItemLore(NBTItem nbtItem) {
|
||||
NBTCompound cfCompound = nbtItem.getCompound("CustomFishing");
|
||||
if (cfCompound == null)
|
||||
return nbtItem;
|
||||
|
||||
NBTCompound displayCompound = nbtItem.getOrCreateCompound("display");
|
||||
NBTList<String> lore = displayCompound.getStringList("Lore");
|
||||
lore.removeIf(it -> GsonComponentSerializer.gson().deserialize(it) instanceof ScoreComponent scoreComponent && scoreComponent.name().equals("cf"));
|
||||
|
||||
if (cfCompound.hasTag("hook_id")) {
|
||||
String hookID = cfCompound.getString("hook_id");
|
||||
HookConfigImpl setting = BukkitCustomFishingPlugin.get().getHookManager().getHookSetting(hookID);
|
||||
if (setting == null) {
|
||||
cfCompound.removeKey("hook_id");
|
||||
cfCompound.removeKey("hook_item");
|
||||
cfCompound.removeKey("hook_dur");
|
||||
} else {
|
||||
for (String newLore : setting.lore()) {
|
||||
ScoreComponent.Builder builder = Component.score().name("cf").objective("hook");
|
||||
builder.append(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
newLore.replace("{dur}", String.valueOf(cfCompound.getInteger("hook_dur")))
|
||||
.replace("{max}", String.valueOf(setting.maxDurability()))
|
||||
));
|
||||
lore.add(GsonComponentSerializer.gson().serialize(builder.build()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cfCompound.hasTag("max_dur")) {
|
||||
int max = cfCompound.getInteger("max_dur");
|
||||
int current = cfCompound.getInteger("cur_dur");
|
||||
for (String newLore : CFConfig.durabilityLore) {
|
||||
ScoreComponent.Builder builder = Component.score().name("cf").objective("durability");
|
||||
builder.append(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
newLore.replace("{dur}", String.valueOf(current))
|
||||
.replace("{max}", String.valueOf(max))
|
||||
));
|
||||
lore.add(GsonComponentSerializer.gson().serialize(builder.build()));
|
||||
}
|
||||
}
|
||||
return nbtItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the lore of an ItemStack based on its custom NBT tags.
|
||||
*
|
||||
* @param itemStack The ItemStack to update
|
||||
*/
|
||||
public static void updateItemLore(ItemStack itemStack) {
|
||||
if (itemStack == null || itemStack.getType() == Material.AIR)
|
||||
return;
|
||||
NBTItem nbtItem = updateNBTItemLore(new NBTItem(itemStack));
|
||||
itemStack.setItemMeta(nbtItem.getItem().getItemMeta());
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduces the durability of a fishing hook item.
|
||||
*
|
||||
* @param rod The fishing rod ItemStack
|
||||
* @param updateLore Whether to update the lore after reducing durability
|
||||
*/
|
||||
public static void decreaseHookDurability(ItemStack rod, int amount, boolean updateLore) {
|
||||
if (rod == null || rod.getType() != Material.FISHING_ROD)
|
||||
return;
|
||||
NBTItem nbtItem = new NBTItem(rod);
|
||||
NBTCompound cfCompound = nbtItem.getCompound("CustomFishing");
|
||||
if (cfCompound != null && cfCompound.hasTag("hook_dur")) {
|
||||
int hookDur = cfCompound.getInteger("hook_dur");
|
||||
if (hookDur != -1) {
|
||||
hookDur = Math.max(0, hookDur - amount);
|
||||
if (hookDur > 0) {
|
||||
cfCompound.setInteger("hook_dur", hookDur);
|
||||
} else {
|
||||
cfCompound.removeKey("hook_id");
|
||||
cfCompound.removeKey("hook_dur");
|
||||
cfCompound.removeKey("hook_item");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (updateLore) updateNBTItemLore(nbtItem);
|
||||
rod.setItemMeta(nbtItem.getItem().getItemMeta());
|
||||
}
|
||||
|
||||
/**
|
||||
* Increases the durability of a fishing hook by a specified amount and optionally updates its lore.
|
||||
*
|
||||
* @param rod The fishing rod ItemStack to modify.
|
||||
* @param amount The amount by which to increase the durability.
|
||||
* @param updateLore Whether to update the lore of the fishing rod.
|
||||
*/
|
||||
public static void increaseHookDurability(ItemStack rod, int amount, boolean updateLore) {
|
||||
if (rod == null || rod.getType() != Material.FISHING_ROD)
|
||||
return;
|
||||
NBTItem nbtItem = new NBTItem(rod);
|
||||
NBTCompound cfCompound = nbtItem.getCompound("CustomFishing");
|
||||
if (cfCompound != null && cfCompound.hasTag("hook_dur")) {
|
||||
int hookDur = cfCompound.getInteger("hook_dur");
|
||||
if (hookDur != -1) {
|
||||
String id = cfCompound.getString("hook_id");
|
||||
HookConfigImpl setting = BukkitCustomFishingPlugin.get().getHookManager().getHookSetting(id);
|
||||
if (setting == null) {
|
||||
cfCompound.removeKey("hook_id");
|
||||
cfCompound.removeKey("hook_dur");
|
||||
cfCompound.removeKey("hook_item");
|
||||
} else {
|
||||
hookDur = Math.min(setting.maxDurability(), hookDur + amount);
|
||||
cfCompound.setInteger("hook_dur", hookDur);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (updateLore) updateNBTItemLore(nbtItem);
|
||||
rod.setItemMeta(nbtItem.getItem().getItemMeta());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the durability of a fishing hook to a specific amount and optionally updates its lore.
|
||||
*
|
||||
* @param rod The fishing rod ItemStack to modify.
|
||||
* @param amount The new durability value to set.
|
||||
* @param updateLore Whether to update the lore of the fishing rod.
|
||||
*/
|
||||
public static void setHookDurability(ItemStack rod, int amount, boolean updateLore) {
|
||||
if (rod == null || rod.getType() != Material.FISHING_ROD)
|
||||
return;
|
||||
NBTItem nbtItem = new NBTItem(rod);
|
||||
NBTCompound cfCompound = nbtItem.getCompound("CustomFishing");
|
||||
if (cfCompound != null && cfCompound.hasTag("hook_dur")) {
|
||||
int hookDur = cfCompound.getInteger("hook_dur");
|
||||
if (hookDur != -1) {
|
||||
String id = cfCompound.getString("hook_id");
|
||||
HookConfigImpl setting = BukkitCustomFishingPlugin.get().getHookManager().getHookSetting(id);
|
||||
if (setting == null) {
|
||||
cfCompound.removeKey("hook_id");
|
||||
cfCompound.removeKey("hook_dur");
|
||||
cfCompound.removeKey("hook_item");
|
||||
} else {
|
||||
hookDur = Math.min(setting.maxDurability(), amount);
|
||||
cfCompound.setInteger("hook_dur", hookDur);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (updateLore) updateNBTItemLore(nbtItem);
|
||||
rod.setItemMeta(nbtItem.getItem().getItemMeta());
|
||||
}
|
||||
|
||||
/**
|
||||
* Decreases the durability of an item and updates its lore.
|
||||
*
|
||||
* @param itemStack The ItemStack to reduce durability for
|
||||
* @param amount The amount by which to reduce durability
|
||||
* @param updateLore Whether to update the lore after reducing durability
|
||||
*/
|
||||
public static void decreaseDurability(Player player, ItemStack itemStack, int amount, boolean updateLore) {
|
||||
if (itemStack == null || itemStack.getType() == Material.AIR)
|
||||
return;
|
||||
NBTItem nbtItem = new NBTItem(itemStack);
|
||||
NBTCompound cfCompound = nbtItem.getCompound("CustomFishing");
|
||||
if (cfCompound != null && cfCompound.hasTag("max_dur")) {
|
||||
int unBreakingLevel = itemStack.getEnchantmentLevel(Enchantment.DURABILITY);
|
||||
if (Math.random() > (double) 1 / (unBreakingLevel + 1)) {
|
||||
return;
|
||||
}
|
||||
if (nbtItem.getByte("Unbreakable") == 1) {
|
||||
return;
|
||||
}
|
||||
int max = cfCompound.getInteger("max_dur");
|
||||
int current = cfCompound.getInteger("cur_dur") - amount;
|
||||
cfCompound.setInteger("cur_dur", current);
|
||||
int damage = (int) (itemStack.getType().getMaxDurability() * (1 - ((double) current / max)));
|
||||
nbtItem.setInteger("Damage", damage);
|
||||
if (current > 0) {
|
||||
if (updateLore) updateNBTItemLore(nbtItem);
|
||||
itemStack.setItemMeta(nbtItem.getItem().getItemMeta());
|
||||
} else {
|
||||
itemStack.setAmount(0);
|
||||
}
|
||||
} else {
|
||||
ItemMeta previousMeta = itemStack.getItemMeta().clone();
|
||||
PlayerItemDamageEvent itemDamageEvent = new PlayerItemDamageEvent(player, itemStack, amount, amount);
|
||||
Bukkit.getPluginManager().callEvent(itemDamageEvent);
|
||||
if (!itemStack.getItemMeta().equals(previousMeta) || itemDamageEvent.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
int unBreakingLevel = itemStack.getEnchantmentLevel(Enchantment.DURABILITY);
|
||||
if (Math.random() > (double) 1 / (unBreakingLevel + 1)) {
|
||||
return;
|
||||
}
|
||||
if (nbtItem.getByte("Unbreakable") == 1) {
|
||||
return;
|
||||
}
|
||||
int damage = nbtItem.getInteger("Damage") + amount;
|
||||
if (damage > itemStack.getType().getMaxDurability()) {
|
||||
itemStack.setAmount(0);
|
||||
} else {
|
||||
nbtItem.setInteger("Damage", damage);
|
||||
if (updateLore) updateNBTItemLore(nbtItem);
|
||||
itemStack.setItemMeta(nbtItem.getItem().getItemMeta());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increases the durability of an item and updates its lore.
|
||||
*
|
||||
* @param itemStack The ItemStack to increase durability for
|
||||
* @param amount The amount by which to increase durability
|
||||
* @param updateLore Whether to update the lore after increasing durability
|
||||
*/
|
||||
public static void increaseDurability(ItemStack itemStack, int amount, boolean updateLore) {
|
||||
if (itemStack == null || itemStack.getType() == Material.AIR)
|
||||
return;
|
||||
NBTItem nbtItem = new NBTItem(itemStack);
|
||||
if (nbtItem.getByte("Unbreakable") == 1) {
|
||||
return;
|
||||
}
|
||||
NBTCompound cfCompound = nbtItem.getCompound("CustomFishing");
|
||||
if (cfCompound != null && cfCompound.hasTag("max_dur")) {
|
||||
int max = cfCompound.getInteger("max_dur");
|
||||
int current = Math.min(max, cfCompound.getInteger("cur_dur") + amount);
|
||||
cfCompound.setInteger("cur_dur", current);
|
||||
int damage = (int) (itemStack.getType().getMaxDurability() * (1 - ((double) current / max)));
|
||||
nbtItem.setInteger("Damage", damage);
|
||||
if (updateLore) updateNBTItemLore(nbtItem);
|
||||
} else {
|
||||
int damage = Math.max(nbtItem.getInteger("Damage") - amount, 0);
|
||||
nbtItem.setInteger("Damage", damage);
|
||||
}
|
||||
itemStack.setItemMeta(nbtItem.getItem().getItemMeta());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the durability of an item and updates its lore.
|
||||
*
|
||||
* @param itemStack The ItemStack to set durability for
|
||||
* @param amount The new durability value
|
||||
* @param updateLore Whether to update the lore after setting durability
|
||||
*/
|
||||
public static void setDurability(ItemStack itemStack, int amount, boolean updateLore) {
|
||||
if (itemStack == null || itemStack.getType() == Material.AIR)
|
||||
return;
|
||||
if (amount <= 0) {
|
||||
itemStack.setAmount(0);
|
||||
return;
|
||||
}
|
||||
NBTItem nbtItem = new NBTItem(itemStack);
|
||||
if (nbtItem.getByte("Unbreakable") == 1) {
|
||||
return;
|
||||
}
|
||||
NBTCompound cfCompound = nbtItem.getCompound("CustomFishing");
|
||||
if (cfCompound != null && cfCompound.hasTag("max_dur")) {
|
||||
int max = cfCompound.getInteger("max_dur");
|
||||
amount = Math.min(amount, max);
|
||||
cfCompound.setInteger("cur_dur", amount);
|
||||
int damage = (int) (itemStack.getType().getMaxDurability() * (1 - ((double) amount / max)));
|
||||
nbtItem.setInteger("Damage", damage);
|
||||
if (updateLore) updateNBTItemLore(nbtItem);
|
||||
} else {
|
||||
nbtItem.setInteger("Damage", itemStack.getType().getMaxDurability() - amount);
|
||||
}
|
||||
itemStack.setItemMeta(nbtItem.getItem().getItemMeta());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current durability of an item.
|
||||
*
|
||||
* @param itemStack The ItemStack to get durability from
|
||||
* @return The current durability value
|
||||
*/
|
||||
public static Pair<Integer, Integer> getCustomDurability(ItemStack itemStack) {
|
||||
if (itemStack == null || itemStack.getType() == Material.AIR)
|
||||
return Pair.of(0, 0);
|
||||
if (itemStack.getItemMeta() instanceof Damageable damageable && damageable.isUnbreakable())
|
||||
return Pair.of(-1, -1);
|
||||
NBTItem nbtItem = new NBTItem(itemStack);
|
||||
NBTCompound cfCompound = nbtItem.getCompound("CustomFishing");
|
||||
if (cfCompound != null && cfCompound.hasTag("max_dur")) {
|
||||
return Pair.of(cfCompound.getInteger("max_dur"), cfCompound.getInteger("cur_dur"));
|
||||
} else {
|
||||
return Pair.of(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives a certain amount of an item to a player, handling stacking and item drops.
|
||||
*
|
||||
* @param player The player to give the item to
|
||||
* @param itemStack The ItemStack to give
|
||||
* @param amount The amount of items to give
|
||||
* @return The actual amount of items given
|
||||
*/
|
||||
public static int giveItem(Player player, ItemStack itemStack, int amount) {
|
||||
PlayerInventory inventory = player.getInventory();
|
||||
ItemMeta meta = itemStack.getItemMeta();
|
||||
int maxStackSize = itemStack.getMaxStackSize();
|
||||
|
||||
if (amount > maxStackSize * 100) {
|
||||
LogUtils.warn("Detected too many items spawning. Lowering the amount to " + (maxStackSize * 100));
|
||||
amount = maxStackSize * 100;
|
||||
}
|
||||
|
||||
int actualAmount = amount;
|
||||
|
||||
for (ItemStack other : inventory.getStorageContents()) {
|
||||
if (other != null) {
|
||||
if (other.getType() == itemStack.getType() && other.getItemMeta().equals(meta)) {
|
||||
if (other.getAmount() < maxStackSize) {
|
||||
int delta = maxStackSize - other.getAmount();
|
||||
if (amount > delta) {
|
||||
other.setAmount(maxStackSize);
|
||||
amount -= delta;
|
||||
} else {
|
||||
other.setAmount(amount + other.getAmount());
|
||||
return actualAmount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (amount > 0) {
|
||||
for (ItemStack other : inventory.getStorageContents()) {
|
||||
if (other == null) {
|
||||
if (amount > maxStackSize) {
|
||||
amount -= maxStackSize;
|
||||
ItemStack cloned = itemStack.clone();
|
||||
cloned.setAmount(maxStackSize);
|
||||
inventory.addItem(cloned);
|
||||
} else {
|
||||
ItemStack cloned = itemStack.clone();
|
||||
cloned.setAmount(amount);
|
||||
inventory.addItem(cloned);
|
||||
return actualAmount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (amount > 0) {
|
||||
for (int i = 0; i < amount / maxStackSize; i++) {
|
||||
ItemStack cloned = itemStack.clone();
|
||||
cloned.setAmount(maxStackSize);
|
||||
player.getWorld().dropItem(player.getLocation(), cloned);
|
||||
}
|
||||
int left = amount % maxStackSize;
|
||||
if (left != 0) {
|
||||
ItemStack cloned = itemStack.clone();
|
||||
cloned.setAmount(left);
|
||||
player.getWorld().dropItem(player.getLocation(), cloned);
|
||||
}
|
||||
}
|
||||
|
||||
return actualAmount;
|
||||
}
|
||||
|
||||
public static String toBase64(ItemStack itemStack) {
|
||||
if (itemStack == null || itemStack.getType() == Material.AIR)
|
||||
return "";
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
try (BukkitObjectOutputStream dataOutput = new BukkitObjectOutputStream(outputStream)) {
|
||||
dataOutput.writeObject(itemStack);
|
||||
byte[] byteArr = outputStream.toByteArray();
|
||||
dataOutput.close();
|
||||
outputStream.close();
|
||||
return Base64Coder.encodeLines(byteArr);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public static ItemStack fromBase64(String base64) {
|
||||
if (base64 == null || base64.equals(""))
|
||||
return new ItemStack(Material.AIR);
|
||||
ByteArrayInputStream inputStream;
|
||||
try {
|
||||
inputStream = new ByteArrayInputStream(Base64Coder.decodeLines(base64));
|
||||
} catch (IllegalArgumentException e) {
|
||||
return new ItemStack(Material.AIR);
|
||||
}
|
||||
ItemStack stack = null;
|
||||
try (BukkitObjectInputStream dataInput = new BukkitObjectInputStream(inputStream)) {
|
||||
stack = (ItemStack) dataInput.readObject();
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
public static ItemStack removeOwner(ItemStack itemStack) {
|
||||
if (itemStack == null || itemStack.getType() == Material.AIR) return itemStack;
|
||||
NBTItem nbtItem = new NBTItem(itemStack);
|
||||
if (nbtItem.hasTag("owner")) {
|
||||
nbtItem.removeKey("owner");
|
||||
return nbtItem.getItem();
|
||||
}
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the amount of items that can't be put in the inventory
|
||||
*/
|
||||
public static int putLootsToBag(Inventory inventory, ItemStack itemStack, int amount) {
|
||||
itemStack = removeOwner(itemStack.clone());
|
||||
ItemMeta meta = itemStack.getItemMeta();
|
||||
int maxStackSize = itemStack.getMaxStackSize();
|
||||
for (ItemStack other : inventory.getStorageContents()) {
|
||||
if (other != null) {
|
||||
if (other.getType() == itemStack.getType() && other.getItemMeta().equals(meta)) {
|
||||
if (other.getAmount() < maxStackSize) {
|
||||
int delta = maxStackSize - other.getAmount();
|
||||
if (amount > delta) {
|
||||
other.setAmount(maxStackSize);
|
||||
amount -= delta;
|
||||
} else {
|
||||
other.setAmount(amount + other.getAmount());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (amount > 0) {
|
||||
for (ItemStack other : inventory.getStorageContents()) {
|
||||
if (other == null) {
|
||||
if (amount > maxStackSize) {
|
||||
amount -= maxStackSize;
|
||||
ItemStack cloned = itemStack.clone();
|
||||
cloned.setAmount(maxStackSize);
|
||||
inventory.addItem(cloned);
|
||||
} else {
|
||||
ItemStack cloned = itemStack.clone();
|
||||
cloned.setAmount(amount);
|
||||
inventory.addItem(cloned);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return amount;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,4 @@
|
||||
# Developer: @Xiao-MoMi
|
||||
# Wiki: https://mo-mi.gitbook.io/xiaomomi-plugins/
|
||||
config-version: '32'
|
||||
config-version: '${config_version}'
|
||||
|
||||
# Debug
|
||||
debug: false
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
config-version: '${config_version}'
|
||||
|
||||
# file:
|
||||
# JSON
|
||||
# YAML
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
config-version: '${config_version}'
|
||||
|
||||
enable: true
|
||||
|
||||
# Container title
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
# Don't change this
|
||||
config-version: '31'
|
||||
|
||||
messages:
|
||||
prefix: '<gradient:#0070B3:#A0EACF>[CustomFishing] </gradient>'
|
||||
reload: '<white>Reloaded. Took <green>{time}ms.'
|
||||
item-not-exist: 'Item not found.'
|
||||
give-item: 'Successfully given player {player} {amount}x {item}.'
|
||||
get-item: 'Successfully got {amount}x {item}.'
|
||||
possible-loots: 'Possible loots here: '
|
||||
split-char: ', '
|
||||
competition-not-exist: 'Competition {id} does not exist.'
|
||||
no-competition-ongoing: "There's no competition ongoing."
|
||||
stop-competition: 'Stopped the current competition.'
|
||||
end-competition: 'Ended the current competition.'
|
||||
no-score: 'No Score'
|
||||
no-player: 'No Player'
|
||||
no-rank: 'No Rank'
|
||||
goal-catch-amount: 'Fish count caught'
|
||||
goal-max-size: 'Largest fish caught'
|
||||
goal-total-size: 'Total length of fish caught'
|
||||
goal-total-score: 'Cumulative score of fish caught'
|
||||
unsafe-modification: "Cannot modify a player's fishing bag if they're active on another linked server."
|
||||
never-played: "The player hasn't joined the server before. Can't modify a nonexistent player's fishing bag."
|
||||
data-not-loaded: "<red>Data hasn't loaded. Please re-enter the server. If issues persist, reach out to the server admin."
|
||||
open-market-gui: "Successfully opened the market gui for {player}"
|
||||
open-fishing-bag: "Successfully opened the fishing bag for {player}"
|
||||
format-day: 'd'
|
||||
format-hour: 'h'
|
||||
format-minute: 'm'
|
||||
format-second: 's'
|
||||
|
||||
gui:
|
||||
search: "Search"
|
||||
select-file: 'Select file'
|
||||
select-item: "Select item"
|
||||
dupe-invalid-key: "<red>● Duplicated or invalid key"
|
||||
new-value: "New value: "
|
||||
temp-new-key: 'New key'
|
||||
set-new-key: "Set new key"
|
||||
edit-key: 'Edit {0}'
|
||||
delete-property: "<#00CED1>● Delete property"
|
||||
click-confirm: "<#00FF7F> -> Click to confirm"
|
||||
invalid-number: "<red>● Invalid number"
|
||||
illegal-format: "<red>● Illegal format"
|
||||
scroll-up: '<gray>● Scroll up'
|
||||
scroll-down: '<gray>● Scroll down'
|
||||
cannot-scroll-up: "<red>You've reached the top"
|
||||
cannot-scroll-down: "<red>You can't scroll further down"
|
||||
next-page: '<gray>● Next Page'
|
||||
goto-next-page: '<gray>Go to page <yellow>{0} <gray>/ <yellow>{1}'
|
||||
cannot-goto-next-page: '<red>There are no more pages'
|
||||
previous-page: '<gray>● Previous page'
|
||||
goto-previous-page: '<gray>Go to page <yellow>{0} <gray>/ <yellow>{1}'
|
||||
cannot-goto-previous-page: "<red>You can't go further back"
|
||||
back-to-parent-page: "<#FF8C00>Back to parent page"
|
||||
back-to-parent-folder: "<#FF8C00>Back to parent folder"
|
||||
current-value: "<gray>Current value: <white>"
|
||||
click-to-toggle: "<#00FF7F> -> Click to toggle"
|
||||
left-click-edit: "<#00FF7F> -> Left click to edit"
|
||||
right-click-reset: "<#FF6347> -> Right click to reset"
|
||||
right-click-delete: "<#FF6347> -> Right click to delete"
|
||||
right-click-cancel: "<#00CED1> -> Right click to cancel"
|
||||
loot-show-in-finder: "<#5F9EA0>● Show In Fish Finder"
|
||||
loot-score: "<#FF1493>● Score"
|
||||
loot-nick: "<#00FF00>● Nick"
|
||||
loot-instant-game: "<#7B68EE>● Instant Game"
|
||||
loot-disable-statistics: "<#CD853F>● Disable Statistics"
|
||||
loot-disable-game: "<#8B4513>● Disable Game"
|
||||
item-amount: "<#1E90FF>● Amount"
|
||||
item-custom-model-data: "<#FFC0CB>● Custom Model Data"
|
||||
item-display-name: "<#FAFAD2>● Display Name"
|
||||
item-custom-durability: "<#1E90FF>● Custom Durability"
|
||||
item-enchantment: "<#8A2BE2>● Enchantment"
|
||||
item-head64: "<#2E8B57>● Head64"
|
||||
item-item-flag: "<#E6E6FA>● Item Flag"
|
||||
item-lore: "<#FA8072>● Lore"
|
||||
item-material: "<#FF00FF>● Material"
|
||||
item-nbt: "<#FA8072>● NBT"
|
||||
item-prevent-grab: "<#FF4500>● Prevent Grabbing"
|
||||
item-price: "<#FFD700>● Price"
|
||||
item-price-base: "<gray> - base: <white>"
|
||||
item-price-bonus: "<gray> - bonus: <white>"
|
||||
item-random-durability: "<#FFFF00>● Random Durability"
|
||||
item-size: "<#FFF0F5>● Size"
|
||||
item-stackable: "<#9370DB>● Stackable"
|
||||
item-stored-enchantment: "<#9370DB>● Stored Enchantment"
|
||||
item-tag: "<#2E8B57>● Tag"
|
||||
item-unbreakable: "<#C0C0C0>● Unbreakable"
|
||||
page-amount-title: "Edit Amount"
|
||||
page-model-data-title: "Edit CustomModelData"
|
||||
page-display-name-title: "Edit display name"
|
||||
page-new-display-name: "New name"
|
||||
page-custom-durability-title: "Edit custom durability"
|
||||
page-stored-enchantment-title: "Edit stored enchantment"
|
||||
page-enchantment-title: "Edit enchantment"
|
||||
page-select-one-enchantment: "Select one enchantment"
|
||||
page-add-new-enchantment: "<green>[+] <gray>Add a new enchantment"
|
||||
page-item-flag-title: "Edit item flag"
|
||||
page-lore-title: "Edit lore"
|
||||
page-add-new-lore: "<green>[+] <gray>Add a new line"
|
||||
page-select-one-lore: "Select one line"
|
||||
page-material-title: "Edit Material"
|
||||
page-nbt-compound-key-title: "Edit compound key"
|
||||
page-nbt-list-key-title: "Edit list key"
|
||||
page-nbt-key-title: "Edit key"
|
||||
page-nbt-invalid-key: "<red>Invaild key"
|
||||
page-nbt-add-new-compound: "<green>[+] <gray>Add a new compound"
|
||||
page-nbt-add-new-list: "<green>[+] <gray>Add a new list"
|
||||
page-nbt-add-new-value: "<green>[+] <gray>Add a new value"
|
||||
page-add-new-key: "<green>[+] <gray>Add a new key"
|
||||
page-nbt-preview: "<green>● NBT Preview"
|
||||
page-nbt-back-to-compound: "<gray>Back to parent compound"
|
||||
page-nbt-set-value-title: "Set value"
|
||||
page-nbt-edit-title: "Edit NBT"
|
||||
page-nick-title: "Edit nick"
|
||||
page-new-nick: "New nick"
|
||||
page-price-title: "Edit price"
|
||||
page-base-price: "Base"
|
||||
page-base-bonus: "Bonus"
|
||||
page-score-title: "Edit score"
|
||||
page-size-title: "Edit size"
|
||||
page-size-min: "Minimum"
|
||||
page-size-max: "Maximum"
|
||||
page-size-max-no-less-min: "<red>● Max must be no less than min"
|
||||
@@ -1,125 +0,0 @@
|
||||
# Don't change this
|
||||
config-version: '31'
|
||||
|
||||
messages:
|
||||
prefix: '<gradient:#0070B3:#A0EACF>[CustomFishing] </gradient>'
|
||||
reload: '<white>Recargado! Tardó <green>{time}ms.'
|
||||
item-not-exist: 'Item no encontrado.'
|
||||
give-item: 'Se ha entregado {amount}x {item} al jugador {player}.'
|
||||
get-item: 'Se ha recibido {amount}x {item}.'
|
||||
possible-loots: 'Posibles recompensas: '
|
||||
split-char: ', '
|
||||
competition-not-exist: 'La Competición {id} no existe.'
|
||||
no-competition-ongoing: "No hay una competencia activa."
|
||||
stop-competition: 'Se ha detenido la competición.'
|
||||
end-competition: 'Ha finalizado la competición.'
|
||||
no-score: 'Sin puntaje'
|
||||
no-player: 'Sin jugador'
|
||||
no-rank: 'Sin rango'
|
||||
goal-catch-amount: 'Peces atrapados'
|
||||
goal-max-size: 'Pez más grande capturado'
|
||||
goal-total-size: 'Longitud total de peces capturados'
|
||||
goal-total-score: 'Puntaje acumulado por peces capturados'
|
||||
unsafe-modification: "No se puede modificar la bolsa de pesca de un jugador si sigue activo en otro servidor vinculado."
|
||||
never-played: "Este jugador nunca se ha unido al servidor. No puedes modificar la bolsa de pesca de un jugador inexistente."
|
||||
data-not-loaded: "<red>No se pudo cargar la información. Por favor, vuelve a ingresar al servidor. Si el problema persiste, contacta a un administrador."
|
||||
open-market-gui: "Se ha abierto la interfaz para {player}"
|
||||
open-fishing-bag: "Se ha abierto la bolsa de pesca de {player}"
|
||||
format-day: 'd'
|
||||
format-hour: 'h'
|
||||
format-minute: 'm'
|
||||
format-second: 's'
|
||||
|
||||
gui:
|
||||
search: "Buscar"
|
||||
select-file: 'Seleccionar archivo'
|
||||
select-item: "Seleccionar item"
|
||||
dupe-invalid-key: "<red>● ID inválida o duplicada"
|
||||
new-value: "Nuevo valor: "
|
||||
temp-new-key: 'Nueva ID'
|
||||
set-new-key: "Definir nueva ID"
|
||||
edit-key: 'Editar {0}'
|
||||
delete-property: "<#00CED1>● Eliminar propiedad"
|
||||
click-confirm: "<#00FF7F> -> Click para confirmar"
|
||||
invalid-number: "<red>● Número inválido"
|
||||
illegal-format: "<red>● Formato inválido"
|
||||
scroll-up: '<gray>● Arriba'
|
||||
scroll-down: '<gray>● Abajo'
|
||||
cannot-scroll-up: "<red>Estás en el límite superior"
|
||||
cannot-scroll-down: "<red>Estás en el límite inferior"
|
||||
next-page: '<gray>● Siguiente Página'
|
||||
goto-next-page: '<gray>Ir a la página <yellow>{0} <gray>/ <yellow>{1}'
|
||||
cannot-goto-next-page: '<red>No hay más páginas'
|
||||
previous-page: '<gray>● Página anterior'
|
||||
goto-previous-page: '<gray>Ir a la página <yellow>{0} <gray>/ <yellow>{1}'
|
||||
cannot-goto-previous-page: "<red>No hay más páginas atrás"
|
||||
back-to-parent-page: "<#FF8C00>Volver al menú anterior"
|
||||
back-to-parent-folder: "<#FF8C00>Volver a la carpeta anterior"
|
||||
current-value: "<gray>Valor actual: <white>"
|
||||
click-to-toggle: "<#00FF7F> -> Click para cambiar"
|
||||
left-click-edit: "<#00FF7F> -> Click izquierdo para editar"
|
||||
right-click-reset: "<#FF6347> -> Click derecho para restablecer"
|
||||
right-click-delete: "<#FF6347> -> Click derecho para eliminar"
|
||||
right-click-cancel: "<#00CED1> -> Click derecho para cancelar"
|
||||
loot-show-in-finder: "<#5F9EA0>● Mostar en el rastreador de peces"
|
||||
loot-score: "<#FF1493>● Puntaje"
|
||||
loot-nick: "<#00FF00>● Apodo"
|
||||
loot-instant-game: "<#7B68EE>● Juego Instantáneo"
|
||||
loot-disable-statistics: "<#CD853F>● Deshabilitar Estadísticas"
|
||||
loot-disable-game: "<#8B4513>● Deshabilitar Juego"
|
||||
item-amount: "<#1E90FF>● Cantidad"
|
||||
item-custom-model-data: "<#FFC0CB>● Custom Model Data"
|
||||
item-display-name: "<#FAFAD2>● Nombre a mostrar"
|
||||
item-custom-durability: "<#1E90FF>● Durabilidad"
|
||||
item-enchantment: "<#8A2BE2>● Encantamiento"
|
||||
item-head64: "<#2E8B57>● Head64"
|
||||
item-item-flag: "<#E6E6FA>● Item Flag"
|
||||
item-lore: "<#FA8072>● Descripción"
|
||||
item-material: "<#FF00FF>● Material"
|
||||
item-nbt: "<#FA8072>● NBT"
|
||||
item-prevent-grab: "<#FF4500>● Evitar recoger item"
|
||||
item-price: "<#FFD700>● Precio"
|
||||
item-price-base: "<gray> - base: <white>"
|
||||
item-price-bonus: "<gray> - bonus: <white>"
|
||||
item-random-durability: "<#FFFF00>● Durabilidad Aleatoria"
|
||||
item-size: "<#FFF0F5>● Tamaño"
|
||||
item-stackable: "<#9370DB>● Acumulable"
|
||||
item-stored-enchantment: "<#9370DB>● Encantamiento Almacenado"
|
||||
item-tag: "<#2E8B57>● Etiqueta"
|
||||
item-unbreakable: "<#C0C0C0>● Irrompible"
|
||||
page-amount-title: "Editar Cantidad"
|
||||
page-model-data-title: "Editar CustomModelData"
|
||||
page-display-name-title: "Editar nombre a mostrar"
|
||||
page-new-display-name: "Nuevo nombre"
|
||||
page-custom-durability-title: "Edit durabilidad"
|
||||
page-stored-enchantment-title: "Edit encantamiento almacenado"
|
||||
page-enchantment-title: "Editar enchantmentamiento"
|
||||
page-select-one-enchantment: "Seleccionar un encantamiento"
|
||||
page-add-new-enchantment: "<green>[+] <gray>Añadir un encantamiento"
|
||||
page-item-flag-title: "Editar item flag"
|
||||
page-lore-title: "Editar descripción"
|
||||
page-add-new-lore: "<green>[+] <gray>Añadir nueva línea"
|
||||
page-select-one-lore: "Seleccionar una línea"
|
||||
page-material-title: "Editar Material"
|
||||
page-nbt-compound-key-title: "Editar ID de NBT compuesta"
|
||||
page-nbt-list-key-title: "Editar lista de IDs"
|
||||
page-nbt-key-title: "Editar ID"
|
||||
page-nbt-invalid-key: "<red>ID inválida"
|
||||
page-nbt-add-new-compound: "<green>[+] <gray>Añadir nueva NBT compuesta"
|
||||
page-nbt-add-new-list: "<green>[+] <gray>Añadir nueva lista"
|
||||
page-nbt-add-new-value: "<green>[+] <gray>Añadir nuevo valor"
|
||||
page-add-new-key: "<green>[+] <gray>Añadir nueva ID"
|
||||
page-nbt-preview: "<green>● Vista previa de NBT"
|
||||
page-nbt-back-to-compound: "<gray>Volver al compuesto padre"
|
||||
page-nbt-set-value-title: "Definir nuevo valor"
|
||||
page-nbt-edit-title: "Editar NBT"
|
||||
page-nick-title: "Editar apodo"
|
||||
page-new-nick: "Nuevo apodo"
|
||||
page-price-title: "Editar precio"
|
||||
page-base-price: "Base"
|
||||
page-base-bonus: "Bonus"
|
||||
page-score-title: "Editar puntuación"
|
||||
page-size-title: "Editar tamaño"
|
||||
page-size-min: "Mínimo"
|
||||
page-size-max: "Máximo"
|
||||
page-size-max-no-less-min: "<red>● El valor máximo no puede ser inferior al mínimo"
|
||||
@@ -1,125 +0,0 @@
|
||||
# Don't change this
|
||||
config-version: '30'
|
||||
|
||||
messages:
|
||||
prefix: '<gradient:#0070B3:#A0EACF>[CustomFishing] </gradient>'
|
||||
reload: '<white>Rechargé. A pris <green>{time}ms.</green>'
|
||||
item-not-exist: 'Objet non trouvé.'
|
||||
give-item: 'Joueur {player} a reçu avec succès {amount}x {item}.'
|
||||
get-item: 'A obtenu avec succès {amount}x {item}.'
|
||||
possible-loots: 'Butins possibles ici : '
|
||||
split-char: ', '
|
||||
competition-not-exist: "La compétition {id} n'existe pas."
|
||||
no-competition-ongoing: 'Aucune compétition en cours.'
|
||||
stop-competition: 'Compétition actuelle arrêtée.'
|
||||
end-competition: 'Compétition actuelle terminée.'
|
||||
no-score: 'Pas de score'
|
||||
no-player: 'Pas de joueur'
|
||||
no-rank: 'Pas de classement'
|
||||
goal-catch-amount: 'Nombre de poissons attrapés'
|
||||
goal-max-size: 'Plus gros poisson attrapé'
|
||||
goal-total-size: 'Longueur totale des poissons attrapés'
|
||||
goal-total-score: 'Score cumulatif des poissons attrapés'
|
||||
unsafe-modification: "Impossible de modifier le sac de pêche d'un joueur s'il est actif sur un autre serveur lié."
|
||||
never-played: "Le joueur n'a jamais rejoint le serveur auparavant. Impossible de modifier le sac de pêche d'un joueur inexistant."
|
||||
data-not-loaded: "<red>Les données n'ont pas été chargées. Veuillez réessayer de rejoindre le serveur. Si les problèmes persistent, contactez l'administrateur du serveur."
|
||||
open-market-gui: "L'interface du marché a été ouverte avec succès pour {player}."
|
||||
open-fishing-bag: "Le sac de pêche de {player} a été ouvert avec succès."
|
||||
format-day: 'j'
|
||||
format-hour: 'h'
|
||||
format-minute: 'm'
|
||||
format-second: 's'
|
||||
|
||||
gui:
|
||||
search: "Rechercher"
|
||||
select-file: "Sélectionner un fichier"
|
||||
select-item: "Sélectionner un élément"
|
||||
dupe-invalid-key: "<red>● Clé en double ou invalide"
|
||||
new-value: "Nouvelle valeur : "
|
||||
temp-new-key: "Nouvelle clé"
|
||||
set-new-key: "Définir une nouvelle clé"
|
||||
edit-key: "Modifier {0}"
|
||||
delete-property: "<#00CED1>● Supprimer la propriété"
|
||||
click-confirm: "<#00FF7F> -> Cliquez pour confirmer"
|
||||
invalid-number: "<red>● Nombre invalide"
|
||||
illegal-format: "<red>● Format illégal"
|
||||
scroll-up: "<gray>● Faire défiler vers le haut"
|
||||
scroll-down: "<gray>● Faire défiler vers le bas"
|
||||
cannot-scroll-up: "<red>Vous avez atteint le haut"
|
||||
cannot-scroll-down: "<red>Vous ne pouvez pas faire défiler plus bas"
|
||||
next-page: "<gray>● Page suivante"
|
||||
goto-next-page: "<gray>Aller à la page <yellow>{0} <gray>/ <yellow>{1}"
|
||||
cannot-goto-next-page: "<red>Il n'y a plus de pages"
|
||||
previous-page: "<gray>● Page précédente"
|
||||
goto-previous-page: "<gray>Aller à la page <yellow>{0} <gray>/ <yellow>{1}"
|
||||
cannot-goto-previous-page: "<red>Vous ne pouvez pas revenir en arrière"
|
||||
back-to-parent-page: "<#FF8C00>Retour à la page parente"
|
||||
back-to-parent-folder: "<#FF8C00>Retour au dossier parent"
|
||||
current-value: "<gray>Valeur actuelle : <white>"
|
||||
click-to-toggle: "<#00FF7F> -> Cliquez pour basculer"
|
||||
left-click-edit: "<#00FF7F> -> Cliquez gauche pour modifier"
|
||||
right-click-reset: "<#FF6347> -> Cliquez droit pour réinitialiser"
|
||||
right-click-delete: "<#FF6347> -> Cliquez droit pour supprimer"
|
||||
right-click-cancel: "<#00CED1> -> Cliquez droit pour annuler"
|
||||
loot-show-in-finder: "<#5F9EA0>● Afficher dans le repère de poisson"
|
||||
loot-score: "<#FF1493>● Score"
|
||||
loot-nick: "<#00FF00>● Surnom"
|
||||
loot-instant-game: "<#7B68EE>● Jeu instantané"
|
||||
loot-disable-statistics: "<#CD853F>● Désactiver les statistiques"
|
||||
loot-disable-game: "<#8B4513>● Désactiver le jeu"
|
||||
item-amount: "<#1E90FF>● Quantité"
|
||||
item-custom-model-data: "<#FFC0CB>● Données de modèle personnalisées"
|
||||
item-display-name: "<#FAFAD2>● Nom affiché"
|
||||
item-custom-durability: "<#1E90FF>● Durabilité personnalisée"
|
||||
item-enchantment: "<#8A2BE2>● Enchantement"
|
||||
item-head64: "<#2E8B57>● Tête64"
|
||||
item-item-flag: "<#E6E6FA>● Drapeau d'élément"
|
||||
item-lore: "<#FA8072>● Légende"
|
||||
item-material: "<#FF00FF>● Matériau"
|
||||
item-nbt: "<#FA8072>● NBT"
|
||||
item-prevent-grab: "<#FF4500>● Empêcher la saisie"
|
||||
item-price: "<#FFD700>● Prix"
|
||||
item-price-base: "<gray> - de base : <white>"
|
||||
item-price-bonus: "<gray> - bonus : <white>"
|
||||
item-random-durability: "<#FFFF00>● Durabilité aléatoire"
|
||||
item-size: "<#FFF0F5>● Taille"
|
||||
item-stackable: "<#9370DB>● Empilable"
|
||||
item-stored-enchantment: "<#9370DB>● Enchantement stocké"
|
||||
item-tag: "<#2E8B57>● Étiquette"
|
||||
item-unbreakable: "<#C0C0C0>● Incassable"
|
||||
page-amount-title: "Modifier la quantité"
|
||||
page-model-data-title: "Modifier CustomModelData"
|
||||
page-display-name-title: "Modifier le nom affiché"
|
||||
page-new-display-name: "Nouveau nom"
|
||||
page-custom-durability-title: "Modifier la durabilité personnalisée"
|
||||
page-stored-enchantment-title: "Modifier l'enchantement stocké"
|
||||
page-enchantment-title: "Modifier l'enchantement"
|
||||
page-select-one-enchantment: "Sélectionner un enchantement"
|
||||
page-add-new-enchantment: "<green>[+] <gray>Ajouter un nouvel enchantement"
|
||||
page-item-flag-title: "Modifier le drapeau d'élément"
|
||||
page-lore-title: "Modifier la légende"
|
||||
page-add-new-lore: "<green>[+] <gray>Ajouter une nouvelle ligne"
|
||||
page-select-one-lore: "Sélectionner une ligne"
|
||||
page-material-title: "Modifier le matériau"
|
||||
page-nbt-compound-key-title: "Modifier la clé composée"
|
||||
page-nbt-list-key-title: "Modifier la clé de liste"
|
||||
page-nbt-key-title: "Modifier la clé"
|
||||
page-nbt-invalid-key: "<red>Clé invalide"
|
||||
page-nbt-add-new-compound: "<green>[+] <gray>Ajouter une nouvelle composante"
|
||||
page-nbt-add-new-list: "<green>[+] <gray>Ajouter une nouvelle liste"
|
||||
page-nbt-add-new-value: "<green>[+] <gray>Ajouter une nouvelle valeur"
|
||||
page-add-new-key: "<green>[+] <gray>Ajouter une nouvelle clé"
|
||||
page-nbt-preview: "<green>● Aperçu NBT"
|
||||
page-nbt-back-to-compound: "<gray>Retour à la composante parente"
|
||||
page-nbt-set-value-title: "Définir la valeur"
|
||||
page-nbt-edit-title: "Modifier NBT"
|
||||
page-nick-title: "Modifier le surnom"
|
||||
page-new-nick: "Nouveau surnom"
|
||||
page-price-title: "Modifier le prix"
|
||||
page-base-price: "De base"
|
||||
page-base-bonus: "Bonus"
|
||||
page-score-title: "Modifier le score"
|
||||
page-size-title: "Modifier la taille"
|
||||
page-size-min: "Minimum"
|
||||
page-size-max: "Maximum"
|
||||
page-size-max-no-less-min: "<red>Le maximum ne doit pas être inférieur au minimum"
|
||||
@@ -1,126 +0,0 @@
|
||||
# Don't change this
|
||||
config-version: '30'
|
||||
|
||||
messages:
|
||||
prefix: '<gradient:#0070B3:#A0EACF>[CustomFishing] </gradient>'
|
||||
reload: '<white>Újratöltve. Időtartam: <green>{time}ms.'
|
||||
item-not-exist: 'Tétel nem található.'
|
||||
give-item: 'Sikeresen adva {player} játékosnak {amount}x {item}.'
|
||||
get-item: 'Sikeresen megszerezve {amount}x {item}.'
|
||||
possible-loots: 'Lehetséges kapások itt: '
|
||||
split-char: ', '
|
||||
competition-not-exist: 'A(z) {id} verseny nem létezik.'
|
||||
no-competition-ongoing: "Nincs folyamatban lévő verseny."
|
||||
stop-competition: 'Leállítottad a jelenlegi versenyt.'
|
||||
end-competition: 'Befejezted a jelenlegi versenyt.'
|
||||
no-score: 'Nincs pontszám'
|
||||
no-player: 'Nincs játékos'
|
||||
no-rank: 'Nincs rang'
|
||||
goal-catch-amount: 'Kifogott halak száma'
|
||||
goal-max-size: 'Legnagyobb kifogott hal'
|
||||
goal-total-size: 'Összes kifogott hal hossza'
|
||||
goal-total-score: 'Kifogott halak összpontszáma'
|
||||
unsafe-modification: "Nem lehet módosítani egy játékos horgász táskáját, ha aktív egy másik szerveren."
|
||||
never-played: "A játékos még nem csatlakozott a szerverhez. Nem lehet módosítani egy nem létező játékos horgász táskáját."
|
||||
data-not-loaded: "<red>Az adatok nem lettek betöltve. Kérjük, csatlakozz újra a szerverhez. Ha a probléma továbbra is fennáll, fordulj a szerveradminisztrátorhoz."
|
||||
open-market-gui: "A piac menü sikeresen meg lett nyitva {player} részére"
|
||||
open-fishing-bag: "A horgász táska sikeresen meg lett nyitva {player} részére"
|
||||
format-day: 'n'
|
||||
format-hour: 'ó'
|
||||
format-minute: 'p'
|
||||
format-second: 'mp'
|
||||
|
||||
# We're looking for a translator :D
|
||||
gui:
|
||||
search: "Search"
|
||||
select-file: 'Select file'
|
||||
select-item: "Select item"
|
||||
dupe-invalid-key: "<red>● Duplicated or invalid key"
|
||||
new-value: "New value: "
|
||||
temp-new-key: 'New key'
|
||||
set-new-key: "Set new key"
|
||||
edit-key: 'Edit {0}'
|
||||
delete-property: "<#00CED1>● Delete property"
|
||||
click-confirm: "<#00FF7F> -> Click to confirm"
|
||||
invalid-number: "<red>● Invalid number"
|
||||
illegal-format: "<red>● Illegal format"
|
||||
scroll-up: '<gray>● Scroll up'
|
||||
scroll-down: '<gray>● Scroll down'
|
||||
cannot-scroll-up: "<red>You've reached the top"
|
||||
cannot-scroll-down: "<red>You can't scroll further down"
|
||||
next-page: '<gray>● Next Page'
|
||||
goto-next-page: '<gray>Go to page <yellow>{0} <gray>/ <yellow>{1}'
|
||||
cannot-goto-next-page: '<red>There are no more pages'
|
||||
previous-page: '<gray>● Previous page'
|
||||
goto-previous-page: '<gray>Go to page <yellow>{0} <gray>/ <yellow>{1}'
|
||||
cannot-goto-previous-page: "<red>You can't go further back"
|
||||
back-to-parent-page: "<#FF8C00>Back to parent page"
|
||||
back-to-parent-folder: "<#FF8C00>Back to parent folder"
|
||||
current-value: "<gray>Current value: <white>"
|
||||
click-to-toggle: "<#00FF7F> -> Click to toggle"
|
||||
left-click-edit: "<#00FF7F> -> Left click to edit"
|
||||
right-click-reset: "<#FF6347> -> Right click to reset"
|
||||
right-click-delete: "<#FF6347> -> Right click to delete"
|
||||
right-click-cancel: "<#00CED1> -> Right click to cancel"
|
||||
loot-show-in-finder: "<#5F9EA0>● Show In Fish Finder"
|
||||
loot-score: "<#FF1493>● Score"
|
||||
loot-nick: "<#00FF00>● Nick"
|
||||
loot-instant-game: "<#7B68EE>● Instant Game"
|
||||
loot-disable-statistics: "<#CD853F>● Disable Statistics"
|
||||
loot-disable-game: "<#8B4513>● Disable Game"
|
||||
item-amount: "<#1E90FF>● Amount"
|
||||
item-custom-model-data: "<#FFC0CB>● Custom Model Data"
|
||||
item-display-name: "<#FAFAD2>● Display Name"
|
||||
item-custom-durability: "<#1E90FF>● Custom Durability"
|
||||
item-enchantment: "<#8A2BE2>● Enchantment"
|
||||
item-head64: "<#2E8B57>● Head64"
|
||||
item-item-flag: "<#E6E6FA>● Item Flag"
|
||||
item-lore: "<#FA8072>● Lore"
|
||||
item-material: "<#FF00FF>● Material"
|
||||
item-nbt: "<#FA8072>● NBT"
|
||||
item-prevent-grab: "<#FF4500>● Prevent Grabbing"
|
||||
item-price: "<#FFD700>● Price"
|
||||
item-price-base: "<gray> - base: <white>"
|
||||
item-price-bonus: "<gray> - bonus: <white>"
|
||||
item-random-durability: "<#FFFF00>● Random Durability"
|
||||
item-size: "<#FFF0F5>● Size"
|
||||
item-stackable: "<#9370DB>● Stackable"
|
||||
item-stored-enchantment: "<#9370DB>● Stored Enchantment"
|
||||
item-tag: "<#2E8B57>● Tag"
|
||||
item-unbreakable: "<#C0C0C0>● Unbreakable"
|
||||
page-amount-title: "Edit Amount"
|
||||
page-model-data-title: "Edit CustomModelData"
|
||||
page-display-name-title: "Edit display name"
|
||||
page-new-display-name: "New name"
|
||||
page-custom-durability-title: "Edit custom durability"
|
||||
page-stored-enchantment-title: "Edit stored enchantment"
|
||||
page-enchantment-title: "Edit enchantment"
|
||||
page-select-one-enchantment: "Select one enchantment"
|
||||
page-add-new-enchantment: "<green>[+] <gray>Add a new enchantment"
|
||||
page-item-flag-title: "Edit item flag"
|
||||
page-lore-title: "Edit lore"
|
||||
page-add-new-lore: "<green>[+] <gray>Add a new line"
|
||||
page-select-one-lore: "Select one line"
|
||||
page-material-title: "Edit Material"
|
||||
page-nbt-compound-key-title: "Edit compound key"
|
||||
page-nbt-list-key-title: "Edit list key"
|
||||
page-nbt-key-title: "Edit key"
|
||||
page-nbt-invalid-key: "<red>Invaild key"
|
||||
page-nbt-add-new-compound: "<green>[+] <gray>Add a new compound"
|
||||
page-nbt-add-new-list: "<green>[+] <gray>Add a new list"
|
||||
page-nbt-add-new-value: "<green>[+] <gray>Add a new value"
|
||||
page-add-new-key: "<green>[+] <gray>Add a new key"
|
||||
page-nbt-preview: "<green>● NBT Preview"
|
||||
page-nbt-back-to-compound: "<gray>Back to parent compound"
|
||||
page-nbt-set-value-title: "Set value"
|
||||
page-nbt-edit-title: "Edit NBT"
|
||||
page-nick-title: "Edit nick"
|
||||
page-new-nick: "New nick"
|
||||
page-price-title: "Edit price"
|
||||
page-base-price: "Base"
|
||||
page-base-bonus: "Bonus"
|
||||
page-score-title: "Edit score"
|
||||
page-size-title: "Edit size"
|
||||
page-size-min: "Minimum"
|
||||
page-size-max: "Maximum"
|
||||
page-size-max-no-less-min: "<red>● Max must be no less than min"
|
||||
@@ -1,125 +0,0 @@
|
||||
# Don't change this
|
||||
config-version: '31'
|
||||
|
||||
messages:
|
||||
prefix: '<gradient:#0070B3:#A0EACF>[CustomFishing] </gradient>'
|
||||
reload: '<white>重载完成. 耗时 <green>{time}ms.'
|
||||
item-not-exist: '物品不存在.'
|
||||
give-item: '给予玩家 {player} {amount}x {item}.'
|
||||
get-item: '获得 {amount}x {item}.'
|
||||
possible-loots: '可能的战利品: '
|
||||
split-char: ', '
|
||||
competition-not-exist: '比赛 {id} 不存在.'
|
||||
no-competition-ongoing: "没有正在进行的比赛."
|
||||
stop-competition: '停止了当前的比赛.'
|
||||
end-competition: '结束了当前的比赛.'
|
||||
no-score: '无比分'
|
||||
no-player: '无选手'
|
||||
no-rank: '无排名'
|
||||
goal-catch-amount: '捕鱼总数'
|
||||
goal-max-size: '最大尺寸'
|
||||
goal-total-size: '捕鱼总尺寸'
|
||||
goal-total-score: '捕鱼总分'
|
||||
unsafe-modification: "你不能修改一个正在其他子服游玩的玩家钓鱼背包."
|
||||
never-played: "此玩家从未玩过服务器."
|
||||
data-not-loaded: "<red>数据未能正常加载. 请尝试切换子服或重进. 如果问题依然存在请联系服务器管理员."
|
||||
open-market-gui: "为玩家 {player} 打开了市场"
|
||||
open-fishing-bag: "为玩家 {player} 打开了钓鱼背包"
|
||||
format-day: '天'
|
||||
format-hour: '小时'
|
||||
format-minute: '分'
|
||||
format-second: '秒'
|
||||
|
||||
gui:
|
||||
search: 搜索
|
||||
select-file: 选择文件
|
||||
select-item-to-edit: 选择要编辑的物品
|
||||
dupe-invalid-key: <red>● 重复或无效的键
|
||||
new-value: '新值: '
|
||||
temp-new-key: '新键'
|
||||
set-new-key: '设置新键'
|
||||
edit-key: '修改 {0}'
|
||||
delete-property: <#00CED1>● 删除属性
|
||||
click-confirm: <#00FF7F> -> 点击确认
|
||||
invalid-number: <red>● 无效的数字
|
||||
illegal-format: <red>● 非法的格式
|
||||
scroll-up: <gray>● 向上翻
|
||||
scroll-down: <gray>● 向下翻
|
||||
cannot-scroll-up: <red>你已经到顶了
|
||||
cannot-scroll-down: <red>你不能再往下了
|
||||
next-page: <gray>● 下一页
|
||||
goto-next-page: <gray>前往 <yellow>{0} <gray>/ <yellow>{1}
|
||||
cannot-goto-next-page: <red>没有更多页了
|
||||
previous-page: <gray>● 上一页
|
||||
goto-previous-page: <gray>前往 <yellow>{0} <gray>/ <yellow>{1}
|
||||
cannot-goto-previous-page: <red>已经到达第一页了
|
||||
back-to-parent-page: <#FF8C00>返回上一界面
|
||||
back-to-parent-folder: <#FF8C00>返回父文件夹
|
||||
current-value: '<gray>当前值: <white>'
|
||||
click-to-toggle: <#00FF7F> -> 点击切换
|
||||
left-click-edit: <#00FF7F> -> 左键编辑
|
||||
right-click-reset: <#FF6347> -> 右键重置
|
||||
right-click-delete: <#FF6347> -> 右键删除
|
||||
right-click-cancel: <#00CED1> -> 右键取消
|
||||
loot-show-in-finder: <#5F9EA0>● 在找鱼器中可见
|
||||
loot-score: <#FF1493>● 比赛分数
|
||||
loot-nick: <#00FF00>● 昵称
|
||||
loot-instant-game: <#7B68EE>● 咬钩立即游戏
|
||||
loot-disable-statistics: <#CD853F>● 禁用统计数据
|
||||
loot-disable-game: <#8B4513>● 禁用游戏
|
||||
item-amount: <#1E90FF>● 数量
|
||||
item-custom-model-data: <#FFC0CB>● 自定义模型值
|
||||
item-display-name: <#FAFAD2>● 名称
|
||||
item-custom-durability: <#1E90FF>● 自定义耐久度
|
||||
item-enchantment: <#8A2BE2>● 附魔
|
||||
item-head64: <#2E8B57>● 头颅base64
|
||||
item-item-flag: <#E6E6FA>● 物品标签
|
||||
item-lore: <#FA8072>● 描述
|
||||
item-material: <#FF00FF>● 材质
|
||||
item-nbt: <#FA8072>● NBT
|
||||
item-prevent-grab: <#FF4500>● 防止抢夺
|
||||
item-price: <#FFD700>● 价格
|
||||
item-price-base: '<gray> - 基础: <white>'
|
||||
item-price-bonus: '<gray> - 尺寸增益: <white>'
|
||||
item-random-durability: <#FFFF00>● 随机耐久
|
||||
item-size: <#FFF0F5>● 尺寸
|
||||
item-stackable: <#9370DB>● 是否可以堆叠
|
||||
item-stored-enchantment: <#9370DB>● 存储附魔
|
||||
item-tag: <#2E8B57>● 启用CustomFishing标签
|
||||
item-unbreakable: <#C0C0C0>● 不可破坏
|
||||
page-amount-title: 修改数量
|
||||
page-model-data-title: 修改自定义模型值
|
||||
page-display-name-title: 修改名称
|
||||
page-new-display-name: 新名称
|
||||
page-custom-durability-title: 修改自定义耐久度
|
||||
page-stored-enchantment-title: 修改存储附魔
|
||||
page-enchantment-title: 修改附魔
|
||||
page-select-one-enchantment: 选择一个附魔
|
||||
page-add-new-enchantment: <green>[+] <gray>新增一个附魔
|
||||
page-item-flag-title: 修改物品标签
|
||||
page-lore-title: 修改描述
|
||||
page-add-new-lore: <green>[+] <gray>新增一行描述
|
||||
page-select-one-lore: 选择一行描述
|
||||
page-material-title: 修改材质
|
||||
page-nbt-compound-key-title: 修改复合键名
|
||||
page-nbt-list-key-title: 修改列表名
|
||||
page-nbt-key-title: 修改键
|
||||
page-nbt-invalid-key: <red>无效的键
|
||||
page-nbt-add-new-compound: <green>[+] <gray>新增一个复合NBT
|
||||
page-nbt-add-new-list: <green>[+] <gray>新增一个列表
|
||||
page-nbt-add-new-value: <green>[+] <gray>新增一个值
|
||||
page-add-new-key: <green>[+] <gray>新增一个键
|
||||
page-nbt-preview: <green>● NBT 预览
|
||||
page-nbt-back-to-compound: <gray>返回父复合NBT
|
||||
page-nbt-set-value-title: 设置值
|
||||
page-nbt-edit-title: 修改NBT
|
||||
page-nick-title: 修改昵称
|
||||
page-new-nick: 新昵称
|
||||
page-price-title: 修改价格
|
||||
page-base-price: 基础
|
||||
page-base-bonus: 尺寸增益
|
||||
page-score-title: 修改分数
|
||||
page-size-title: 修改尺寸
|
||||
page-size-min: 最小值
|
||||
page-size-max: 最大值
|
||||
page-size-max-no-less-min: <red>● 最大值必须大于最小值
|
||||
123
core/src/main/resources/translations/en.yml
Normal file
123
core/src/main/resources/translations/en.yml
Normal file
@@ -0,0 +1,123 @@
|
||||
# Don"t change this
|
||||
config-version: "31"
|
||||
|
||||
command.prefix: "<gradient:#0070B3:#A0EACF>[CustomFishing] </gradient>"
|
||||
command.reload.success: "<white>Reloaded. Took <green><arg:0></green>ms.</white>"
|
||||
command.item.failure.not_exist: "<red>Item not exists</red>"
|
||||
command.item.give.success: "Successfully given player <arg:0> <arg:1>x <arg:2>."
|
||||
command.item.get.success: "Successfully got <arg:0>x <arg:1>."
|
||||
command.fish_finder.possible_loots: "Possible loots here: "
|
||||
command.fish_finder.no_loot: "No loot available"
|
||||
command.fish_finder.split_char: ", "
|
||||
command.competition.failure.not_exist: "Competition <arg:0> does not exist."
|
||||
command.competition.failure.no_competition: "There's no competition ongoing."
|
||||
command.competition.stop.success: "Stopped the current competition."
|
||||
command.competition.end.success: "Ended the current competition."
|
||||
command.bag.edit.failure.unsafe: "Cannot edit a player's fishing bag if they"re active on another linked server."
|
||||
command.bag.edit.failure.never_played: 'The player hasn\'t joined the server before. Can't modify a nonexistent player"s fishing bag."
|
||||
command.bag.open.success: "Successfully opened the fishing bag for <arg:0>"
|
||||
command.data.failure.not_load: '<red>Data hasn't loaded. Please re-enter the server. If issues persist, reach out to the server admin.</red>"
|
||||
command.market.open.success: "Successfully opened the market gui for <arg:0>"
|
||||
competition.no_score: "No Score"
|
||||
competition.no_player: "No Player"
|
||||
competition.no_rank: "No Rank"
|
||||
competition.goal.catch_amount: "Fish count caught"
|
||||
competition.goal.max_size: "Largest fish caught"
|
||||
competition.goal.total_score: "Cumulative score of fish caught"
|
||||
competition.goal.total_size: "Total length of fish caught"
|
||||
format.day: "d"
|
||||
format.hour: "h"
|
||||
format.minute: "m"
|
||||
format.second: "s"
|
||||
gui.search: "Search"
|
||||
gui.select_file: "Select file"
|
||||
gui.select_item: "Select item"
|
||||
gui.invalid_key: "<red>● Duplicated or invalid key"
|
||||
gui.new_value: "New value: "
|
||||
gui.temp_new_key: "New key"
|
||||
gui.set_new_key: "Set new key"
|
||||
gui.edit_key: "Edit <arg:0>"
|
||||
gui.delete_property: "<#00CED1>● Delete property"
|
||||
gui.click_confirm: "<#00FF7F> -> Click to confirm"
|
||||
gui.invalid_number: "<red>● Invalid number"
|
||||
gui.illegal_format: "<red>● Illegal format"
|
||||
gui.scroll_up: "<gray>● Scroll up"
|
||||
gui.scroll_down: "<gray>● Scroll down"
|
||||
gui.cannot_scroll_up: "<red>You"ve reached the top"
|
||||
gui.cannot_scroll_down: "<red>You can"t scroll further down"
|
||||
gui.next_page: "<gray>● Next Page"
|
||||
gui.goto_next_page: "<gray>Go to page <yellow><arg:0> <gray>/ <yellow><arg:1>"
|
||||
gui.cannot_goto_next_page: "<red>There are no more pages"
|
||||
gui.previous_page: "<gray>● Previous page"
|
||||
gui.goto_previous_page: "<gray>Go to page <yellow><arg:0> <gray>/ <yellow><arg:1>"
|
||||
gui.cannot_goto_previous_page: "<red>You can"t go further back"
|
||||
gui.back_to_parent_page: "<#FF8C00>Back to parent page"
|
||||
gui.back_to_parent_folder: "<#FF8C00>Back to parent folder"
|
||||
gui.current_value: "<gray>Current value: <white><arg:0>"
|
||||
gui.click_to_toggle: "<#00FF7F> -> Click to toggle"
|
||||
gui.left_click_edit: "<#00FF7F> -> Left click to edit"
|
||||
gui.right_click_reset: "<#FF6347> -> Right click to reset"
|
||||
gui.right_click_delete: "<#FF6347> -> Right click to delete"
|
||||
gui.right_click_cancel: "<#00CED1> -> Right click to cancel"
|
||||
gui.loot_show_in_finder: "<#5F9EA0>● Show In Fish Finder"
|
||||
gui.loot_score: "<#FF1493>● Score"
|
||||
gui.loot_nick: "<#00FF00>● Nick"
|
||||
gui.loot_instant_game: "<#7B68EE>● Instant Game"
|
||||
gui.loot_disable_statistics: "<#CD853F>● Disable Statistics"
|
||||
gui.loot_disable_game: "<#8B4513>● Disable Game"
|
||||
gui.item_amount: "<#1E90FF>● Amount"
|
||||
gui.item_custom_model_data: "<#FFC0CB>● Custom Model Data"
|
||||
gui.item_display_name: "<#FAFAD2>● Display Name"
|
||||
gui.item_custom_durability: "<#1E90FF>● Custom Durability"
|
||||
gui.item_enchantment: "<#8A2BE2>● Enchantment"
|
||||
gui.item_head64: "<#2E8B57>● Head64"
|
||||
gui.item_item_flag: "<#E6E6FA>● Item Flag"
|
||||
gui.item_lore: "<#FA8072>● Lore"
|
||||
gui.item_material: "<#FF00FF>● Material"
|
||||
gui.item_nbt: "<#FA8072>● NBT"
|
||||
gui.item_prevent_grab: "<#FF4500>● Prevent Grabbing"
|
||||
gui.item_price: "<#FFD700>● Price"
|
||||
gui.item_price_base: "<gray> - base: <white>"
|
||||
gui.item_price_bonus: "<gray> - bonus: <white>"
|
||||
gui.item_random_durability: "<#FFFF00>● Random Durability"
|
||||
gui.item_size: "<#FFF0F5>● Size"
|
||||
gui.item_stackable: "<#9370DB>● Stackable"
|
||||
gui.item_stored_enchantment: "<#9370DB>● Stored Enchantment"
|
||||
gui.item_tag: "<#2E8B57>● Tag"
|
||||
gui.item_unbreakable: "<#C0C0C0>● Unbreakable"
|
||||
gui.page_amount_title: "Edit Amount"
|
||||
gui.page_model_data_title: "Edit CustomModelData"
|
||||
gui.page_display_name_title: "Edit display name"
|
||||
gui.page_new_display_name: "New name"
|
||||
gui.page_custom_durability_title: "Edit custom durability"
|
||||
gui.page_stored_enchantment_title: "Edit stored enchantment"
|
||||
gui.page_enchantment_title: "Edit enchantment"
|
||||
gui.page_select_one_enchantment: "Select one enchantment"
|
||||
gui.page_add_new_enchantment: "<green>[+] <gray>Add a new enchantment"
|
||||
gui.page_item_flag_title: "Edit item flag"
|
||||
gui.page_lore_title: "Edit lore"
|
||||
gui.page_add_new_lore: "<green>[+] <gray>Add a new line"
|
||||
gui.page_select_one_lore: "Select one line"
|
||||
gui.page_material_title: "Edit Material"
|
||||
gui.page_nbt_compound_key_title: "Edit compound key"
|
||||
gui.page_nbt_list_key_title: "Edit list key"
|
||||
gui.page_nbt_key_title: "Edit key"
|
||||
gui.page_nbt_invalid_key: "<red>Invaild key"
|
||||
gui.page_nbt_add_new_compound: "<green>[+] <gray>Add a new compound"
|
||||
gui.page_nbt_add_new_list: "<green>[+] <gray>Add a new list"
|
||||
gui.page_nbt_add_new_value: "<green>[+] <gray>Add a new value"
|
||||
gui.page_add_new_key: "<green>[+] <gray>Add a new key"
|
||||
gui.page_nbt_preview: "<green>● NBT Preview"
|
||||
gui.page_nbt_back_to_compound: "<gray>Back to parent compound"
|
||||
gui.page_nbt_set_value_title: "Set value"
|
||||
gui.page_nbt_edit_title: "Edit NBT"
|
||||
gui.page_nick_title: "Edit nick"
|
||||
gui.page_new_nick: "New nick"
|
||||
gui.page_price_title: "Edit price"
|
||||
gui.page_base_price: "Base"
|
||||
gui.page_base_bonus: "Bonus"
|
||||
gui.page_score_title: "Edit score"
|
||||
gui.page_size_title: "Edit size"
|
||||
gui.page_size_min: "Minimum"
|
||||
gui.page_size_max: "Maximum"
|
||||
gui.page_size_max_no_less_min: "<red>● Max must be no less than min</red>"
|
||||
@@ -1,7 +1,7 @@
|
||||
# Project settings
|
||||
# Rule: [major update].[feature update].[bug fix]
|
||||
project_version=1.7.1
|
||||
config_version=2
|
||||
project_version=2.2.0
|
||||
config_version=32
|
||||
project_group=net.momirealms
|
||||
|
||||
# Dependency settings
|
||||
|
||||
Reference in New Issue
Block a user