From b61391cea678dfb461ea6a61bd3e96ec15780608 Mon Sep 17 00:00:00 2001 From: XiaoMoMi <972454774@qq.com> Date: Sun, 17 Sep 2023 23:06:47 +0800 Subject: [PATCH] totems --- .../api/mechanic/action/ActionTrigger.java | 2 +- build.gradle.kts | 2 +- plugin/build.gradle.kts | 1 + .../compatibility/IntegrationManagerImpl.java | 3 + .../compatibility/VaultHook.java | 40 ++++ .../mechanic/action/ActionManagerImpl.java | 177 ++++++++++++++---- .../requirement/RequirementManagerImpl.java | 15 ++ .../mechanic/totem/ActivatedTotem.java | 32 ++++ .../mechanic/totem/TotemManagerImpl.java | 70 ++++--- .../mechanic/totem/TotemModel.java | 23 ++- .../mechanic/totem/block/TotemBlock.java | 11 ++ .../totem/block/{ => property}/AxisImpl.java | 25 ++- .../totem/block/{ => property}/FaceImpl.java | 31 +-- .../{ => property}/TotemBlockProperty.java | 4 +- .../totem/block/type/EndWithType.java | 4 +- .../mechanic/totem/block/type/EqualType.java | 7 +- .../mechanic/totem/block/type/OrType.java | 52 ----- .../totem/block/type/StartWithType.java | 4 +- .../totem/block/type/TypeCondition.java | 11 +- .../customfishing/util/MatrixUtils.java | 48 ----- .../main/resources/contents/totem/default.yml | 172 +++++++++++++++-- plugin/src/main/resources/game-conditions.yml | 14 +- 22 files changed, 518 insertions(+), 230 deletions(-) create mode 100644 plugin/src/main/java/net/momirealms/customfishing/compatibility/VaultHook.java rename plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/{ => property}/AxisImpl.java (71%) rename plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/{ => property}/FaceImpl.java (77%) rename plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/{ => property}/TotemBlockProperty.java (90%) delete mode 100644 plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/type/OrType.java delete mode 100644 plugin/src/main/java/net/momirealms/customfishing/util/MatrixUtils.java diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/ActionTrigger.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/ActionTrigger.java index 70850f41..f73ab0cc 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/ActionTrigger.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/action/ActionTrigger.java @@ -26,5 +26,5 @@ public enum ActionTrigger { CAST, BITE, LAND, - ACTIVATE, INTERACT + ACTIVATE, TIMER, INTERACT } diff --git a/build.gradle.kts b/build.gradle.kts index 4843f050..26afabcf 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,7 +7,7 @@ plugins { allprojects { - version = "2.0-beta-0916" + version = "2.0-beta-0917" apply() apply(plugin = "java") diff --git a/plugin/build.gradle.kts b/plugin/build.gradle.kts index bdcb77a8..16816955 100644 --- a/plugin/build.gradle.kts +++ b/plugin/build.gradle.kts @@ -43,6 +43,7 @@ dependencies { compileOnly("pers.neige.neigeitems:NeigeItems:1.15.9") compileOnly("com.github.Zrips:Jobs:4.17.2") compileOnly("com.github.Archy-X:AureliumSkills:Beta1.3.21") + compileOnly("com.github.MilkBowl:VaultAPI:1.7") // local jars compileOnly(files("libs/AdvancedEnchantments-api.jar")) diff --git a/plugin/src/main/java/net/momirealms/customfishing/compatibility/IntegrationManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/IntegrationManagerImpl.java index 723d1948..49ece251 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/compatibility/IntegrationManagerImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/IntegrationManagerImpl.java @@ -126,6 +126,9 @@ public class IntegrationManagerImpl implements IntegrationManager { } else if (plugin.isHookedPluginEnabled("CustomCrops")) { this.seasonInterface = new CustomCropsSeasonImpl(); } + if (plugin.isHookedPluginEnabled("Vault")) { + VaultHook.initialize(); + } } @Override diff --git a/plugin/src/main/java/net/momirealms/customfishing/compatibility/VaultHook.java b/plugin/src/main/java/net/momirealms/customfishing/compatibility/VaultHook.java new file mode 100644 index 00000000..14c2e391 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/compatibility/VaultHook.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) <2022> + * + * 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 . + */ + +package net.momirealms.customfishing.compatibility; + +import net.milkbowl.vault.economy.Economy; +import net.momirealms.customfishing.api.CustomFishingPlugin; +import org.bukkit.plugin.RegisteredServiceProvider; + +public class VaultHook { + + private static Economy economy; + + public static boolean initialize() { + RegisteredServiceProvider rsp = CustomFishingPlugin.getInstance().getServer().getServicesManager().getRegistration(Economy.class); + if (rsp == null) { + return false; + } + economy = rsp.getProvider(); + return true; + } + + public static Economy getEconomy() { + return economy; + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/action/ActionManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/action/ActionManagerImpl.java index 67ee6825..489aef76 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/action/ActionManagerImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/action/ActionManagerImpl.java @@ -32,6 +32,7 @@ import net.momirealms.customfishing.api.mechanic.action.ActionTrigger; import net.momirealms.customfishing.api.mechanic.loot.Loot; import net.momirealms.customfishing.api.mechanic.requirement.Requirement; import net.momirealms.customfishing.api.util.LogUtils; +import net.momirealms.customfishing.compatibility.VaultHook; import net.momirealms.customfishing.compatibility.papi.PlaceholderManagerImpl; import net.momirealms.customfishing.mechanic.item.ItemManagerImpl; import net.momirealms.customfishing.setting.CFLocale; @@ -40,6 +41,7 @@ import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Entity; import org.bukkit.entity.ExperienceOrb; import org.bukkit.entity.Player; import org.bukkit.inventory.EquipmentSlot; @@ -90,6 +92,7 @@ public class ActionManagerImpl implements ActionManager { this.registerItemAmountAction(); this.registerItemDurabilityAction(); this.registerGiveItemAction(); + this.registerMoneyAction(); } public void load() { @@ -199,22 +202,23 @@ public class ActionManagerImpl implements ActionManager { return condition -> { if (Math.random() > chance) return; Player owner = condition.getPlayer(); - - for (Player player : Bukkit.getOnlinePlayers()) { - double distance = LocationUtils.getDistance(player.getLocation(), owner.getLocation()); - if (distance <= range) { - condition.insertArg("{near}", player.getName()); - List replaced = PlaceholderManagerImpl.getInstance().parse( - owner, - msg, - condition.getArgs() - ); - for (String text : replaced) { - AdventureManagerImpl.getInstance().sendPlayerMessage(player, text); + plugin.getScheduler().runTaskSync(() -> { + for (Entity player : condition.getLocation().getWorld().getNearbyEntities(condition.getLocation(), range, range, range, entity -> entity instanceof Player)) { + double distance = LocationUtils.getDistance(player.getLocation(), condition.getLocation()); + if (distance <= range) { + condition.insertArg("{near}", player.getName()); + List replaced = PlaceholderManagerImpl.getInstance().parse( + owner, + msg, + condition.getArgs() + ); + for (String text : replaced) { + AdventureManagerImpl.getInstance().sendPlayerMessage((Player) player, text); + } + condition.delArg("{near}"); } - condition.delArg("{near}"); } - } + }, condition.getLocation()); }; } else { LogUtils.warn("Illegal value format found at action: message-nearby"); @@ -268,21 +272,23 @@ public class ActionManagerImpl implements ActionManager { return condition -> { if (Math.random() > chance) return; Player owner = condition.getPlayer(); - for (Player player : Bukkit.getOnlinePlayers()) { - double distance = LocationUtils.getDistance(player.getLocation(), owner.getLocation()); - if (distance <= range) { - condition.insertArg("{near}", player.getName()); - List replaced = PlaceholderManagerImpl.getInstance().parse( - owner, - cmd, - condition.getArgs() - ); - for (String text : replaced) { - Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), text); + plugin.getScheduler().runTaskSync(() -> { + for (Entity player : condition.getLocation().getWorld().getNearbyEntities(condition.getLocation(), range, range, range, entity -> entity instanceof Player)) { + double distance = LocationUtils.getDistance(player.getLocation(), condition.getLocation()); + if (distance <= range) { + condition.insertArg("{near}", player.getName()); + List replaced = PlaceholderManagerImpl.getInstance().parse( + owner, + cmd, + condition.getArgs() + ); + for (String text : replaced) { + Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), text); + } + condition.delArg("{near}"); } - condition.delArg("{near}"); } - } + }, condition.getLocation()); }; } else { LogUtils.warn("Illegal value format found at action: command-nearby"); @@ -316,6 +322,35 @@ public class ActionManagerImpl implements ActionManager { AdventureManagerImpl.getInstance().sendActionbar(condition.getPlayer(), random); }; }); + registerAction("actionbar-nearby", (args, chance) -> { + if (args instanceof ConfigurationSection section) { + String actionbar = section.getString("actionbar"); + int range = section.getInt("range"); + return condition -> { + if (Math.random() > chance) return; + Player owner = condition.getPlayer(); + plugin.getScheduler().runTaskSync(() -> { + for (Entity player : condition.getLocation().getWorld().getNearbyEntities(condition.getLocation(), range, range, range, entity -> entity instanceof Player)) { + double distance = LocationUtils.getDistance(player.getLocation(), condition.getLocation()); + if (distance <= range) { + condition.insertArg("{near}", player.getName()); + String replaced = PlaceholderManagerImpl.getInstance().parse( + owner, + actionbar, + condition.getArgs() + ); + AdventureManagerImpl.getInstance().sendActionbar((Player) player, replaced); + condition.delArg("{near}"); + } + } + }, condition.getLocation() + ); + }; + } else { + LogUtils.warn("Illegal value format found at action: command-nearby"); + return null; + } + }); } private void registerMendingAction() { @@ -367,21 +402,30 @@ public class ActionManagerImpl implements ActionManager { if (args instanceof ConfigurationSection section) { String text = section.getString("text", ""); int duration = section.getInt("duration", 20); - boolean position = section.getString("position", "hook").equals("hook"); + boolean position = section.getString("position", "other").equals("other"); double x = section.getDouble("x"); double y = section.getDouble("y"); double z = section.getDouble("z"); + int range = section.getInt("range", 16); return condition -> { if (Math.random() > chance) return; - Player player = condition.getPlayer(); - Location location = position ? condition.getLocation() : player.getLocation(); - ArmorStandUtils.sendHologram( - condition.getPlayer(), - location.clone().add(x, y, z), - AdventureManagerImpl.getInstance().getComponentFromMiniMessage( - PlaceholderManagerImpl.getInstance().parse(player, text, condition.getArgs()) - ), - duration + Player owner = condition.getPlayer(); + Location location = position ? condition.getLocation() : owner.getLocation(); + plugin.getScheduler().runTaskSync(() -> { + for (Entity player : condition.getLocation().getWorld().getNearbyEntities(condition.getLocation(), range, range, range, entity -> entity instanceof Player)) { + double distance = LocationUtils.getDistance(player.getLocation(), condition.getLocation()); + if (distance <= range) { + ArmorStandUtils.sendHologram( + (Player) player, + location.clone().add(x, y, z), + AdventureManagerImpl.getInstance().getComponentFromMiniMessage( + PlaceholderManagerImpl.getInstance().parse(owner, text, condition.getArgs()) + ), + duration + ); + } + } + }, condition.getLocation() ); }; } else { @@ -494,6 +538,23 @@ public class ActionManagerImpl implements ActionManager { }); } + private void registerMoneyAction() { + registerAction("give-money", (args, chance) -> { + double money = ConfigUtils.getDoubleValue(args); + return condition -> { + if (Math.random() > chance) return; + VaultHook.getEconomy().depositPlayer(condition.getPlayer(), money); + }; + }); + registerAction("take-money", (args, chance) -> { + double money = ConfigUtils.getDoubleValue(args); + return condition -> { + if (Math.random() > chance) return; + VaultHook.getEconomy().withdrawPlayer(condition.getPlayer(), money); + }; + }); + } + private void registerDelayedAction() { registerAction("delay", (args, chance) -> { List actions = new ArrayList<>(); @@ -541,8 +602,44 @@ public class ActionManagerImpl implements ActionManager { fadeOut * 50 ); }; + } else { + LogUtils.warn("Illegal value format found at action: title"); + return null; + } + }); + registerAction("title-nearby", (args, chance) -> { + if (args instanceof ConfigurationSection section) { + String title = section.getString("title"); + String subtitle = section.getString("subtitle"); + int fadeIn = section.getInt("fade-in", 20); + int stay = section.getInt("stay", 30); + int fadeOut = section.getInt("fade-out", 10); + int range = section.getInt("range", 32); + return condition -> { + if (Math.random() > chance) return; + plugin.getScheduler().runTaskSync(() -> { + for (Entity player : condition.getLocation().getWorld().getNearbyEntities(condition.getLocation(), range, range, range, entity -> entity instanceof Player)) { + double distance = LocationUtils.getDistance(player.getLocation(), condition.getLocation()); + if (distance <= range) { + condition.insertArg("{near}", player.getName()); + AdventureManagerImpl.getInstance().sendTitle( + condition.getPlayer(), + PlaceholderManagerImpl.getInstance().parse(condition.getPlayer(), title, condition.getArgs()), + PlaceholderManagerImpl.getInstance().parse(condition.getPlayer(), subtitle, condition.getArgs()), + fadeIn * 50, + stay * 50, + fadeOut * 50 + ); + condition.delArg("{near}"); + } + } + }, condition.getLocation() + ); + }; + } else { + LogUtils.warn("Illegal value format found at action: title-nearby"); + return null; } - return null; }); registerAction("random-title", (args, chance) -> { if (args instanceof ConfigurationSection section) { @@ -562,8 +659,10 @@ public class ActionManagerImpl implements ActionManager { fadeOut * 50 ); }; + } else { + LogUtils.warn("Illegal value format found at action: random-title"); + return null; } - return null; }); } diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/requirement/RequirementManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/requirement/RequirementManagerImpl.java index f310d990..25564cd3 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/requirement/RequirementManagerImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/requirement/RequirementManagerImpl.java @@ -30,6 +30,7 @@ import net.momirealms.customfishing.api.mechanic.requirement.Requirement; import net.momirealms.customfishing.api.mechanic.requirement.RequirementExpansion; import net.momirealms.customfishing.api.mechanic.requirement.RequirementFactory; import net.momirealms.customfishing.api.util.LogUtils; +import net.momirealms.customfishing.compatibility.VaultHook; import net.momirealms.customfishing.compatibility.papi.ParseUtils; import net.momirealms.customfishing.util.ClassUtils; import net.momirealms.customfishing.util.ConfigUtils; @@ -143,6 +144,7 @@ public class RequirementManagerImpl implements RequirementManager { this.registerNumberEqualRequirement(); this.registerRegexRequirement(); this.registerItemInHandRequirement(); + this.registerMoneyRequirement(); } public ConditionalElement getConditionalElements(ConfigurationSection section) { @@ -465,6 +467,19 @@ public class RequirementManagerImpl implements RequirementManager { }); } + private void registerMoneyRequirement() { + registerRequirement("money", (args, actions, advanced) -> { + double money = ConfigUtils.getDoubleValue(args); + return condition -> { + double current = VaultHook.getEconomy().getBalance(condition.getPlayer()); + if (current >= money) + return true; + if (advanced) triggerActions(actions, condition); + return false; + }; + }); + } + private void registerRandomRequirement() { registerRequirement("random", (args, actions, advanced) -> { double random = ConfigUtils.getDoubleValue(args); diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/ActivatedTotem.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/ActivatedTotem.java index 79a12cc5..435a1e6b 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/ActivatedTotem.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/ActivatedTotem.java @@ -17,11 +17,17 @@ package net.momirealms.customfishing.mechanic.totem; +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.mechanic.action.Action; +import net.momirealms.customfishing.api.mechanic.action.ActionTrigger; +import net.momirealms.customfishing.api.mechanic.condition.Condition; +import net.momirealms.customfishing.api.mechanic.effect.EffectCarrier; import net.momirealms.customfishing.api.scheduler.CancellableTask; import net.momirealms.customfishing.mechanic.totem.particle.ParticleSetting; import org.bukkit.Location; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; public class ActivatedTotem { @@ -29,11 +35,15 @@ public class ActivatedTotem { private final List 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 = CustomFishingPlugin.get().getEffectManager().getEffect("totem", config.getKey()); for (ParticleSetting particleSetting : config.getParticleSettings()) { this.subTasks.add(particleSetting.start(coreLocation, config.getRadius())); } @@ -52,4 +62,26 @@ public class ActivatedTotem { task.cancel(); } } + + public long getExpireTime() { + return expireTime; + } + + public void doTimerAction() { + HashMap args = new HashMap<>(); + args.put("{time_left}", String.valueOf((expireTime - System.currentTimeMillis())/1000)); + Condition condition = new Condition(coreLocation, null, args); + if (effectCarrier != null) { + Action[] actions = effectCarrier.getActions(ActionTrigger.TIMER); + if (actions != null) { + for (Action action : actions) { + action.trigger(condition); + } + } + } + } + + public EffectCarrier getEffectCarrier() { + return effectCarrier; + } } diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/TotemManagerImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/TotemManagerImpl.java index 92f135dc..fa610fb4 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/TotemManagerImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/TotemManagerImpl.java @@ -25,10 +25,11 @@ import net.momirealms.customfishing.api.mechanic.action.Action; import net.momirealms.customfishing.api.mechanic.action.ActionTrigger; import net.momirealms.customfishing.api.mechanic.condition.Condition; import net.momirealms.customfishing.api.mechanic.effect.EffectCarrier; -import net.momirealms.customfishing.mechanic.totem.block.AxisImpl; -import net.momirealms.customfishing.mechanic.totem.block.FaceImpl; +import net.momirealms.customfishing.api.scheduler.CancellableTask; +import net.momirealms.customfishing.mechanic.totem.block.property.AxisImpl; +import net.momirealms.customfishing.mechanic.totem.block.property.FaceImpl; import net.momirealms.customfishing.mechanic.totem.block.TotemBlock; -import net.momirealms.customfishing.mechanic.totem.block.TotemBlockProperty; +import net.momirealms.customfishing.mechanic.totem.block.property.TotemBlockProperty; import net.momirealms.customfishing.mechanic.totem.block.type.TypeCondition; import net.momirealms.customfishing.mechanic.totem.particle.DustParticleSetting; import net.momirealms.customfishing.mechanic.totem.particle.ParticleSetting; @@ -58,6 +59,7 @@ public class TotemManagerImpl implements TotemManager, Listener { private final HashMap> totemConfigMap; private final List allMaterials; private final ConcurrentHashMap activatedTotems; + private CancellableTask timerCheckTask; public TotemManagerImpl(CustomFishingPlugin plugin) { this.plugin = plugin; @@ -69,6 +71,21 @@ public class TotemManagerImpl implements TotemManager, Listener { public void load() { this.loadConfig(); Bukkit.getPluginManager().registerEvents(this, plugin); + this.timerCheckTask = plugin.getScheduler().runTaskAsyncTimer(() -> { + long time = System.currentTimeMillis(); + ArrayList removed = new ArrayList<>(); + for (Map.Entry 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() { @@ -78,6 +95,8 @@ public class TotemManagerImpl implements TotemManager, Listener { } activatedTotems.clear(); HandlerList.unregisterAll(this); + if (this.timerCheckTask != null && !this.timerCheckTask.isCancelled()) + this.timerCheckTask.cancel(); } public void disable() { @@ -89,7 +108,7 @@ public class TotemManagerImpl implements TotemManager, Listener { public EffectCarrier getTotemEffect(Location location) { for (ActivatedTotem activatedTotem : activatedTotems.values()) { if (LocationUtils.getDistance(activatedTotem.getCoreLocation(), location) < activatedTotem.getTotemConfig().getRadius()) { - return plugin.getEffectManager().getEffect("totem", activatedTotem.getTotemConfig().getKey()); + return activatedTotem.getEffectCarrier(); } } return null; @@ -151,11 +170,6 @@ public class TotemManagerImpl implements TotemManager, Listener { if (previous != null) { previous.cancel(); } - - plugin.getScheduler().runTaskAsyncLater(() -> { - ActivatedTotem activated = this.activatedTotems.remove(simpleLocation); - if (activated != null) activated.cancel(); - }, config.getDuration(), TimeUnit.SECONDS); } @SuppressWarnings("DuplicatedCode") @@ -197,19 +211,17 @@ public class TotemManagerImpl implements TotemManager, Listener { HashSet coreMaterials = new HashSet<>(); for (TotemBlock totemBlock : totemConfig.getTotemCore()) { - for (String text : totemBlock.getTypeCondition().getRawTexts()) { - 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); - } + 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); } @@ -319,6 +331,9 @@ public class TotemManagerImpl implements TotemManager, Listener { modelList.add(originalModel.mirrorHorizontally()); } } + for (TotemModel totemModel : modelList) { + System.out.println(totemModel.toString()); + } return modelList.toArray(new TotemModel[0]); } @@ -327,11 +342,14 @@ public class TotemManagerImpl implements TotemManager, Listener { ConfigurationSection layerSection = section.getConfigurationSection("layer"); List totemBlocksList = new ArrayList<>(); if (layerSection != null) { - for (Map.Entry entry : layerSection.getValues(false).entrySet()) { + var set = layerSection.getValues(false).entrySet(); + TotemBlock[][][][] totemBlocks = new TotemBlock[set.size()][][][]; + for (Map.Entry entry : set) { if (entry.getValue() instanceof List list) { - totemBlocksList.add(parseLayer((List) list)); + totemBlocks[Integer.parseInt(entry.getKey())-1] = parseLayer((List) list); } } + totemBlocksList.addAll(List.of(totemBlocks)); } String[] core = section.getString("core","1,1,1").split(","); @@ -354,7 +372,7 @@ public class TotemManagerImpl implements TotemManager, Listener { public TotemBlock[][] parseSingleLine(String line) { List totemBlocksList = new ArrayList<>(); - String[] splits = line.split("\\s"); + String[] splits = line.split("\\s+"); for (String split : splits) { totemBlocksList.add(parseSingleElement(split)); } @@ -371,12 +389,16 @@ public class TotemManagerImpl implements TotemManager, Listener { index = block.length(); } else { String propertyStr = block.substring(index+1, block.length()-1); + System.out.println(propertyStr); String[] properties = propertyStr.split(";"); for (String property : properties) { + System.out.println(property); String[] split = property.split("="); - if (split.length <= 2) continue; + if (split.length < 2) continue; String key = split[0]; String value = split[1]; + System.out.println(key); + System.out.println(value); switch (key) { case "face" -> { BlockFace blockFace = BlockFace.valueOf(value.toUpperCase(Locale.ENGLISH)); diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/TotemModel.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/TotemModel.java index f1d39ebd..3200fb13 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/TotemModel.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/TotemModel.java @@ -23,6 +23,8 @@ import org.bukkit.Axis; import org.bukkit.Location; import java.io.Serializable; +import java.util.Arrays; +import java.util.StringJoiner; public class TotemModel implements Serializable { @@ -58,6 +60,26 @@ public class TotemModel implements Serializable { 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(); + } + @Override public TotemModel clone() { return SerializationUtils.clone(this); @@ -139,7 +161,6 @@ public class TotemModel implements Serializable { 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++) { diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/TotemBlock.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/TotemBlock.java index 289f4a04..b97717b9 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/TotemBlock.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/TotemBlock.java @@ -17,11 +17,13 @@ package net.momirealms.customfishing.mechanic.totem.block; +import net.momirealms.customfishing.mechanic.totem.block.property.TotemBlockProperty; import net.momirealms.customfishing.mechanic.totem.block.type.TypeCondition; import org.bukkit.Axis; import org.bukkit.block.Block; import java.io.Serializable; +import java.util.StringJoiner; public class TotemBlock implements Serializable { @@ -64,4 +66,13 @@ public class TotemBlock implements Serializable { property.mirror(axis); } } + + @Override + public String toString() { + StringJoiner stringJoiner = new StringJoiner(";"); + for (TotemBlockProperty property : properties) { + stringJoiner.add(property.getRawText()); + } + return typeCondition.getRawText() + "{" + stringJoiner + "}"; + } } diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/AxisImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/property/AxisImpl.java similarity index 71% rename from plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/AxisImpl.java rename to plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/property/AxisImpl.java index d37ec6fc..449a9970 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/AxisImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/property/AxisImpl.java @@ -15,15 +15,18 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.mechanic.totem.block; +package net.momirealms.customfishing.mechanic.totem.block.property; import org.bukkit.Axis; import org.bukkit.block.Block; import org.bukkit.block.data.Orientable; -public class AxisImpl implements TotemBlockProperty { +import java.io.Serializable; +import java.util.Locale; - private final Axis axis; +public class AxisImpl implements TotemBlockProperty, Serializable { + + private Axis axis; public AxisImpl(Axis axis) { this.axis = axis; @@ -36,13 +39,12 @@ public class AxisImpl implements TotemBlockProperty { @Override public TotemBlockProperty rotate90() { - if (this.axis == Axis.Y) { - return this; - } else if (this.axis == Axis.X) { - return new AxisImpl(Axis.Z); - } else { - return new AxisImpl(Axis.X); + if (this.axis == Axis.X) { + axis = Axis.Z; + } else if (this.axis == Axis.Z) { + axis = Axis.X; } + return this; } @Override @@ -52,4 +54,9 @@ public class AxisImpl implements TotemBlockProperty { } return false; } + + @Override + public String getRawText() { + return "axis=" + axis.name().toLowerCase(Locale.ENGLISH); + } } diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/FaceImpl.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/property/FaceImpl.java similarity index 77% rename from plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/FaceImpl.java rename to plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/property/FaceImpl.java index 0a9e23d2..1aea4fbf 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/FaceImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/property/FaceImpl.java @@ -15,16 +15,19 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.mechanic.totem.block; +package net.momirealms.customfishing.mechanic.totem.block.property; import org.bukkit.Axis; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.block.data.Directional; -public class FaceImpl implements TotemBlockProperty { +import java.io.Serializable; +import java.util.Locale; - private final BlockFace blockFace; +public class FaceImpl implements TotemBlockProperty, Serializable { + + private BlockFace blockFace; public FaceImpl(BlockFace blockFace) { this.blockFace = blockFace; @@ -54,20 +57,13 @@ public class FaceImpl implements TotemBlockProperty { case UP, DOWN -> { return this; } - case EAST -> { - return new FaceImpl(BlockFace.SOUTH); - } - case SOUTH -> { - return new FaceImpl(BlockFace.WEST); - } - case WEST -> { - return new FaceImpl(BlockFace.NORTH); - } - case NORTH -> { - return new FaceImpl(BlockFace.EAST); - } + 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 @@ -77,4 +73,9 @@ public class FaceImpl implements TotemBlockProperty { } return false; } + + @Override + public String getRawText() { + return "face=" + blockFace.name().toLowerCase(Locale.ENGLISH); + } } diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/TotemBlockProperty.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/property/TotemBlockProperty.java similarity index 90% rename from plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/TotemBlockProperty.java rename to plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/property/TotemBlockProperty.java index de7c7745..43c02903 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/TotemBlockProperty.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/property/TotemBlockProperty.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package net.momirealms.customfishing.mechanic.totem.block; +package net.momirealms.customfishing.mechanic.totem.block.property; import org.bukkit.Axis; import org.bukkit.block.Block; @@ -28,4 +28,6 @@ public interface TotemBlockProperty { TotemBlockProperty rotate90(); boolean isPropertyMet(Block block); + + String getRawText(); } diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/type/EndWithType.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/type/EndWithType.java index 5d889166..7797b7e4 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/type/EndWithType.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/type/EndWithType.java @@ -35,7 +35,7 @@ public class EndWithType implements TypeCondition, Serializable { } @Override - public String[] getRawTexts() { - return new String[]{"*" + end}; + public String getRawText() { + return "*" + end; } } diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/type/EqualType.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/type/EqualType.java index 73b43f0d..56c3ff40 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/type/EqualType.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/type/EqualType.java @@ -17,6 +17,7 @@ package net.momirealms.customfishing.mechanic.totem.block.type; +import net.momirealms.customfishing.api.CustomFishingPlugin; import org.bukkit.block.Block; import java.io.Serializable; @@ -31,11 +32,11 @@ public class EqualType implements TypeCondition, Serializable { @Override public boolean isMet(Block type) { - return this.type.equals(type.getType().name()); + return this.type.equals(CustomFishingPlugin.get().getBlockManager().getAnyBlockID(type)); } @Override - public String[] getRawTexts() { - return new String[]{type}; + public String getRawText() { + return type; } } diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/type/OrType.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/type/OrType.java deleted file mode 100644 index 02c540a9..00000000 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/type/OrType.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) <2022> - * - * 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 . - */ - -package net.momirealms.customfishing.mechanic.totem.block.type; - -import org.bukkit.block.Block; - -import java.io.Serializable; -import java.util.HashSet; -import java.util.List; - -public class OrType implements TypeCondition, Serializable { - - private final TypeCondition[] typeConditions; - - public OrType(TypeCondition[] typeConditions) { - this.typeConditions = typeConditions; - } - - @Override - public boolean isMet(Block block) { - for (TypeCondition typeCondition : typeConditions) { - if (typeCondition.isMet(block)) { - return true; - } - } - return false; - } - - @Override - public String[] getRawTexts() { - HashSet strings = new HashSet<>(); - for (TypeCondition condition : typeConditions) { - strings.addAll(List.of(condition.getRawTexts())); - } - return strings.toArray(new String[0]); - } -} diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/type/StartWithType.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/type/StartWithType.java index 5394a15c..74784288 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/type/StartWithType.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/type/StartWithType.java @@ -35,7 +35,7 @@ public class StartWithType implements TypeCondition, Serializable { } @Override - public String[] getRawTexts() { - return new String[]{start + "*"}; + public String getRawText() { + return start + "*"; } } diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/type/TypeCondition.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/type/TypeCondition.java index 9d49a99d..ea456d67 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/type/TypeCondition.java +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/type/TypeCondition.java @@ -19,26 +19,17 @@ package net.momirealms.customfishing.mechanic.totem.block.type; import org.bukkit.block.Block; -import java.util.ArrayList; -import java.util.List; - public interface TypeCondition { boolean isMet(Block block); - String[] getRawTexts(); + String getRawText(); 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 if (raw.contains("||")) { - String[] split = raw.split("\\|\\|"); - List typeConditionList = new ArrayList<>(); - for (String element : split) - typeConditionList.add(getTypeCondition(element)); - return new OrType(typeConditionList.toArray(new TypeCondition[0])); } else { return new EqualType(raw); } diff --git a/plugin/src/main/java/net/momirealms/customfishing/util/MatrixUtils.java b/plugin/src/main/java/net/momirealms/customfishing/util/MatrixUtils.java deleted file mode 100644 index 2abe0e33..00000000 --- a/plugin/src/main/java/net/momirealms/customfishing/util/MatrixUtils.java +++ /dev/null @@ -1,48 +0,0 @@ -package net.momirealms.customfishing.util; - -public class MatrixUtils { - - public static T[][] rotate90(T[][] matrix) { - int rows = matrix.length; - if (rows == 0) { - return matrix; - } - int cols = matrix[0].length; - - @SuppressWarnings("unchecked") - T[][] rotated = (T[][]) new Object[cols][rows]; - - for (int r = 0; r < rows; r++) { - for (int c = 0; c < cols; c++) { - rotated[c][rows - 1 - r] = matrix[r][c]; - } - } - return rotated; - } - - public static void mirrorHorizontally(T[][] matrix) { - int rows = matrix.length; - int cols = matrix[0].length; - - for (int i = 0; i < rows / 2; i++) { - for (int j = 0; j < cols; j++) { - T temp = matrix[i][j]; - matrix[i][j] = matrix[rows - i - 1][j]; - matrix[rows - i - 1][j] = temp; - } - } - } - - public static void mirrorVertically(T[][] matrix) { - int rows = matrix.length; - int cols = matrix[0].length; - - for (int i = 0; i < rows; i++) { - for (int j = 0; j < cols / 2; j++) { - T temp = matrix[i][j]; - matrix[i][j] = matrix[i][cols - j - 1]; - matrix[i][cols - j - 1] = temp; - } - } - } -} diff --git a/plugin/src/main/resources/contents/totem/default.yml b/plugin/src/main/resources/contents/totem/default.yml index 0156ed49..72aa7177 100644 --- a/plugin/src/main/resources/contents/totem/default.yml +++ b/plugin/src/main/resources/contents/totem/default.yml @@ -1,7 +1,72 @@ -double_loot_fishing_totem: +double_loot_totem: radius: 8 duration: 300 - requirements: {} + pattern: + core: 3,1,2 # layer:3 line:1 index:2 -> CRYING_OBSIDIAN + layer: + 4: + - '*_STAIRS{face=east} OBSERVER{face=south} *_STAIRS{face=west}' + 3: + - 'AIR CRYING_OBSIDIAN AIR' + 2: + - 'AIR *_LOG{axis=y}||*_PILLAR{axis=y} AIR' + 1: + - 'AIR ANVIL AIR' + effects: + double_loot: + type: multiple-loot + value: 1.0 + requirements: + requirement_1: + type: item-in-hand + value: + hand: main + item: NAUTILUS_SHELL + amount: 1 + not-met-actions: + action_1: + type: message + value: + - '<#BA55D3>[TotemActivation] <#F5FFFA>Hold a nautilus shell in main hand to activate the totem.' + events: + timer: + actionbar_action: + type: actionbar-nearby + value: + actionbar: '<#BA55D3>[Double Loot Totem] Time Left: {time_left} seconds' + range: 16 + hologram_action_1: + type: hologram + value: + duration: 20 + text: '<#BA55D3>[Double Loot Totem]' + position: other + range: 16 + y: 3.3 + x: 0 + z: 0 + hologram_action_2: + type: hologram + value: + duration: 20 + text: 'Time Left: {time_left} seconds' + position: other + range: 16 + y: 2.8 + x: 0 + z: 0 + activate: + remove_item_action: + type: item-amount + value: + hand: main + amount: -1 + broadcast_action: + type: message-nearby + value: + message: + - '<#BA55D3>[TotemActivation] <#F5FFFA>{player} <#F5F5F5>activated a totem nearby!' + range: 32 particles: particle_01: type: REDSTONE @@ -138,26 +203,97 @@ double_loot_fishing_totem: task: period: 40 delay: 20 +golden_star_totem: + radius: 10 + duration: 120 + pattern: + core: 4,2,2 # layer:4 line:2 index:2 -> DAYLIGHT_DETECTOR + layer: + 4: + - 'AIR AIR AIR' + - 'AIR DAYLIGHT_DETECTOR AIR' + - 'AIR AIR AIR' + 3: + - 'AIR AIR AIR' + - 'AIR LIGHTNING_ROD AIR' + - 'AIR AIR AIR' + 2: + - 'AIR AIR AIR' + - 'AIR GOLD_BLOCK AIR' + - 'AIR AIR AIR' + 1: + - 'AIR GOLD_BLOCK AIR' + - 'GOLD_BLOCK GOLD_BLOCK GOLD_BLOCK' + - 'AIR GOLD_BLOCK AIR' + particles: + particle_01: + type: REDSTONE + options: + color: 255,215,0 + scale: 3 + polar-coordinates-formula: + horizontal: '{radius} + sin({theta} * 5) * 2.5' + vertical: '-2.5' + theta: + draw-interval: 5 + range: + - 0~360 + task: + period: 5 + delay: 0 effects: - double_loot: - type: multiple-loot - value: 1.0 + golden_weight_increase: + type: group-mod + value: + - golden_star:+15 + requirements: + requirement_1: + type: item-in-hand + value: + hand: main + item: GOLD_INGOT + amount: 1 + not-met-actions: + action_1: + type: message + value: + - '<#BA55D3>[TotemActivation] <#F5FFFA>Hold a gold ingot in main hand to activate the totem.' events: + timer: + actionbar_action: + type: actionbar-nearby + value: + actionbar: '<#FFFF00>[Golden Star Totem] Time Left: {time_left} seconds' + range: 16 + hologram_action_1: + type: hologram + value: + duration: 20 + text: '<#FFFF00>[Golden Star Totem]' + position: other + range: 16 + y: 1 + x: 0 + z: 0 + hologram_action_2: + type: hologram + value: + duration: 20 + text: 'Time Left: {time_left} seconds' + position: other + range: 16 + y: 0.5 + x: 0 + z: 0 activate: + remove_item_action: + type: item-amount + value: + hand: main + amount: -1 broadcast_action: type: message-nearby value: message: - - '<#BA55D3>[TotemActivation] <#F5FFFA>{player} <#F5F5F5>activated a totem nearby!' - range: 32 - pattern: - core: 3,1,2 # layer:3 line:1 index:2 -> CRYING_OBSIDIAN - layer: - 1: - - 'AIR ANVIL AIR' - 2: - - 'AIR *_LOG{axis:y}||*_PILLAR{axis:y} AIR' - 3: - - 'AIR CRYING_OBSIDIAN AIR' - 4: - - '*_STAIRS{face:south} OBSERVER{face:west} *_STAIRS{face:north}' \ No newline at end of file + - '<#FFFF00>[TotemActivation] <#F5FFFA>{player} <#F5F5F5>activated a totem nearby!' + range: 32 \ No newline at end of file diff --git a/plugin/src/main/resources/game-conditions.yml b/plugin/src/main/resources/game-conditions.yml index 47fcf358..0645b1cd 100644 --- a/plugin/src/main/resources/game-conditions.yml +++ b/plugin/src/main/resources/game-conditions.yml @@ -44,8 +44,6 @@ global-group: - rainbow_7:+1 ocean_fish_game: conditions: - group: - - ocean biome: - minecraft:ocean - minecraft:deep_ocean @@ -78,8 +76,16 @@ global-group: - tension_game_hard:+7 river_fish_game: conditions: - group: - - river + '!biome': + - minecraft:ocean + - minecraft:deep_ocean + - minecraft:cold_ocean + - minecraft:deep_cold_ocean + - minecraft:frozen_ocean + - minecraft:deep_frozen_ocean + - minecraft:lukewarm_ocean + - minecraft:deep_lukewarm_ocean + - minecraft:warm_ocean list: - accurate_click_bar_1_easy:+15 - accurate_click_bar_1_normal:+5