9
0
mirror of https://github.com/Xiao-MoMi/Custom-Fishing.git synced 2025-12-27 10:59:13 +00:00

minor update

This commit is contained in:
XiaoMoMi
2023-09-15 01:50:20 +08:00
parent 9ed926364f
commit 61404cab2d
18 changed files with 714 additions and 68 deletions

View File

@@ -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();

View File

@@ -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<String> 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<String> 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<String> 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<String> 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<String> 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() {

View File

@@ -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) {

View File

@@ -0,0 +1,27 @@
/*
* 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.mechanic.totem;
import net.momirealms.customfishing.mechanic.totem.block.TotemBlock;
public class TotemConfig {
private TotemBlock[][][][][] totemBlocks;
}

View File

@@ -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<String, TotemConfig> 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<File> fileDeque = new ArrayDeque<>();
for (String type : List.of("totem")) {
File typeFolder = new File(plugin.getDataFolder() + File.separator + "contents" + File.separator + type);
if (!typeFolder.exists()) {
if (!typeFolder.mkdirs()) return;
plugin.saveResource("contents" + File.separator + type + File.separator + "default.yml", false);
}
fileDeque.push(typeFolder);
while (!fileDeque.isEmpty()) {
File file = fileDeque.pop();
File[] files = file.listFiles();
if (files == null) continue;
for (File subFile : files) {
if (subFile.isDirectory()) {
fileDeque.push(subFile);
} else if (subFile.isFile() && subFile.getName().endsWith(".yml")) {
this.loadSingleFile(subFile);
}
}
}
}
}
private void loadSingleFile(File file) {
YamlConfiguration config = YamlConfiguration.loadConfiguration(file);
}
public TotemBlock[][][][][] getMirroredRotatedModels(ConfigurationSection section) {
TotemBlock[][][][] originalModel = parseModel(section);
List<TotemBlock[][][][]> 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<TotemBlock[][][]> totemBlocksList = new ArrayList<>();
for (Map.Entry<String, Object> entry : section.getValues(false).entrySet()) {
if (entry.getValue() instanceof List<?> list) {
totemBlocksList.add(parseLayer((List<String>) list));
}
}
return 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("{");
String type = block.substring(0, index-1);
String propertyStr = block.substring(index+1, block.length()-1);
String[] properties = propertyStr.split(";");
List<TotemBlockProperty> 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() {
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (C) <2022> <XiaoMoMi>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.momirealms.customfishing.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;
}
}

View File

@@ -0,0 +1,80 @@
/*
* 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.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;
}
}

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,31 @@
/*
* 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.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);
}

View File

@@ -0,0 +1,36 @@
/*
* 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.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);
}
}

View File

@@ -0,0 +1,36 @@
/*
* 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.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());
}
}

View File

@@ -0,0 +1,36 @@
/*
* 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.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);
}
}

View File

@@ -0,0 +1,35 @@
/*
* 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.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);
}
}
}

View File

@@ -0,0 +1,30 @@
/*
* 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.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)
);
}
}

View File

@@ -0,0 +1,48 @@
package net.momirealms.customfishing.util;
public class MatrixUtils {
public static <T> 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 <T> 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 <T> 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;
}
}
}
}

View File

@@ -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'
- '<white>{time}s <gray>/ <white>{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:
- '<gold>[CustomFishing] You activated a double loot totem!'
#commands-nearby-players: []
messages-nearby-players:
- '<blue>[!] {activator} activated a fishing totem!'
- '<blue>[!] 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: '<red>You don''t have permission to activate this totem!'
value: double_loot_fishing_totem.activate
requirement_2:
type: world
message: '<red>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'
- '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}'