mirror of
https://github.com/Xiao-MoMi/Custom-Fishing.git
synced 2026-01-06 15:51:50 +00:00
checkpoint - 14
This commit is contained in:
@@ -41,6 +41,7 @@ import org.bukkit.plugin.java.JavaPlugin;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class BukkitCustomFishingPluginImpl extends BukkitCustomFishingPlugin {
|
||||
|
||||
@@ -48,6 +49,7 @@ public class BukkitCustomFishingPluginImpl extends BukkitCustomFishingPlugin {
|
||||
private final PluginLogger logger;
|
||||
private ChatCatcherManager chatCatcherManager;
|
||||
private BukkitCommandManager commandManager;
|
||||
private Consumer<String> debugger;
|
||||
|
||||
public BukkitCustomFishingPluginImpl(Plugin boostrap) {
|
||||
super(boostrap);
|
||||
@@ -56,6 +58,7 @@ public class BukkitCustomFishingPluginImpl extends BukkitCustomFishingPlugin {
|
||||
this.classPathAppender = new ReflectionClassPathAppender(this);
|
||||
this.logger = new JavaPluginLogger(getBoostrap().getLogger());
|
||||
this.dependencyManager = new DependencyManagerImpl(this);
|
||||
this.debugger = (s) -> {};
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -72,10 +75,11 @@ public class BukkitCustomFishingPluginImpl extends BukkitCustomFishingPlugin {
|
||||
Dependency.JEDIS,
|
||||
Dependency.EXP4J,
|
||||
Dependency.MYSQL_DRIVER, Dependency.MARIADB_DRIVER,
|
||||
Dependency.SQLITE_DRIVER,
|
||||
Dependency.SQLITE_DRIVER, Dependency.SLF4J_API, Dependency.SLF4J_SIMPLE,
|
||||
Dependency.H2_DRIVER,
|
||||
Dependency.MONGODB_DRIVER_CORE, Dependency.MONGODB_DRIVER_SYNC, Dependency.MONGODB_DRIVER_BSON,
|
||||
Dependency.HIKARI_CP)
|
||||
Dependency.HIKARI_CP
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -118,24 +122,38 @@ public class BukkitCustomFishingPluginImpl extends BukkitCustomFishingPlugin {
|
||||
@Override
|
||||
public void reload() {
|
||||
ItemType.reset();
|
||||
this.eventManager.reload();
|
||||
this.configManager.reload();
|
||||
this.requirementManager.reload();
|
||||
this.actionManager.reload();
|
||||
|
||||
this.itemManager.unload();
|
||||
this.eventManager.unload();
|
||||
this.entityManager.unload();
|
||||
this.lootManager.unload();
|
||||
this.blockManager.unload();
|
||||
this.effectManager.unload();
|
||||
this.hookManager.unload();
|
||||
|
||||
// before ConfigManager
|
||||
this.placeholderManager.reload();
|
||||
this.itemManager.reload();
|
||||
this.competitionManager.reload();
|
||||
this.marketManager.reload();
|
||||
this.storageManager.reload();
|
||||
this.lootManager.reload();
|
||||
this.configManager.reload();
|
||||
// after ConfigManager
|
||||
this.debugger = ConfigManager.debug() ? logger::info : (s) -> {};
|
||||
|
||||
this.actionManager.reload();
|
||||
this.requirementManager.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();
|
||||
this.marketManager.reload();
|
||||
this.competitionManager.reload();
|
||||
this.statisticsManager.reload();
|
||||
this.bagManager.reload();
|
||||
this.storageManager.reload();
|
||||
|
||||
this.itemManager.load();
|
||||
this.eventManager.load();
|
||||
this.entityManager.load();
|
||||
this.lootManager.load();
|
||||
this.blockManager.load();
|
||||
this.effectManager.load();
|
||||
this.hookManager.load();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -192,6 +210,11 @@ public class BukkitCustomFishingPluginImpl extends BukkitCustomFishingPlugin {
|
||||
return getBoostrap().getDescription().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String message) {
|
||||
this.debugger.accept(message);
|
||||
}
|
||||
|
||||
public ChatCatcherManager getChatCatcherManager() {
|
||||
return chatCatcherManager;
|
||||
}
|
||||
|
||||
@@ -17,12 +17,16 @@
|
||||
|
||||
package net.momirealms.customfishing.bukkit.bag;
|
||||
|
||||
import dev.dejvokep.boostedyaml.block.implementation.Section;
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import net.momirealms.customfishing.api.mechanic.action.Action;
|
||||
import net.momirealms.customfishing.api.mechanic.bag.BagManager;
|
||||
import net.momirealms.customfishing.api.mechanic.bag.FishingBagHolder;
|
||||
import net.momirealms.customfishing.api.mechanic.config.ConfigManager;
|
||||
import net.momirealms.customfishing.api.mechanic.effect.EffectModifier;
|
||||
import net.momirealms.customfishing.api.mechanic.item.ItemType;
|
||||
import net.momirealms.customfishing.api.mechanic.requirement.Requirement;
|
||||
import net.momirealms.customfishing.api.storage.user.UserData;
|
||||
import net.momirealms.customfishing.bukkit.config.BukkitConfigManager;
|
||||
import net.momirealms.customfishing.common.helper.AdventureHelper;
|
||||
import net.momirealms.sparrow.heart.SparrowHeart;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
@@ -37,16 +41,19 @@ import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class BukkitBagManager implements BagManager, Listener {
|
||||
|
||||
private final BukkitCustomFishingPlugin plugin;
|
||||
private final HashMap<UUID, UserData> tempEditMap;
|
||||
private Action<Player>[] collectLootActions;
|
||||
private Action<Player>[] bagFullActions;
|
||||
private boolean bagStoreLoots;
|
||||
private String bagTitle;
|
||||
private List<Material> bagWhiteListItems = new ArrayList<>();
|
||||
private Requirement<Player>[] collectRequirements;
|
||||
|
||||
public BukkitBagManager(BukkitCustomFishingPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
@@ -55,6 +62,7 @@ public class BukkitBagManager implements BagManager, Listener {
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
this.loadConfig();
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin.getBoostrap());
|
||||
}
|
||||
|
||||
@@ -69,40 +77,33 @@ public class BukkitBagManager implements BagManager, Listener {
|
||||
this.plugin.getStorageManager().getDataSource().updateManyPlayersData(tempEditMap.values(), true);
|
||||
}
|
||||
|
||||
private void loadConfig() {
|
||||
Section config = BukkitConfigManager.getMainConfig().getSection("mechanics.fishing-bag");
|
||||
|
||||
bagTitle = config.getString("bag-title", "");
|
||||
bagStoreLoots = config.getBoolean("can-store-loot", false);
|
||||
bagWhiteListItems = config.getStringList("whitelist-items").stream().map(it -> Material.valueOf(it.toUpperCase(Locale.ENGLISH))).toList();
|
||||
collectLootActions = plugin.getActionManager().parseActions(config.getSection("collect-actions"));
|
||||
bagFullActions = plugin.getActionManager().parseActions(config.getSection("full-actions"));
|
||||
collectRequirements = plugin.getRequirementManager().parseRequirements(config.getSection("collect-requirements"), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Boolean> openBag(Player viewer, UUID owner) {
|
||||
CompletableFuture<Boolean> future = new CompletableFuture<>();
|
||||
Optional<UserData> onlineUser = plugin.getStorageManager().getOnlineUser(owner);
|
||||
onlineUser.ifPresentOrElse(data -> {
|
||||
viewer.openInventory(data.holder().getInventory());
|
||||
SparrowHeart.getInstance().updateInventoryTitle(viewer,
|
||||
plugin.getPlaceholderManager().parse(
|
||||
Bukkit.getOfflinePlayer(owner),
|
||||
ConfigManager.bagTitle(),
|
||||
Map.of(
|
||||
"{uuid}", owner.toString(),
|
||||
"{player}", data.name()
|
||||
)
|
||||
)
|
||||
);
|
||||
SparrowHeart.getInstance().updateInventoryTitle(viewer, AdventureHelper.componentToJson(AdventureHelper.miniMessage(plugin.getPlaceholderManager().parse(Bukkit.getOfflinePlayer(owner), bagTitle, Map.of("{uuid}", owner.toString(), "{player}", data.name())))));
|
||||
future.complete(true);
|
||||
}, () -> plugin.getStorageManager().getOfflineUserData(owner, true).thenAccept(result -> result.ifPresentOrElse(data -> {
|
||||
if (data.isLocked()) {
|
||||
future.complete(false);
|
||||
future.completeExceptionally(new RuntimeException("Data is locked"));
|
||||
return;
|
||||
}
|
||||
this.tempEditMap.put(viewer.getUniqueId(), data);
|
||||
viewer.openInventory(data.holder().getInventory());
|
||||
SparrowHeart.getInstance().updateInventoryTitle(viewer,
|
||||
plugin.getPlaceholderManager().parse(
|
||||
Bukkit.getOfflinePlayer(owner),
|
||||
ConfigManager.bagTitle(),
|
||||
Map.of(
|
||||
"{uuid}", owner.toString(),
|
||||
"{player}", data.name()
|
||||
)
|
||||
)
|
||||
);
|
||||
SparrowHeart.getInstance().updateInventoryTitle(viewer, AdventureHelper.componentToJson(AdventureHelper.miniMessage(plugin.getPlaceholderManager().parse(Bukkit.getOfflinePlayer(owner), bagTitle, Map.of("{uuid}", owner.toString(), "{player}", data.name())))));
|
||||
future.complete(true);
|
||||
}, () -> future.complete(false))));
|
||||
return future;
|
||||
@@ -130,32 +131,37 @@ public class BukkitBagManager implements BagManager, Listener {
|
||||
*
|
||||
* @param event The InventoryClickEvent triggered when an item is clicked in an inventory.
|
||||
*/
|
||||
@EventHandler
|
||||
@EventHandler (ignoreCancelled = true)
|
||||
public void onInvClick(InventoryClickEvent event) {
|
||||
if (event.isCancelled())
|
||||
return;
|
||||
if (!(event.getInventory().getHolder() instanceof FishingBagHolder))
|
||||
return;
|
||||
|
||||
ItemStack movedItem = event.getCurrentItem();
|
||||
Inventory clicked = event.getClickedInventory();
|
||||
|
||||
if (clicked != event.getWhoClicked().getInventory()) {
|
||||
if (event.getAction() != InventoryAction.HOTBAR_SWAP
|
||||
&& event.getAction() != InventoryAction.HOTBAR_MOVE_AND_READD
|
||||
) {
|
||||
if (event.getAction() != InventoryAction.HOTBAR_SWAP && event.getAction() != InventoryAction.HOTBAR_MOVE_AND_READD) {
|
||||
return;
|
||||
}
|
||||
movedItem = event.getWhoClicked().getInventory().getItem(event.getHotbarButton());
|
||||
}
|
||||
if (movedItem == null || movedItem.getType() == Material.AIR)
|
||||
return;
|
||||
if (ConfigManager.bagWhiteListItems().contains(movedItem.getType()))
|
||||
|
||||
if (movedItem == null || movedItem.getType() == Material.AIR || bagWhiteListItems.contains(movedItem.getType()))
|
||||
return;
|
||||
|
||||
String id = plugin.getItemManager().getItemID(movedItem);
|
||||
Optional<EffectModifier> optionalEffectModifier = plugin.getEffectManager().getEffectModifier(id);
|
||||
if (optionalEffectModifier.isPresent())
|
||||
ItemType type = ItemType.getTypeByID(id);
|
||||
if (type == null) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
if (ConfigManager.bagStoreLoots() && plugin.getLootManager().getLoot(id).isPresent())
|
||||
}
|
||||
|
||||
if (type == ItemType.LOOT && bagStoreLoots)
|
||||
return;
|
||||
|
||||
if (type == ItemType.BAIT || type == ItemType.ROD || type == ItemType.UTIL || type == ItemType.HOOK)
|
||||
return;
|
||||
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,11 @@ public class BukkitCommandManager extends AbstractCommandManager<CommandSender>
|
||||
new StopCompetitionCommand(this),
|
||||
new StartCompetitionCommand(this),
|
||||
new OpenMarketCommand(this),
|
||||
new OpenBagCommand(this)
|
||||
new OpenBagCommand(this),
|
||||
new FishingBagCommand(this),
|
||||
new GUIEditorCommand(this),
|
||||
new EditOnlineBagCommand(this),
|
||||
new EditOfflineBagCommand(this)
|
||||
);
|
||||
|
||||
private final Index<String, CommandFeature<CommandSender>> INDEX = Index.create(CommandFeature::getFeatureID, FEATURES);
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package net.momirealms.customfishing.bukkit.command.feature;
|
||||
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import net.momirealms.customfishing.bukkit.command.BukkitCommandFeature;
|
||||
import net.momirealms.customfishing.common.command.CustomFishingCommandManager;
|
||||
import net.momirealms.customfishing.common.locale.MessageConstants;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.CommandManager;
|
||||
import org.incendo.cloud.parser.standard.UUIDParser;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class EditOfflineBagCommand extends BukkitCommandFeature<CommandSender> {
|
||||
|
||||
public EditOfflineBagCommand(CustomFishingCommandManager<CommandSender> commandManager) {
|
||||
super(commandManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Command.Builder<? extends CommandSender> assembleCommand(CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
|
||||
return builder
|
||||
.senderType(Player.class)
|
||||
.required("uuid", UUIDParser.uuidParser())
|
||||
.handler(context -> {
|
||||
Player admin = context.sender();
|
||||
UUID uuid = context.get("uuid");
|
||||
BukkitCustomFishingPlugin.getInstance().getBagManager().openBag(admin, uuid).whenComplete((result, throwable) -> {
|
||||
if (throwable != null) {
|
||||
handleFeedback(context, MessageConstants.COMMAND_BAG_EDIT_FAILURE_UNSAFE);
|
||||
return;
|
||||
}
|
||||
if (!result) {
|
||||
handleFeedback(context, MessageConstants.COMMAND_BAG_EDIT_FAILURE_NEVER_PLAYED);
|
||||
return;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFeatureID() {
|
||||
return "edit_offline_bag";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package net.momirealms.customfishing.bukkit.command.feature;
|
||||
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import net.momirealms.customfishing.bukkit.command.BukkitCommandFeature;
|
||||
import net.momirealms.customfishing.common.command.CustomFishingCommandManager;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.CommandManager;
|
||||
import org.incendo.cloud.bukkit.parser.PlayerParser;
|
||||
|
||||
public class EditOnlineBagCommand extends BukkitCommandFeature<CommandSender> {
|
||||
|
||||
public EditOnlineBagCommand(CustomFishingCommandManager<CommandSender> commandManager) {
|
||||
super(commandManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Command.Builder<? extends CommandSender> assembleCommand(CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
|
||||
return builder
|
||||
.senderType(Player.class)
|
||||
.required("player", PlayerParser.playerParser())
|
||||
.handler(context -> {
|
||||
Player admin = context.sender();
|
||||
Player online = context.get("player");
|
||||
BukkitCustomFishingPlugin.getInstance().getBagManager().openBag(admin, online.getUniqueId());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFeatureID() {
|
||||
return "edit_online_bag";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package net.momirealms.customfishing.bukkit.command.feature;
|
||||
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import net.momirealms.customfishing.bukkit.command.BukkitCommandFeature;
|
||||
import net.momirealms.customfishing.common.command.CustomFishingCommandManager;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.CommandManager;
|
||||
|
||||
public class FishingBagCommand extends BukkitCommandFeature<CommandSender> {
|
||||
|
||||
public FishingBagCommand(CustomFishingCommandManager<CommandSender> commandManager) {
|
||||
super(commandManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Command.Builder<? extends CommandSender> assembleCommand(CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
|
||||
return builder
|
||||
.senderType(Player.class)
|
||||
.handler(context -> BukkitCustomFishingPlugin.getInstance().getBagManager().openBag(context.sender(), context.sender().getUniqueId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFeatureID() {
|
||||
return "fishingbag";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package net.momirealms.customfishing.bukkit.command.feature;
|
||||
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import net.momirealms.customfishing.bukkit.command.BukkitCommandFeature;
|
||||
import net.momirealms.customfishing.bukkit.gui.page.file.FileSelector;
|
||||
import net.momirealms.customfishing.common.command.CustomFishingCommandManager;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.CommandManager;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class GUIEditorCommand extends BukkitCommandFeature<CommandSender> {
|
||||
|
||||
public GUIEditorCommand(CustomFishingCommandManager<CommandSender> commandManager) {
|
||||
super(commandManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Command.Builder<? extends CommandSender> assembleCommand(CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
|
||||
return builder
|
||||
.senderType(Player.class)
|
||||
.handler(context -> {
|
||||
new FileSelector(context.sender(), new File(BukkitCustomFishingPlugin.getInstance().getDataFolder(), "contents"));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFeatureID() {
|
||||
return "browser";
|
||||
}
|
||||
}
|
||||
@@ -14,9 +14,7 @@ import org.bukkit.inventory.ItemStack;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.incendo.cloud.Command;
|
||||
import org.incendo.cloud.CommandManager;
|
||||
import org.incendo.cloud.bukkit.data.MultiplePlayerSelector;
|
||||
import org.incendo.cloud.bukkit.parser.PlayerParser;
|
||||
import org.incendo.cloud.bukkit.parser.selector.MultiplePlayerSelectorParser;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.context.CommandInput;
|
||||
import org.incendo.cloud.parser.standard.IntegerParser;
|
||||
|
||||
@@ -2,7 +2,6 @@ package net.momirealms.customfishing.bukkit.command.feature;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import net.momirealms.customfishing.api.mechanic.competition.FishingCompetition;
|
||||
import net.momirealms.customfishing.bukkit.command.BukkitCommandFeature;
|
||||
import net.momirealms.customfishing.common.command.CustomFishingCommandManager;
|
||||
import net.momirealms.customfishing.common.locale.MessageConstants;
|
||||
|
||||
@@ -44,8 +44,6 @@ import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public class BukkitCompetitionManager implements CompetitionManager {
|
||||
|
||||
private final BukkitCustomFishingPlugin plugin;
|
||||
@@ -75,7 +73,7 @@ public class BukkitCompetitionManager implements CompetitionManager {
|
||||
if (this.timerCheckTask != null)
|
||||
this.timerCheckTask.cancel();
|
||||
if (currentCompetition != null && currentCompetition.isOnGoing())
|
||||
currentCompetition.stop(true);
|
||||
this.currentCompetition.stop(true);
|
||||
this.commandConfigMap.clear();
|
||||
this.timeConfigMap.clear();
|
||||
}
|
||||
@@ -84,7 +82,7 @@ public class BukkitCompetitionManager implements CompetitionManager {
|
||||
if (this.timerCheckTask != null)
|
||||
this.timerCheckTask.cancel();
|
||||
if (currentCompetition != null && currentCompetition.isOnGoing())
|
||||
currentCompetition.stop(false);
|
||||
this.currentCompetition.stop(false);
|
||||
this.commandConfigMap.clear();
|
||||
this.timeConfigMap.clear();
|
||||
}
|
||||
|
||||
@@ -47,8 +47,52 @@ public class BukkitConfigManager extends ConfigManager {
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
this.loadConfigs();
|
||||
MAIN_CONFIG = loadConfig("config.yml");
|
||||
this.loadSettings();
|
||||
this.loadConfigs();
|
||||
}
|
||||
|
||||
private void loadSettings() {
|
||||
YamlDocument config = getMainConfig();
|
||||
|
||||
metrics = config.getBoolean("metrics", true);
|
||||
checkUpdate = config.getBoolean("update-checker", true);
|
||||
debug = config.getBoolean("debug", false);
|
||||
|
||||
overrideVanillaWaitTime = config.getBoolean("mechanics.fishing-wait-time.override-vanilla", false);
|
||||
waterMinTime = config.getInt("mechanics.fishing-wait-time.min-wait-time", 100);
|
||||
waterMaxTime = config.getInt("mechanics.fishing-wait-time.max-wait-time", 600);
|
||||
|
||||
lavaMinTime = config.getInt("mechanics.lava-fishing.min-wait-time", 100);
|
||||
lavaMaxTime = config.getInt("mechanics.lava-fishing.max-wait-time", 600);
|
||||
|
||||
restrictedSizeRange = config.getBoolean("mechanics.size.restricted-size-range", true);
|
||||
|
||||
placeholderLimit = config.getInt("mechanics.competition.placeholder-limit", 3);
|
||||
serverGroup = config.getString("mechanics.competition.server-group", "default");
|
||||
redisRanking = config.getBoolean("mechanics.competition.redis-ranking", false);
|
||||
|
||||
AdventureHelper.legacySupport = config.getBoolean("other-settings.legacy-color-code-support", true);
|
||||
dataSaveInterval = config.getInt("other-settings.data-save-interval", 600);
|
||||
logDataSaving = config.getBoolean("other-settings.log-data-saving", true);
|
||||
lockData = config.getBoolean("other-settings.lock-data", true);
|
||||
|
||||
durabilityLore = new ArrayList<>(config.getStringList("other-settings.custom-durability-format"));
|
||||
|
||||
itemDetectOrder = config.getStringList("other-settings.item-detection-order").toArray(new String[0]);
|
||||
blockDetectOrder = config.getStringList("other-settings.block-detection-order").toArray(new String[0]);
|
||||
|
||||
allowMultipleTotemType = config.getBoolean("mechanics.totem.allow-multiple-type", true);
|
||||
allowSameTotemType = config.getBoolean("mechanics.totem.allow-same-type", false);
|
||||
|
||||
Section placeholderSection = config.getSection("other-settings.placeholder-register");
|
||||
if (placeholderSection != null) {
|
||||
for (Map.Entry<String, Object> entry : placeholderSection.getStringRouteMappedValues(false).entrySet()) {
|
||||
if (entry.getValue() instanceof String original) {
|
||||
plugin.getPlaceholderManager().registerCustomPlaceholder(entry.getKey(), original);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void loadConfigs() {
|
||||
|
||||
@@ -33,10 +33,16 @@ public class BukkitEffectManager implements EffectManager {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void disable() {
|
||||
@Override
|
||||
public void unload() {
|
||||
this.effectModifiers.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerEffectModifier(EffectModifier effect) {
|
||||
if (effectModifiers.containsKey(effect.id())) return false;
|
||||
|
||||
@@ -72,11 +72,13 @@ public class BukkitItemManager implements ItemManager, Listener {
|
||||
@Override
|
||||
public void unload() {
|
||||
HandlerList.unregisterAll(this);
|
||||
this.items.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin.getBoostrap());
|
||||
this.resetItemDetectionOrder();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -24,6 +24,17 @@ public class BukkitLootManager implements LootManager {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unload() {
|
||||
this.lootMap.clear();
|
||||
this.groupMembersMap.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerLoot(@NotNull Loot loot) {
|
||||
this.lootMap.put(loot.id(), loot);
|
||||
|
||||
@@ -17,12 +17,10 @@
|
||||
|
||||
package net.momirealms.customfishing.bukkit.market;
|
||||
|
||||
import dev.dejvokep.boostedyaml.YamlDocument;
|
||||
import dev.dejvokep.boostedyaml.block.implementation.Section;
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import net.momirealms.customfishing.api.mechanic.action.Action;
|
||||
import net.momirealms.customfishing.api.mechanic.action.ActionManager;
|
||||
import net.momirealms.customfishing.api.mechanic.config.ConfigManager;
|
||||
import net.momirealms.customfishing.api.mechanic.config.GUIItemParser;
|
||||
import net.momirealms.customfishing.api.mechanic.context.Context;
|
||||
import net.momirealms.customfishing.api.mechanic.context.ContextKeys;
|
||||
@@ -56,12 +54,11 @@ import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
public class BukkitMarketManager implements MarketManager, Listener {
|
||||
|
||||
private final BukkitCustomFishingPlugin plugin;
|
||||
|
||||
private boolean enable;
|
||||
|
||||
private final HashMap<String, MathValue<Player>> priceMap;
|
||||
private String formula;
|
||||
private MathValue<Player> earningsLimit;
|
||||
@@ -108,7 +105,6 @@ public class BukkitMarketManager implements MarketManager, Listener {
|
||||
public void load() {
|
||||
this.loadConfig();
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin.getBoostrap());
|
||||
if (!enable) return;
|
||||
this.resetEarningsTask = plugin.getScheduler().asyncRepeating(() -> {
|
||||
int now = getRealTimeDate();
|
||||
if (this.cachedDate != now) {
|
||||
@@ -365,7 +361,7 @@ public class BukkitMarketManager implements MarketManager, Listener {
|
||||
}
|
||||
} else if (element.getSymbol() == sellAllSlot) {
|
||||
ArrayList<ItemStack> itemStacksToSell = new ArrayList<>(List.of(gui.context.getHolder().getInventory().getStorageContents()));
|
||||
if (sellFishingBag && ConfigManager.enableFishingBag()) {
|
||||
if (sellFishingBag) {
|
||||
Optional<UserData> optionalUserData = BukkitCustomFishingPlugin.getInstance().getStorageManager().getOnlineUser(gui.context.getHolder().getUniqueId());
|
||||
optionalUserData.ifPresent(userData -> itemStacksToSell.addAll(List.of(userData.holder().getInventory().getStorageContents())));
|
||||
}
|
||||
@@ -441,6 +437,7 @@ public class BukkitMarketManager implements MarketManager, Listener {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
public double getItemPrice(Context<Player> context, ItemStack itemStack) {
|
||||
if (itemStack == null || itemStack.getType() == Material.AIR)
|
||||
return 0;
|
||||
@@ -500,6 +497,7 @@ public class BukkitMarketManager implements MarketManager, Listener {
|
||||
return Pair.of(amount, worth);
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
public void clearWorthyItems(Context<Player> context, List<ItemStack> itemStacks) {
|
||||
for (ItemStack itemStack : itemStacks) {
|
||||
double price = getItemPrice(context, itemStack);
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
package net.momirealms.customfishing.bukkit.market;
|
||||
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import net.momirealms.customfishing.api.mechanic.config.ConfigManager;
|
||||
import net.momirealms.customfishing.api.mechanic.context.Context;
|
||||
import net.momirealms.customfishing.api.mechanic.context.ContextKeys;
|
||||
import net.momirealms.customfishing.api.mechanic.market.MarketGUIHolder;
|
||||
@@ -37,6 +36,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
public class MarketGUI {
|
||||
|
||||
private final HashMap<Character, MarketGUIElement> itemsCharMap;
|
||||
@@ -109,7 +109,6 @@ public class MarketGUI {
|
||||
* Refresh the GUI, updating the display based on current data.
|
||||
* @return The MarketGUI instance.
|
||||
*/
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
public MarketGUI refresh() {
|
||||
double earningLimit = manager.earningLimit(context);
|
||||
MarketDynamicGUIElement sellElement = (MarketDynamicGUIElement) getElement(manager.sellSlot);
|
||||
@@ -134,7 +133,7 @@ public class MarketGUI {
|
||||
MarketDynamicGUIElement sellAllElement = (MarketDynamicGUIElement) getElement(manager.sellAllSlot);
|
||||
if (sellAllElement != null && !sellAllElement.getSlots().isEmpty()) {
|
||||
ArrayList<ItemStack> itemStacksToSell = new ArrayList<>(List.of(context.getHolder().getInventory().getStorageContents()));
|
||||
if (manager.sellFishingBag && ConfigManager.enableFishingBag()) {
|
||||
if (manager.sellFishingBag) {
|
||||
Optional<UserData> optionalUserData = BukkitCustomFishingPlugin.getInstance().getStorageManager().getOnlineUser(context.getHolder().getUniqueId());
|
||||
optionalUserData.ifPresent(userData -> itemStacksToSell.addAll(List.of(userData.holder().getInventory().getStorageContents())));
|
||||
}
|
||||
|
||||
@@ -121,7 +121,9 @@ public class MongoDBProvider extends AbstractStorage {
|
||||
if (doc == null) {
|
||||
if (Bukkit.getPlayer(uuid) != null) {
|
||||
if (lock) lockOrUnlockPlayerData(uuid, true);
|
||||
future.complete(Optional.of(PlayerData.empty()));
|
||||
var data = PlayerData.empty();
|
||||
data.uuid(uuid);
|
||||
future.complete(Optional.of(data));
|
||||
} else {
|
||||
future.complete(Optional.empty());
|
||||
}
|
||||
|
||||
@@ -144,6 +144,7 @@ public abstract class AbstractSQLDatabase extends AbstractStorage {
|
||||
} else if (Bukkit.getPlayer(uuid) != null) {
|
||||
// the player is online
|
||||
var data = PlayerData.empty();
|
||||
data.uuid(uuid);
|
||||
insertPlayerData(uuid, data, lock);
|
||||
future.complete(Optional.of(data));
|
||||
} else {
|
||||
|
||||
@@ -21,7 +21,6 @@ import dev.dejvokep.boostedyaml.YamlDocument;
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import net.momirealms.customfishing.api.storage.StorageType;
|
||||
import net.momirealms.customfishing.common.dependency.Dependency;
|
||||
import org.h2.jdbcx.JdbcConnectionPool;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
@@ -127,6 +127,7 @@ public class SQLiteProvider extends AbstractSQLDatabase {
|
||||
future.complete(Optional.of(data));
|
||||
} else if (Bukkit.getPlayer(uuid) != null) {
|
||||
var data = PlayerData.empty();
|
||||
data.uuid(uuid);
|
||||
insertPlayerData(uuid, data, lock);
|
||||
future.complete(Optional.of(data));
|
||||
} else {
|
||||
|
||||
@@ -60,6 +60,7 @@ public class JsonProvider extends AbstractStorage {
|
||||
playerData = readFromJsonFile(file, PlayerData.class);
|
||||
} else if (Bukkit.getPlayer(uuid) != null) {
|
||||
playerData = PlayerData.empty();
|
||||
playerData.uuid(uuid);
|
||||
} else {
|
||||
playerData = null;
|
||||
}
|
||||
|
||||
@@ -64,7 +64,9 @@ public class YAMLProvider extends AbstractStorage {
|
||||
File dataFile = getPlayerDataFile(uuid);
|
||||
if (!dataFile.exists()) {
|
||||
if (Bukkit.getPlayer(uuid) != null) {
|
||||
return CompletableFuture.completedFuture(Optional.of(PlayerData.empty()));
|
||||
var data = PlayerData.empty();
|
||||
data.uuid(uuid);
|
||||
return CompletableFuture.completedFuture(Optional.of(data));
|
||||
} else {
|
||||
return CompletableFuture.completedFuture(Optional.empty());
|
||||
}
|
||||
|
||||
@@ -1,86 +1,87 @@
|
||||
///*
|
||||
// * 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;
|
||||
// }
|
||||
//}
|
||||
/*
|
||||
* 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.ActionTrigger;
|
||||
import net.momirealms.customfishing.api.mechanic.context.Context;
|
||||
import net.momirealms.customfishing.api.mechanic.context.ContextKeys;
|
||||
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 org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
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 Context<Player> context;
|
||||
private final double radius;
|
||||
|
||||
public ActivatedTotem(Player activator, Location coreLocation, TotemConfig config) {
|
||||
this.context = Context.player(activator, true)
|
||||
.arg(ContextKeys.LOCATION, coreLocation)
|
||||
.arg(ContextKeys.X, coreLocation.getBlockX())
|
||||
.arg(ContextKeys.Y, coreLocation.getBlockY())
|
||||
.arg(ContextKeys.Z, coreLocation.getBlockZ())
|
||||
.arg(ContextKeys.ID, config.id());
|
||||
this.subTasks = new ArrayList<>();
|
||||
this.expireTime = (long) (System.currentTimeMillis() + config.duration().evaluate(context) * 1000L);
|
||||
this.coreLocation = coreLocation.clone().add(0.5,0,0.5);
|
||||
this.totemConfig = config;
|
||||
this.radius = config.duration().evaluate(context);
|
||||
for (TotemParticle particleSetting : config.particleSettings()) {
|
||||
this.subTasks.add(particleSetting.start(coreLocation, radius));
|
||||
}
|
||||
}
|
||||
|
||||
public TotemConfig getTotemConfig() {
|
||||
return totemConfig;
|
||||
}
|
||||
|
||||
public Location getCoreLocation() {
|
||||
return coreLocation;
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
for (SchedulerTask task : this.subTasks) {
|
||||
task.cancel();
|
||||
}
|
||||
this.subTasks.clear();
|
||||
}
|
||||
|
||||
public long getExpireTime() {
|
||||
return this.expireTime;
|
||||
}
|
||||
|
||||
public double getRadius() {
|
||||
return radius;
|
||||
}
|
||||
|
||||
public void doTimerAction() {
|
||||
this.context.arg(ContextKeys.TIME_LEFT, String.valueOf((expireTime - System.currentTimeMillis())/1000));
|
||||
BukkitCustomFishingPlugin.getInstance().getEventManager().getEventCarrier(totemConfig.id())
|
||||
.ifPresent(carrier -> carrier.trigger(context, ActionTrigger.TIMER));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,357 +17,406 @@
|
||||
|
||||
package net.momirealms.customfishing.bukkit.totem;
|
||||
|
||||
import dev.dejvokep.boostedyaml.YamlDocument;
|
||||
import dev.dejvokep.boostedyaml.block.implementation.Section;
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import net.momirealms.customfishing.api.mechanic.config.ConfigManager;
|
||||
import net.momirealms.customfishing.api.mechanic.misc.value.MathValue;
|
||||
import net.momirealms.customfishing.api.mechanic.totem.TotemConfig;
|
||||
import net.momirealms.customfishing.api.mechanic.totem.TotemManager;
|
||||
import net.momirealms.customfishing.api.mechanic.totem.TotemModel;
|
||||
import net.momirealms.customfishing.api.mechanic.totem.block.TotemBlock;
|
||||
import net.momirealms.customfishing.api.mechanic.totem.block.property.AxisImpl;
|
||||
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.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.event.EventHandler;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
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 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]);
|
||||
// }
|
||||
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();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getActivatedTotems(Location location) {
|
||||
Collection<String> activated = new ArrayList<>();
|
||||
double nearest = Double.MAX_VALUE;
|
||||
String nearestTotemID = null;
|
||||
for (ActivatedTotem activatedTotem : activatedTotems.values()) {
|
||||
double distance = LocationUtils.getDistance(activatedTotem.getCoreLocation(), location);
|
||||
if (distance < activatedTotem.getRadius()) {
|
||||
activated.add(activatedTotem.getTotemConfig().id());
|
||||
if (nearest > distance) {
|
||||
nearest = distance;
|
||||
nearestTotemID = activatedTotem.getTotemConfig().id();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nearestTotemID == null) return List.of();
|
||||
if (!ConfigManager.allowMultipleTotemType()) {
|
||||
if (ConfigManager.allowSameTotemType()) {
|
||||
String finalNearestTotemID = nearestTotemID;
|
||||
activated.removeIf(element -> !element.equals(finalNearestTotemID));
|
||||
return activated;
|
||||
} else {
|
||||
return List.of(nearestTotemID);
|
||||
}
|
||||
} else {
|
||||
if (ConfigManager.allowSameTotemType()) {
|
||||
return activated;
|
||||
} else {
|
||||
return new HashSet<>(activated);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@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 (ignoreCancelled = true)
|
||||
public void onInteractBlock(PlayerInteractEvent event) {
|
||||
if (
|
||||
event.isBlockInHand() ||
|
||||
event.getAction() != org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK ||
|
||||
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.getBoostrap().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) {
|
||||
YamlDocument config = plugin.getConfigManager().loadData(file);
|
||||
for (Map.Entry<String, Object> entry : config.getStringRouteMappedValues(false).entrySet()) {
|
||||
if (entry.getValue() instanceof Section section) {
|
||||
TotemConfig totemConfig = TotemConfig.builder()
|
||||
.id(entry.getKey())
|
||||
.totemModels(getTotemModels(section.getSection("pattern")))
|
||||
.activateRequirements(plugin.getRequirementManager().parseRequirements(section.getSection("requirements"), true))
|
||||
.radius(MathValue.auto(section.get("radius", 8.0)))
|
||||
.duration(MathValue.auto(section.get("duration", 100)))
|
||||
.particleSettings(getParticleSettings(section.getSection("particles")))
|
||||
.build();
|
||||
|
||||
HashSet<String> coreMaterials = new HashSet<>();
|
||||
for (TotemBlock totemBlock : totemConfig.totemCore()) {
|
||||
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(Section section) {
|
||||
List<ParticleSetting> particleSettings = new ArrayList<>();
|
||||
if (section != null)
|
||||
for (Map.Entry<String, Object> entry : section.getStringRouteMappedValues(false).entrySet()) {
|
||||
if (entry.getValue() instanceof Section innerSection) {
|
||||
particleSettings.add(getParticleSetting(innerSection));
|
||||
}
|
||||
}
|
||||
return particleSettings.toArray(new ParticleSetting[0]);
|
||||
}
|
||||
|
||||
public ParticleSetting getParticleSetting(Section 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])
|
||||
),
|
||||
section.getDouble("options.scale", 1.0).floatValue()
|
||||
)
|
||||
);
|
||||
} 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])
|
||||
),
|
||||
section.getDouble("options.scale", 1.0).floatValue()
|
||||
)
|
||||
);
|
||||
} else {
|
||||
return new ParticleSetting(
|
||||
formulaHorizontal,
|
||||
formulaVertical,
|
||||
particle,
|
||||
interval,
|
||||
ranges,
|
||||
delay,
|
||||
period
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private TotemModel[] getTotemModels(Section 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")
|
||||
private TotemModel parseModel(Section section) {
|
||||
Section layerSection = section.getSection("layer");
|
||||
List<TotemBlock[][][]> totemBlocksList = new ArrayList<>();
|
||||
if (layerSection != null) {
|
||||
var set = layerSection.getStringRouteMappedValues(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][][][])
|
||||
);
|
||||
}
|
||||
|
||||
private TotemBlock[][][] parseLayer(List<String> lines) {
|
||||
List<TotemBlock[][]> totemBlocksList = new ArrayList<>();
|
||||
for (String line : lines) {
|
||||
totemBlocksList.add(parseSingleLine(line));
|
||||
}
|
||||
return totemBlocksList.toArray(new TotemBlock[0][][]);
|
||||
}
|
||||
|
||||
private 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][]);
|
||||
}
|
||||
|
||||
private 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]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,10 +15,16 @@ reload:
|
||||
|
||||
sellfish:
|
||||
enable: true
|
||||
permission: customfishing.command.sellfish
|
||||
permission: customfishing.sellfish
|
||||
usage:
|
||||
- /sellfish
|
||||
|
||||
fishingbag:
|
||||
enable: true
|
||||
permission: fishingbag.user
|
||||
usage:
|
||||
- /fishingbag
|
||||
|
||||
get_item:
|
||||
enable: true
|
||||
permission: customfishing.command.getitem
|
||||
@@ -66,4 +72,25 @@ open_bag:
|
||||
permission: customfishing.command.open.bag
|
||||
usage:
|
||||
- /customfishing open bag
|
||||
- /cfishing open bag
|
||||
- /cfishing open bag
|
||||
|
||||
edit_online_bag:
|
||||
enable: true
|
||||
permission: customfishing.command.edit.bag
|
||||
usage:
|
||||
- /customfishing fishingbag edit-online
|
||||
- /cfishing fishingbag edit-online
|
||||
|
||||
edit_offline_bag:
|
||||
enable: true
|
||||
permission: customfishing.command.edit.bag
|
||||
usage:
|
||||
- /customfishing fishingbag edit-offline
|
||||
- /cfishing fishingbag edit-offline
|
||||
|
||||
browser:
|
||||
enable: true
|
||||
permission: customfishing.command.browser
|
||||
usage:
|
||||
- /customfishing browser
|
||||
- /cfishing browser
|
||||
@@ -143,8 +143,6 @@ mechanics:
|
||||
|
||||
# Fishing bag is where players can store their baits, utils, hooks and rods (Loot optional)
|
||||
fishing-bag:
|
||||
# Enable
|
||||
enable: true
|
||||
# Fishing bag container title
|
||||
bag-title: '<blue>{player}''s Fishing Bag</blue>'
|
||||
# Other whitelist-items
|
||||
@@ -368,21 +366,18 @@ mechanics:
|
||||
placeholder-limit: 3
|
||||
# If a player could get multiple loots from fishing, should the loots spawn at the same time or have delay for each (measured in ticks)
|
||||
multiple-loot-spawn-delay: 4
|
||||
# Totem settings
|
||||
totem:
|
||||
# Is it allowed for different types of totems to take effect at the same time
|
||||
allow-multiple-type: true
|
||||
# Is it allowed for totems of the same type to take effect cumulatively
|
||||
allow-same-type: false
|
||||
|
||||
# Other settings
|
||||
other-settings:
|
||||
# It's recommended to use MiniMessage format. If you insist on using legacy color code "&", enable the support below.
|
||||
# Disable this would improve performance
|
||||
legacy-color-code-support: true
|
||||
# Thread pool settings
|
||||
thread-pool-settings:
|
||||
# The size of the core Thread pool, that is, the size of the Thread pool when there is no task to execute
|
||||
# Increase the size of corePoolSize when you are running a large server with many players fishing at the same time
|
||||
corePoolSize: 10
|
||||
# The maximum number of threads allowed to be created in the Thread pool. The current number of threads in the Thread pool will not exceed this value
|
||||
maximumPoolSize: 10
|
||||
# If a thread is idle for more than this attribute value, it will exit due to timeout
|
||||
keepAliveTime: 30
|
||||
# Event priority: MONITOR HIGHEST HIGH NORMAL LOW LOWEST
|
||||
event-priority: NORMAL
|
||||
# Save the data from cache to file periodically to minimize the data loss if server crashes
|
||||
|
||||
@@ -38,7 +38,7 @@ argument.parse.failure.aggregate.missing: "<red>Missing component '<arg:0>'</red
|
||||
argument.parse.failure.aggregate.failure: "<red>Invalid component '<arg:0>': <arg:1></red>"
|
||||
argument.parse.failure.either: "<red>Could not resolve <arg:1> or <arg:2> from '<arg:0>'</red>"
|
||||
argument.parse.failure.namedtextcolor: "<red>'<arg:0>' is not a named text color</red>"
|
||||
command.reload.success: "<white>Reloaded. Took <green><arg:0></green>ms.</white>"
|
||||
command.reload.success: "<white>Reloaded. Took <green><arg:0></green> ms.</white>"
|
||||
command.item.failure.not_exist: "<red>Item [<arg:0>] not exists.</red>"
|
||||
command.item.give.success: "<white>Successfully given <arg:0> <arg:1>x <arg:2>.</white>"
|
||||
command.item.get.success: "<white>Successfully got <arg:0>x <arg:1>.</white>"
|
||||
|
||||
Reference in New Issue
Block a user