diff --git a/api/src/main/java/net/momirealms/customfishing/api/CustomFishingPlugin.java b/api/src/main/java/net/momirealms/customfishing/api/CustomFishingPlugin.java index 7755f6c2..c8a3c892 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/CustomFishingPlugin.java +++ b/api/src/main/java/net/momirealms/customfishing/api/CustomFishingPlugin.java @@ -44,6 +44,7 @@ public abstract class CustomFishingPlugin extends JavaPlugin { protected StorageManager storageManager; protected PlaceholderManager placeholderManager; protected StatisticsManager statisticsManager; + protected TotemManager totemManager; private static CustomFishingPlugin instance; @@ -123,6 +124,10 @@ public abstract class CustomFishingPlugin extends JavaPlugin { return storageManager; } + public TotemManager getTotemManager() { + return totemManager; + } + public IntegrationManager getIntegrationManager() { return integrationManager; } diff --git a/build.gradle.kts b/build.gradle.kts index b1670764..ca2f9c7f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,7 +7,7 @@ plugins { allprojects { - version = "2.0-beta" + version = "2.0-beta-0914" apply() apply(plugin = "java") diff --git a/plugin/src/main/java/net/momirealms/customfishing/CustomFishingPluginImpl.java b/plugin/src/main/java/net/momirealms/customfishing/CustomFishingPluginImpl.java index 2caf547c..96f3ab32 100644 --- a/plugin/src/main/java/net/momirealms/customfishing/CustomFishingPluginImpl.java +++ b/plugin/src/main/java/net/momirealms/customfishing/CustomFishingPluginImpl.java @@ -43,6 +43,7 @@ import net.momirealms.customfishing.mechanic.market.MarketManagerImpl; import net.momirealms.customfishing.mechanic.misc.CoolDownManager; import net.momirealms.customfishing.mechanic.requirement.RequirementManagerImpl; import net.momirealms.customfishing.mechanic.statistic.StatisticsManagerImpl; +import net.momirealms.customfishing.mechanic.totem.TotemManagerImpl; import net.momirealms.customfishing.scheduler.SchedulerImpl; import net.momirealms.customfishing.setting.CFConfig; import net.momirealms.customfishing.setting.CFLocale; @@ -97,6 +98,7 @@ public class CustomFishingPluginImpl extends CustomFishingPlugin { this.integrationManager = new IntegrationManagerImpl(this); this.statisticsManager = new StatisticsManagerImpl(this); this.coolDownManager = new CoolDownManager(this); + this.totemManager = new TotemManagerImpl(this); this.reload(); if (CFConfig.updateChecker) this.versionManager.checkUpdate().thenAccept(result -> { @@ -125,6 +127,7 @@ public class CustomFishingPluginImpl extends CustomFishingPlugin { ((PlaceholderManagerImpl) this.placeholderManager).disable(); ((StatisticsManagerImpl) this.statisticsManager).disable(); ((ActionManagerImpl) this.actionManager).disable(); + ((TotemManagerImpl) this.totemManager).disable(); this.coolDownManager.disable(); this.commandManager.unload(); } @@ -146,6 +149,8 @@ public class CustomFishingPluginImpl extends CustomFishingPlugin { ((LootManagerImpl) this.lootManager).load(); ((FishingManagerImpl) this.fishingManager).unload(); ((FishingManagerImpl) this.fishingManager).load(); + ((TotemManagerImpl) this.totemManager).unload(); + ((TotemManagerImpl) this.totemManager).load(); ((EffectManagerImpl) this.effectManager).unload(); ((EffectManagerImpl) this.effectManager).load(); ((MarketManagerImpl) this.marketManager).unload(); 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 1ca85b99..dc3a144b 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 @@ -37,6 +37,7 @@ import net.momirealms.customfishing.setting.CFLocale; import net.momirealms.customfishing.util.ArmorStandUtils; import net.momirealms.customfishing.util.ClassUtils; import net.momirealms.customfishing.util.ConfigUtils; +import net.momirealms.customfishing.util.LocationUtils; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.configuration.ConfigurationSection; @@ -187,6 +188,35 @@ public class ActionManagerImpl implements ActionManager { } }; }); + registerAction("message-nearby", (args, chance) -> { + if (args instanceof ConfigurationSection section) { + List msg = section.getStringList("message"); + int range = section.getInt("range"); + 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); + } + condition.delArg("{near}"); + } + } + }; + } else { + LogUtils.warn("Illegal value format found at action: message-nearby"); + return null; + } + }); registerAction("random-message", (args, chance) -> { ArrayList msg = ConfigUtils.stringListArgs(args); return condition -> { @@ -227,6 +257,34 @@ public class ActionManagerImpl implements ActionManager { }, condition.getLocation()); }; }); + registerAction("command-nearby", (args, chance) -> { + if (args instanceof ConfigurationSection section) { + List cmd = section.getStringList("command"); + int range = section.getInt("range"); + 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); + } + condition.delArg("{near}"); + } + } + }; + } else { + LogUtils.warn("Illegal value format found at action: command-nearby"); + return null; + } + }); } private void registerCloseInvAction() { 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 c49fd8c4..b1f7b3be 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 @@ -140,6 +140,7 @@ public class RequirementManagerImpl implements RequirementManager { this.registerLootRequirement(); this.registerLessThanRequirement(); this.registerNumberEqualRequirement(); + this.registerRegexRequirement(); } public ConditionalElement getConditionalElements(ConfigurationSection section) { @@ -641,6 +642,23 @@ public class RequirementManagerImpl implements RequirementManager { }); } + private void registerRegexRequirement() { + registerRequirement("regex", (args, actions, advanced) -> { + if (args instanceof ConfigurationSection section) { + String v1 = section.getString("papi", ""); + String v2 = section.getString("regex", ""); + return condition -> { + if (ParseUtils.setPlaceholders(condition.getPlayer(), v1).matches(v2)) return true; + if (advanced) triggerActions(actions, condition); + return false; + }; + } else { + LogUtils.warn("Wrong value format found at regex requirement."); + return null; + } + }); + } + private void registerNumberEqualRequirement() { registerRequirement("==", (args, actions, advanced) -> { if (args instanceof ConfigurationSection section) { diff --git a/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/TotemConfig.java b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/TotemConfig.java new file mode 100644 index 00000000..c32fa048 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/TotemConfig.java @@ -0,0 +1,27 @@ +/* + * 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; + +import net.momirealms.customfishing.mechanic.totem.block.TotemBlock; + +public class TotemConfig { + + private TotemBlock[][][][][] totemBlocks; + + +} 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 e5ae6d06..b38f367d 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 @@ -17,5 +17,163 @@ package net.momirealms.customfishing.mechanic.totem; -public class TotemManagerImpl { +import net.momirealms.customfishing.api.CustomFishingPlugin; +import net.momirealms.customfishing.api.manager.TotemManager; +import net.momirealms.customfishing.mechanic.totem.block.AxisImpl; +import net.momirealms.customfishing.mechanic.totem.block.FaceImpl; +import net.momirealms.customfishing.mechanic.totem.block.TotemBlock; +import net.momirealms.customfishing.mechanic.totem.block.TotemBlockProperty; +import net.momirealms.customfishing.mechanic.totem.block.type.TypeCondition; +import net.momirealms.customfishing.util.MatrixUtils; +import org.apache.commons.lang3.SerializationUtils; +import org.bukkit.Axis; +import org.bukkit.Bukkit; +import org.bukkit.block.BlockFace; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; + +import java.io.File; +import java.util.*; + +public class TotemManagerImpl implements TotemManager { + + private final CustomFishingPlugin plugin; + private final HashMap totemConfigMap; + + public TotemManagerImpl(CustomFishingPlugin plugin) { + this.plugin = plugin; + this.totemConfigMap = new HashMap<>(); + } + + public void load() { + this.loadConfig(); + } + + public void unload() { + this.totemConfigMap.clear(); + } + + @SuppressWarnings("DuplicatedCode") + private void loadConfig() { + Deque fileDeque = new ArrayDeque<>(); + for (String type : List.of("totem")) { + File typeFolder = new File(plugin.getDataFolder() + File.separator + "contents" + File.separator + type); + if (!typeFolder.exists()) { + if (!typeFolder.mkdirs()) return; + plugin.saveResource("contents" + File.separator + type + File.separator + "default.yml", false); + } + fileDeque.push(typeFolder); + while (!fileDeque.isEmpty()) { + File file = fileDeque.pop(); + File[] files = file.listFiles(); + if (files == null) continue; + for (File subFile : files) { + if (subFile.isDirectory()) { + fileDeque.push(subFile); + } else if (subFile.isFile() && subFile.getName().endsWith(".yml")) { + this.loadSingleFile(subFile); + } + } + } + } + } + + private void loadSingleFile(File file) { + YamlConfiguration config = YamlConfiguration.loadConfiguration(file); + + } + + public TotemBlock[][][][][] getMirroredRotatedModels(ConfigurationSection section) { + TotemBlock[][][][] originalModel = parseModel(section); + List modelList = new ArrayList<>(); + + for (int i = 0; i < 4; i++) { + TotemBlock[][][][] tempModel = SerializationUtils.clone(originalModel); + for (TotemBlock[][][] totemBlocks : tempModel) { + TotemBlock[][][] rotatedTotemBlocks = MatrixUtils.rotate90(totemBlocks); + for (TotemBlock[][] totemBlocks1 : rotatedTotemBlocks) { + for (TotemBlock[] totemBlocks2 : totemBlocks1) { + for (TotemBlock totemBlock : totemBlocks2) { + totemBlock.rotate90(); + } + } + } + } + modelList.add(tempModel); + + TotemBlock[][][][] tempModel2 = SerializationUtils.clone(tempModel); + for (TotemBlock[][][] totemBlocks : tempModel2) { + MatrixUtils.mirrorHorizontally(totemBlocks); + } + modelList.add(tempModel2); + } + + return modelList.toArray(new TotemBlock[0][][][][]); + } + + @SuppressWarnings("unchecked") + public TotemBlock[][][][] parseModel(ConfigurationSection section) { + List totemBlocksList = new ArrayList<>(); + for (Map.Entry entry : section.getValues(false).entrySet()) { + if (entry.getValue() instanceof List list) { + totemBlocksList.add(parseLayer((List) list)); + } + } + return totemBlocksList.toArray(new TotemBlock[0][][][]); + } + + public TotemBlock[][][] parseLayer(List lines) { + List totemBlocksList = new ArrayList<>(); + for (String line : lines) { + totemBlocksList.add(parseSingleLine(line)); + } + return totemBlocksList.toArray(new TotemBlock[0][][]); + } + + public TotemBlock[][] parseSingleLine(String line) { + List 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 totemBlockList = new ArrayList<>(); + for (String block : orBlocks) { + int index = block.indexOf("{"); + String type = block.substring(0, index-1); + String propertyStr = block.substring(index+1, block.length()-1); + String[] properties = propertyStr.split(";"); + List propertyList = new ArrayList<>(); + for (String property : properties) { + String[] split = property.split("="); + if (split.length <= 2) continue; + String key = split[0]; + String value = split[1]; + switch (key) { + case "face" -> { + BlockFace blockFace = BlockFace.valueOf(value.toUpperCase(Locale.ENGLISH)); + propertyList.add(new FaceImpl(blockFace)); + } + case "axis" -> { + Axis axis = Axis.valueOf(value.toUpperCase(Locale.ENGLISH)); + propertyList.add(new AxisImpl(axis)); + } + } + } + TotemBlock totemBlock = new TotemBlock( + TypeCondition.getTypeCondition(type), + propertyList.toArray(new TotemBlockProperty[0]) + ); + totemBlockList.add(totemBlock); + } + return totemBlockList.toArray(new TotemBlock[0]); + } + + public void disable() { + } } 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/AxisImpl.java new file mode 100644 index 00000000..d37ec6fc --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/AxisImpl.java @@ -0,0 +1,55 @@ +/* + * 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; + +import org.bukkit.Axis; +import org.bukkit.block.Block; +import org.bukkit.block.data.Orientable; + +public class AxisImpl implements TotemBlockProperty { + + private final Axis axis; + + public AxisImpl(Axis axis) { + this.axis = axis; + } + + @Override + public TotemBlockProperty mirror(Axis axis) { + return this; + } + + @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); + } + } + + @Override + public boolean isPropertyMet(Block block) { + if (block.getBlockData() instanceof Orientable orientable) { + return orientable.getAxis().equals(this.axis); + } + return false; + } +} 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/FaceImpl.java new file mode 100644 index 00000000..0a9e23d2 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/FaceImpl.java @@ -0,0 +1,80 @@ +/* + * 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; + +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 { + + private final BlockFace blockFace; + + public FaceImpl(BlockFace blockFace) { + this.blockFace = blockFace; + } + + @Override + public TotemBlockProperty mirror(Axis axis) { + if (axis == Axis.X) { + if (blockFace == BlockFace.SOUTH || blockFace == BlockFace.NORTH) { + return new FaceImpl(blockFace.getOppositeFace()); + } else { + return this; + } + } else if (axis == Axis.Z) { + if (blockFace == BlockFace.EAST || blockFace == BlockFace.WEST) { + return new FaceImpl(blockFace.getOppositeFace()); + } else { + return this; + } + } + return this; + } + + @Override + public TotemBlockProperty rotate90() { + switch (blockFace) { + case UP, DOWN -> { + return this; + } + case EAST -> { + 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); + } + default -> throw new IllegalArgumentException("Unsupported block facing: " + blockFace); + } + } + + @Override + public boolean isPropertyMet(Block block) { + if (block.getBlockData() instanceof Directional directional) { + return directional.getFacing().equals(this.blockFace); + } + return false; + } +} 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 new file mode 100644 index 00000000..aa6648ca --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/TotemBlock.java @@ -0,0 +1,43 @@ +package net.momirealms.customfishing.mechanic.totem.block; + +import net.momirealms.customfishing.mechanic.totem.block.type.TypeCondition; +import org.bukkit.block.Block; + +import java.io.Serializable; + +public class TotemBlock implements Serializable { + + private final TypeCondition typeCondition; + private final TotemBlockProperty[] properties; + + public TotemBlock(TypeCondition typeCondition, TotemBlockProperty[] properties) { + this.typeCondition = typeCondition; + this.properties = properties; + } + + public TypeCondition getTypeCondition() { + return typeCondition; + } + + public TotemBlockProperty[] getProperties() { + return properties; + } + + public boolean isRightBlock(Block block) { + if (!typeCondition.isMet(block)) { + return false; + } + for (TotemBlockProperty property : properties) { + if (!property.isPropertyMet(block)) { + return false; + } + } + return true; + } + + public void rotate90() { + for (TotemBlockProperty property : properties) { + property.rotate90(); + } + } +} 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/TotemBlockProperty.java new file mode 100644 index 00000000..de7c7745 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/TotemBlockProperty.java @@ -0,0 +1,31 @@ +/* + * 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; + +import org.bukkit.Axis; +import org.bukkit.block.Block; + +public interface TotemBlockProperty { + + + TotemBlockProperty mirror(Axis axis); + + TotemBlockProperty rotate90(); + + boolean isPropertyMet(Block block); +} 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 new file mode 100644 index 00000000..e8a3cf5c --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/type/EndWithType.java @@ -0,0 +1,36 @@ +/* + * 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; + +public class EndWithType implements TypeCondition, Serializable { + + private final String end; + + public EndWithType(String end) { + this.end = end; + } + + @Override + public boolean isMet(Block type) { + return type.getType().name().endsWith(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 new file mode 100644 index 00000000..bbc0e3ed --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/type/EqualType.java @@ -0,0 +1,36 @@ +/* + * 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; + +public class EqualType implements TypeCondition, Serializable { + + private final String type; + + public EqualType(String type) { + this.type = type; + } + + @Override + public boolean isMet(Block type) { + return this.type.equals(type.getType().name()); + } +} 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 new file mode 100644 index 00000000..99815f92 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/type/StartWithType.java @@ -0,0 +1,36 @@ +/* + * 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; + +public class StartWithType implements TypeCondition, Serializable { + + private final String start; + + public StartWithType(String start) { + this.start = start; + } + + @Override + public boolean isMet(Block type) { + return type.getType().name().startsWith(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 new file mode 100644 index 00000000..b57e16a4 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/mechanic/totem/block/type/TypeCondition.java @@ -0,0 +1,35 @@ +/* + * 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; + +public interface TypeCondition { + + boolean isMet(Block block); + + static TypeCondition getTypeCondition(String raw) { + if (raw.startsWith("*")) { + return new EndWithType(raw.substring(1)); + } else if (raw.endsWith("*")) { + return new StartWithType(raw.substring(0, raw.length() -1)); + } else { + return new EqualType(raw); + } + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/util/LocationUtils.java b/plugin/src/main/java/net/momirealms/customfishing/util/LocationUtils.java new file mode 100644 index 00000000..2ee76af0 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/util/LocationUtils.java @@ -0,0 +1,30 @@ +/* + * 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.util; + +import org.bukkit.Location; + +public class LocationUtils { + + public static double getDistance(Location location1, Location location2) { + return Math.sqrt(Math.pow(location2.getX() - location1.getX(), 2) + + Math.pow(location2.getY() - location1.getY(), 2) + + Math.pow(location2.getZ() - location1.getZ(), 2) + ); + } +} diff --git a/plugin/src/main/java/net/momirealms/customfishing/util/MatrixUtils.java b/plugin/src/main/java/net/momirealms/customfishing/util/MatrixUtils.java new file mode 100644 index 00000000..2abe0e33 --- /dev/null +++ b/plugin/src/main/java/net/momirealms/customfishing/util/MatrixUtils.java @@ -0,0 +1,48 @@ +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 9ce810a5..66a07391 100644 --- a/plugin/src/main/resources/contents/totem/default.yml +++ b/plugin/src/main/resources/contents/totem/default.yml @@ -1,70 +1,15 @@ +# it's still unavailable for the moment double_loot_fishing_totem: - # Totem Core Block ID + rotate-check: true + mirror-check: true core: - - o - - radius: 8 - # seconds - duration: 300 - particle: DRIPPING_OBSIDIAN_TEAR - - hologram: - enable: true - text: - - '<#87CEFA>{player}''s Fishing Totem' - - '{time}s / {max_time}s' - y-offset: 3.8 - - # Potion effect type and its amplifier - potion-effects: - NIGHT_VISION: 1 - - # Fishing bonus - effect: - double-loot: 1 - - # placeholders: {activator} {player} {world} {x} {y} {z} - action: - #commands-activator: [] - messages-activator: - - '[CustomFishing] You activated a double loot totem!' - #commands-nearby-players: [] - messages-nearby-players: - - '[!] {activator} activated a fishing totem!' - - '[!] Players inside of the effective range would get fishing buffs!' - - # https://mo-mi.gitbook.io/xiaomomi-plugins/plugin-wiki/customfishing/requirements - requirements: - requirement_1: - type: permission - message: 'You don''t have permission to activate this totem!' - value: double_loot_fishing_totem.activate - requirement_2: - type: world - message: 'You can only activate this totem in Nether.' - value: - - world_nether - - # The layout of the totem - # 图腾的摆放放 - # The greater the layer number is, the higher the y position is - # 层数越高,则对应的Y坐标也越高 - # Totem core can be put anywhere in the layout - # 图腾核心可以位于摆放中的任意位置 - # “*” represents any type of block is allowed here [example *] - # “*” 代表这个位置可以用任何方块 - # “()“ represents the block is protected and will not be removed when activating [example (a)] - # “()“ 代表图腾激活后此方块会被保护 - # “>“ represents the block would turn into another block after activating [example: a>b] - # ">" 代表图腾激活后,左边的方块会变成右边的方块 - # “|“ represents alternative block choice for this place [example a|b>c] - # “|“ 代表这个位置可以使用多种替选方块 + position: 3,1,2 layer: - 4: - - '(p) (o) (p)' - 3: - - 'air (c) air' - 2: - - 'air (pillar) air' 1: - - 'air (a) air' \ No newline at end of file + - '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