9
0
mirror of https://github.com/Xiao-MoMi/Custom-Fishing.git synced 2025-12-26 18:39:11 +00:00

checkpoint - 13

This commit is contained in:
XiaoMoMi
2024-06-12 02:24:09 +08:00
parent 388fbbc341
commit ccbfa68e04
29 changed files with 545 additions and 362 deletions

View File

@@ -113,8 +113,6 @@ public class BukkitCustomFishingPluginImpl extends BukkitCustomFishingPlugin {
else this.getPluginLogger().warn("Update is available: https://polymart.org/resource/2723");
});
}
this.integrationManager.load();
}
@Override

View File

@@ -73,8 +73,18 @@ public class BukkitBagManager implements BagManager, Listener {
public CompletableFuture<Boolean> openBag(Player viewer, UUID owner) {
CompletableFuture<Boolean> future = new CompletableFuture<>();
Optional<UserData> onlineUser = plugin.getStorageManager().getOnlineUser(owner);
onlineUser.ifPresentOrElse(userData -> {
viewer.openInventory(userData.holder().getInventory());
onlineUser.ifPresentOrElse(data -> {
viewer.openInventory(data.holder().getInventory());
SparrowHeart.getInstance().updateInventoryTitle(viewer,
plugin.getPlaceholderManager().parse(
Bukkit.getOfflinePlayer(owner),
ConfigManager.bagTitle(),
Map.of(
"{uuid}", owner.toString(),
"{player}", data.name()
)
)
);
future.complete(true);
}, () -> plugin.getStorageManager().getOfflineUserData(owner, true).thenAccept(result -> result.ifPresentOrElse(data -> {
if (data.isLocked()) {

View File

@@ -2,10 +2,7 @@ package net.momirealms.customfishing.bukkit.command;
import net.kyori.adventure.util.Index;
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
import net.momirealms.customfishing.bukkit.command.feature.GetItemCommand;
import net.momirealms.customfishing.bukkit.command.feature.GiveItemCommand;
import net.momirealms.customfishing.bukkit.command.feature.ReloadCommand;
import net.momirealms.customfishing.bukkit.command.feature.SellFishCommand;
import net.momirealms.customfishing.bukkit.command.feature.*;
import net.momirealms.customfishing.common.command.AbstractCommandManager;
import net.momirealms.customfishing.common.command.CommandFeature;
import net.momirealms.customfishing.common.sender.Sender;
@@ -24,7 +21,12 @@ public class BukkitCommandManager extends AbstractCommandManager<CommandSender>
new ReloadCommand(this),
new SellFishCommand(this),
new GetItemCommand(this),
new GiveItemCommand(this)
new GiveItemCommand(this),
new EndCompetitionCommand(this),
new StopCompetitionCommand(this),
new StartCompetitionCommand(this),
new OpenMarketCommand(this),
new OpenBagCommand(this)
);
private final Index<String, CommandFeature<CommandSender>> INDEX = Index.create(CommandFeature::getFeatureID, FEATURES);

View File

@@ -0,0 +1,37 @@
package net.momirealms.customfishing.bukkit.command.feature;
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
import net.momirealms.customfishing.api.mechanic.competition.FishingCompetition;
import net.momirealms.customfishing.bukkit.command.BukkitCommandFeature;
import net.momirealms.customfishing.common.command.CustomFishingCommandManager;
import net.momirealms.customfishing.common.locale.MessageConstants;
import org.bukkit.command.CommandSender;
import org.incendo.cloud.Command;
import org.incendo.cloud.CommandManager;
public class EndCompetitionCommand extends BukkitCommandFeature<CommandSender> {
public EndCompetitionCommand(CustomFishingCommandManager<CommandSender> commandManager) {
super(commandManager);
}
@Override
public Command.Builder<? extends CommandSender> assembleCommand(CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
return builder
.flag(manager.flagBuilder("silent").withAliases("s").build())
.handler(context -> {
FishingCompetition competition = BukkitCustomFishingPlugin.getInstance().getCompetitionManager().getOnGoingCompetition();
if (competition == null) {
handleFeedback(context, MessageConstants.COMMAND_COMPETITION_FAILURE_NO_COMPETITION);
} else {
competition.end(true);
handleFeedback(context, MessageConstants.COMMAND_COMPETITION_END_SUCCESS);
}
});
}
@Override
public String getFeatureID() {
return "end_competition";
}
}

View File

@@ -69,6 +69,6 @@ public class GetItemCommand extends BukkitCommandFeature<CommandSender> {
@Override
public String getFeatureID() {
return "getitem";
return "get_item";
}
}

View File

@@ -72,6 +72,6 @@ public class GiveItemCommand extends BukkitCommandFeature<CommandSender> {
@Override
public String getFeatureID() {
return "giveitem";
return "give_item";
}
}

View File

@@ -0,0 +1,36 @@
package net.momirealms.customfishing.bukkit.command.feature;
import net.kyori.adventure.text.Component;
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
import net.momirealms.customfishing.bukkit.command.BukkitCommandFeature;
import net.momirealms.customfishing.common.command.CustomFishingCommandManager;
import net.momirealms.customfishing.common.locale.MessageConstants;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.incendo.cloud.Command;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.bukkit.parser.PlayerParser;
public class OpenBagCommand extends BukkitCommandFeature<CommandSender> {
public OpenBagCommand(CustomFishingCommandManager<CommandSender> commandManager) {
super(commandManager);
}
@Override
public Command.Builder<? extends CommandSender> assembleCommand(CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
return builder
.required("player", PlayerParser.playerParser())
.flag(manager.flagBuilder("silent").withAliases("s").build())
.handler(context -> {
final Player player = context.get("player");
BukkitCustomFishingPlugin.getInstance().getBagManager().openBag(player, player.getUniqueId());
handleFeedback(context, MessageConstants.COMMAND_BAG_OPEN_SUCCESS, Component.text(player.getName()));
});
}
@Override
public String getFeatureID() {
return "open_bag";
}
}

View File

@@ -0,0 +1,36 @@
package net.momirealms.customfishing.bukkit.command.feature;
import net.kyori.adventure.text.Component;
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
import net.momirealms.customfishing.bukkit.command.BukkitCommandFeature;
import net.momirealms.customfishing.common.command.CustomFishingCommandManager;
import net.momirealms.customfishing.common.locale.MessageConstants;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.incendo.cloud.Command;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.bukkit.parser.PlayerParser;
public class OpenMarketCommand extends BukkitCommandFeature<CommandSender> {
public OpenMarketCommand(CustomFishingCommandManager<CommandSender> commandManager) {
super(commandManager);
}
@Override
public Command.Builder<? extends CommandSender> assembleCommand(CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
return builder
.required("player", PlayerParser.playerParser())
.flag(manager.flagBuilder("silent").withAliases("s").build())
.handler(context -> {
final Player player = context.get("player");
BukkitCustomFishingPlugin.getInstance().getMarketManager().openMarketGUI(player);
handleFeedback(context, MessageConstants.COMMAND_MARKET_OPEN_SUCCESS, Component.text(player.getName()));
});
}
@Override
public String getFeatureID() {
return "open_market";
}
}

View File

@@ -0,0 +1,53 @@
package net.momirealms.customfishing.bukkit.command.feature;
import net.kyori.adventure.text.Component;
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
import net.momirealms.customfishing.api.mechanic.competition.FishingCompetition;
import net.momirealms.customfishing.bukkit.command.BukkitCommandFeature;
import net.momirealms.customfishing.common.command.CustomFishingCommandManager;
import net.momirealms.customfishing.common.locale.MessageConstants;
import org.bukkit.command.CommandSender;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.incendo.cloud.Command;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.context.CommandContext;
import org.incendo.cloud.context.CommandInput;
import org.incendo.cloud.parser.standard.StringParser;
import org.incendo.cloud.suggestion.Suggestion;
import org.incendo.cloud.suggestion.SuggestionProvider;
import java.util.concurrent.CompletableFuture;
public class StartCompetitionCommand extends BukkitCommandFeature<CommandSender> {
public StartCompetitionCommand(CustomFishingCommandManager<CommandSender> commandManager) {
super(commandManager);
}
@Override
public Command.Builder<? extends CommandSender> assembleCommand(CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
return builder
.required("id", StringParser.stringComponent().suggestionProvider(new SuggestionProvider<>() {
@Override
public @NonNull CompletableFuture<? extends @NonNull Iterable<? extends @NonNull Suggestion>> suggestionsFuture(@NonNull CommandContext<Object> context, @NonNull CommandInput input) {
return CompletableFuture.completedFuture(BukkitCustomFishingPlugin.getInstance().getCompetitionManager().getCompetitionIDs().stream().map(Suggestion::suggestion).toList());
}
}))
.optional("group", StringParser.stringParser())
.flag(manager.flagBuilder("silent").withAliases("s").build())
.handler(context -> {
String id = context.get("id");
String group = context.getOrDefault("group", null);
if (BukkitCustomFishingPlugin.getInstance().getCompetitionManager().startCompetition(id, true, group)) {
handleFeedback(context, MessageConstants.COMMAND_COMPETITION_START_SUCCESS);
} else {
handleFeedback(context, MessageConstants.COMMAND_COMPETITION_FAILURE_NOT_EXIST, Component.text(id));
}
});
}
@Override
public String getFeatureID() {
return "start_competition";
}
}

View File

@@ -0,0 +1,37 @@
package net.momirealms.customfishing.bukkit.command.feature;
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
import net.momirealms.customfishing.api.mechanic.competition.FishingCompetition;
import net.momirealms.customfishing.bukkit.command.BukkitCommandFeature;
import net.momirealms.customfishing.common.command.CustomFishingCommandManager;
import net.momirealms.customfishing.common.locale.MessageConstants;
import org.bukkit.command.CommandSender;
import org.incendo.cloud.Command;
import org.incendo.cloud.CommandManager;
public class StopCompetitionCommand extends BukkitCommandFeature<CommandSender> {
public StopCompetitionCommand(CustomFishingCommandManager<CommandSender> commandManager) {
super(commandManager);
}
@Override
public Command.Builder<? extends CommandSender> assembleCommand(CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
return builder
.flag(manager.flagBuilder("silent").withAliases("s").build())
.handler(context -> {
FishingCompetition competition = BukkitCustomFishingPlugin.getInstance().getCompetitionManager().getOnGoingCompetition();
if (competition == null) {
handleFeedback(context, MessageConstants.COMMAND_COMPETITION_FAILURE_NO_COMPETITION);
} else {
competition.stop(true);
handleFeedback(context, MessageConstants.COMMAND_COMPETITION_STOP_SUCCESS);
}
});
}
@Override
public String getFeatureID() {
return "stop_competition";
}
}

View File

@@ -44,6 +44,8 @@ import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import static java.util.Objects.requireNonNull;
public class BukkitCompetitionManager implements CompetitionManager {
private final BukkitCustomFishingPlugin plugin;
@@ -216,7 +218,6 @@ public class BukkitCompetitionManager implements CompetitionManager {
public boolean startCompetition(String competition, boolean force, String serverGroup) {
CompetitionConfig config = commandConfigMap.get(competition);
if (config == null) {
plugin.getPluginLogger().warn("Competition " + competition + " doesn't exist.");
return false;
}
return startCompetition(config, force, serverGroup);
@@ -291,4 +292,9 @@ public class BukkitCompetitionManager implements CompetitionManager {
public CompetitionConfig getCompetition(String key) {
return commandConfigMap.get(key);
}
@Override
public Collection<String> getCompetitionIDs() {
return commandConfigMap.keySet();
}
}

View File

@@ -67,10 +67,7 @@ public class Competition implements FishingCompetition {
if (ConfigManager.redisRanking()) this.rankingProvider = new RedisRankingProvider();
else this.rankingProvider = new LocalRankingProvider();
this.publicContext = Context.player(null, true);
this.publicContext.arg(
ContextKeys.GOAL,
goal
);
this.publicContext.arg(ContextKeys.GOAL, goal);
}
@Override

View File

@@ -29,6 +29,12 @@ import java.util.function.BiFunction;
public class BukkitConfigManager extends ConfigManager {
private static YamlDocument MAIN_CONFIG;
public static YamlDocument getMainConfig() {
return MAIN_CONFIG;
}
public BukkitConfigManager(BukkitCustomFishingPlugin plugin) {
super(plugin);
this.registerBuiltInItemProperties();
@@ -42,6 +48,7 @@ public class BukkitConfigManager extends ConfigManager {
@Override
public void load() {
this.loadConfigs();
MAIN_CONFIG = loadConfig("config.yml");
}
private void loadConfigs() {
@@ -114,6 +121,7 @@ public class BukkitConfigManager extends ConfigManager {
float size = (float) RandomUtils.generateRandomDouble(minSize, maxSize);
item.setTag(size, "CustomFishing", "size");
context.arg(ContextKeys.SIZE, size);
context.arg(ContextKeys.SIZE_FORMATTED, String.format("%.2f", size));
};
}, 1_000, "size");
this.registerItemParser(arg -> {
@@ -125,8 +133,9 @@ public class BukkitConfigManager extends ConfigManager {
double bonusPrice = bonus.evaluate(context);
float size = Optional.ofNullable(context.arg(ContextKeys.SIZE)).orElse(0f);
double price = basePrice + bonusPrice * size;
item.setTag(price, "CustomFishing", "price");
item.setTag(price, "Price");
context.arg(ContextKeys.PRICE, price);
context.arg(ContextKeys.PRICE_FORMATTED, String.format("%.2f", price));
};
}, 1_500, "price");
}

View File

@@ -59,11 +59,13 @@ public class BukkitIntegrationManager implements IntegrationManager {
this.load();
}
@Override
public void disable() {
this.enchantmentProviders.clear();
this.levelerProviders.clear();
}
@Override
public void load() {
if (isHooked("ItemsAdder")) {
registerItemProvider(new ItemsAdderItemProvider());

View File

@@ -33,12 +33,14 @@ import net.momirealms.customfishing.api.mechanic.misc.value.MathValue;
import net.momirealms.customfishing.api.mechanic.misc.value.TextValue;
import net.momirealms.customfishing.api.storage.data.EarningData;
import net.momirealms.customfishing.api.storage.user.UserData;
import net.momirealms.customfishing.bukkit.config.BukkitConfigManager;
import net.momirealms.customfishing.bukkit.item.BukkitItemFactory;
import net.momirealms.customfishing.common.item.Item;
import net.momirealms.customfishing.common.plugin.scheduler.SchedulerTask;
import net.momirealms.customfishing.common.util.Pair;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.ShulkerBox;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
@@ -47,6 +49,8 @@ import org.bukkit.event.inventory.*;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BlockStateMeta;
import org.bukkit.inventory.meta.BundleMeta;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
@@ -89,6 +93,9 @@ public class BukkitMarketManager implements MarketManager, Listener {
private SchedulerTask resetEarningsTask;
private int cachedDate;
private boolean allowBundle;
private boolean allowShulkerBox;
public BukkitMarketManager(BukkitCustomFishingPlugin plugin) {
this.plugin = plugin;
this.priceMap = new HashMap<>();
@@ -127,18 +134,16 @@ public class BukkitMarketManager implements MarketManager, Listener {
this.resetEarningsTask.cancel();
}
// Load configuration from the plugin's config file
private void loadConfig() {
YamlDocument config = plugin.getConfigManager().loadConfig("market.yml");
this.enable = config.getBoolean("enable", true);
this.formula = config.getString("price-formula", "{base} + {bonus} * {size}");
if (!this.enable) return;
Section config = BukkitConfigManager.getMainConfig().getSection("mechanics.market");
// Load various configuration settings
this.formula = config.getString("price-formula", "{base} + {bonus} * {size}");
this.layout = config.getStringList("layout").toArray(new String[0]);
this.title = TextValue.auto(config.getString("title", "market.title"));
this.itemSlot = config.getString("item-slot.symbol", "I").charAt(0);
this.allowItemWithNoPrice = config.getBoolean("item-slot.allow-items-with-no-price", true);
this.allowBundle = config.getBoolean("allow-bundle", true);
this.allowShulkerBox = config.getBoolean("allow-shulker-box", true);
Section sellAllSection = config.getSection("sell-all-icons");
if (sellAllSection != null) {
@@ -202,7 +207,7 @@ public class BukkitMarketManager implements MarketManager, Listener {
public void openMarketGUI(Player player) {
Optional<UserData> optionalUserData = plugin.getStorageManager().getOnlineUser(player.getUniqueId());
if (optionalUserData.isEmpty()) {
plugin.getPluginLogger().warn("Player " + player.getName() + "'s market data is not loaded yet.");
plugin.getPluginLogger().warn("Player " + player.getName() + "'s market data has not been loaded yet.");
return;
}
Context<Player> context = Context.player(player);
@@ -447,6 +452,18 @@ public class BukkitMarketManager implements MarketManager, Listener {
return price * itemStack.getAmount();
}
if (allowBundle && itemStack.getItemMeta() instanceof BundleMeta bundleMeta) {
Pair<Integer, Double> pair = getItemsToSell(context, bundleMeta.getItems());
return pair.right();
}
if (allowShulkerBox && itemStack.getItemMeta() instanceof BlockStateMeta stateMeta) {
if (stateMeta.getBlockState() instanceof ShulkerBox shulkerBox) {
Pair<Integer, Double> pair = getItemsToSell(context, Arrays.stream(shulkerBox.getInventory().getStorageContents()).filter(Objects::nonNull).toList());
return pair.right();
}
}
// If no custom price is defined, attempt to fetch the price from a predefined price map.
String itemID = itemStack.getType().name();
Optional<Integer> optionalCMD = wrapped.customModelData();
@@ -487,6 +504,19 @@ public class BukkitMarketManager implements MarketManager, Listener {
for (ItemStack itemStack : itemStacks) {
double price = getItemPrice(context, itemStack);
if (price > 0 && itemStack != null) {
if (allowBundle && itemStack.getItemMeta() instanceof BundleMeta bundleMeta) {
clearWorthyItems(context, bundleMeta.getItems());
itemStack.setItemMeta(bundleMeta);
continue;
}
if (allowShulkerBox && itemStack.getItemMeta() instanceof BlockStateMeta stateMeta) {
if (stateMeta.getBlockState() instanceof ShulkerBox shulkerBox) {
clearWorthyItems(context, Arrays.stream(shulkerBox.getInventory().getStorageContents()).filter(Objects::nonNull).toList());
stateMeta.setBlockState(shulkerBox);
itemStack.setItemMeta(stateMeta);
continue;
}
}
itemStack.setAmount(0);
}
}

View File

@@ -19,16 +19,51 @@ sellfish:
usage:
- /sellfish
getitem:
get_item:
enable: true
permission: customfishing.command.getitem
usage:
- /customfishing items get
- /cfishing items get
giveitem:
give_item:
enable: true
permission: customfishing.command.giveitem
usage:
- /customfishing items give
- /cfishing items give
- /cfishing items give
stop_competition:
enable: true
permission: customfishing.command.competition
usage:
- /customfishing competition stop
- /cfishing competition stop
end_competition:
enable: true
permission: customfishing.command.competition
usage:
- /customfishing competition end
- /cfishing competition end
start_competition:
enable: true
permission: customfishing.command.competition
usage:
- /customfishing competition start
- /cfishing competition start
open_market:
enable: true
permission: customfishing.command.open.market
usage:
- /customfishing open market
- /cfishing open market
open_bag:
enable: true
permission: customfishing.command.open.bag
usage:
- /customfishing open bag
- /cfishing open bag

View File

@@ -1,18 +1,13 @@
# Don"t change this
config-version: '${config_version}'
# Debug
debug: false
# BStats
metrics: true
# Check updates
update-checker: true
# Language
# https://github.com/Xiao-MoMi/Custom-Fishing/tree/main/plugin/src/main/resources/messages
lang: en
# Mechanic settings
mechanics:
# Specifies the conditions required for the plugin mechanics to work.
@@ -23,7 +18,6 @@ mechanics:
type: '!world'
value:
- blacklist_world
# Configures global effects. This is useful if you want to give all the players certain effects based on certain conditions
global-effects:
effect_1:
@@ -156,7 +150,6 @@ mechanics:
# Other whitelist-items
whitelist-items:
- fishing_rod
# Can fishing bag store fishing loots?
can-store-loot: false
# Requirements for automatically collecting
@@ -193,31 +186,178 @@ mechanics:
message_action:
type: message
value: "<#EEE8AA>[Fishing Bag]</#EEE8AA> Your fishing bag has been full."
# Fishing wait time
market:
# Market GUI title
title: '<gradient:#A52A2A:#800000:#A52A2A>Fish Market</gradient>'
# Whether to enable limitations
limitation:
enable: true
earnings: '10000' # You can use expressions here
# Market menu layout
layout:
- 'AAAAAAAAA'
- 'AIIIIIIIA'
- 'AIIIIIIIA'
- 'AIIIIIIIA'
- 'AAAABAAAA'
# Price formula (For CustomFishing loots)
price-formula: '{BASE} + {BONUS} * {SIZE}'
# Allow player to sell fish in bundles
allow-bundle: true
# Allow player to sell fish in shulker boxes
allow-shulker-box: true
# Item price (For vanilla items & other plugin items that have CustomModelData)
item-price:
# Vanilla Items
COD: 10
PUFFERFISH: 10
SALMON: 10
TROPICAL_FISH: 10
# PAPER (CustomModelData: 999)
PAPER:999: 5
# Slots to put items in
item-slot:
symbol: 'I'
allow-items-with-no-price: true
# This is an icon that allows players to sell all the fish from their inventory and fishingbag
# You can enable it by putting the symbol into layout
sell-all-icons:
symbol: 'S'
# Should the fish in fishing bag be sold
fishingbag: true
allow-icon:
material: IRON_BLOCK
display:
name: '<#00CED1><b>● <!b>Ship the fish'
lore:
- '<font:uniform><gradient:#E6E6FA:#48D1CC:#E6E6FA>You will get <green>{money_formatted} coins</green> from the fish in inventory and bag</gradient></font>'
action:
sound_action:
type: sound
value:
key: 'minecraft:block.amethyst_block.place'
source: 'player'
volume: 1
pitch: 1
message_action:
type: message
value: 'You earned {money_formatted} coins from the fish! You can get {rest_formatted} more coins from market today'
command_action:
type: command
value: 'money give {player} {money}'
# Requires Vault and any economy plugin
# money_action:
# type: give-money
# value: '{money}'
deny-icon:
material: REDSTONE_BLOCK
display:
name: '<red><b>● <!b>Denied trade'
lore:
- '<font:uniform><gradient:#E6E6FA:red:#E6E6FA>Nothing to sell!</gradient></font>'
action:
sound_action:
type: sound
value:
key: 'minecraft:entity.villager.no'
source: 'player'
volume: 1
pitch: 1
limit-icon:
material: REDSTONE_BLOCK
display:
name: '<red><b>● <!b>Denied trade'
lore:
- '<font:uniform><gradient:#E6E6FA:red:#E6E6FA>The worth of items exceeds the money that can be earned for the rest of today!</gradient></font>'
action:
sound_action:
type: sound
value:
key: 'minecraft:block.anvil.land'
source: 'player'
volume: 1
pitch: 1
# Sell icon
sell-icons:
symbol: 'B'
allow-icon:
material: IRON_BLOCK
display:
name: '<#00CED1><b>● <!b>Ship the fish'
lore:
- '<font:uniform><gradient:#E6E6FA:#48D1CC:#E6E6FA>You will get <green>{money_formatted} coins</green> from the fish</gradient></font>'
action:
sound_action:
type: sound
value:
key: 'minecraft:block.amethyst_block.place'
source: 'player'
volume: 1
pitch: 1
message_action:
type: message
value: 'You earned {money_formatted} coins from the fish! You can get {rest_formatted} more coins from market today'
command_action:
type: command
value: 'money give {player} {money}'
# Requires Vault and any economy plugin
# money_action:
# type: give-money
# value: '{money}'
deny-icon:
material: REDSTONE_BLOCK
display:
name: '<red><b>● <!b>Denied trade'
lore:
- '<font:uniform><gradient:#E6E6FA:red:#E6E6FA>Nothing to sell!</gradient></font>'
action:
sound_action:
type: sound
value:
key: 'minecraft:entity.villager.no'
source: 'player'
volume: 1
pitch: 1
limit-icon:
material: REDSTONE_BLOCK
display:
name: '<red><b>● <!b>Denied trade'
lore:
- '<font:uniform><gradient:#E6E6FA:red:#E6E6FA>The worth of items exceeds the money that can be earned for the rest of today!</gradient></font>'
action:
sound_action:
type: sound
value:
key: 'minecraft:block.anvil.land'
source: 'player'
volume: 1
pitch: 1
# Decorative icons
decorative-icons:
glass-pane:
symbol: 'A'
material: BLACK_STAINED_GLASS_PANE
display:
name: ' '
# This section would take effect if you set "override-vanilla" to true
# That also means vanilla mechanics for example lure enchantment
# would no longer take effect, so you have to configurate its effect
# in enchantment effects.
# would no longer take effect, so you have to configure its effect in CustomFishing
fishing-wait-time:
# override vanilla mechanic
override-vanilla: false
# ticks
min-wait-time: 100
max-wait-time: 600
# Lava fishing settings
# To modify vanilla fishing time, you should edit paper-world-defaults.yml where there's a section called fishing-time-range
lava-fishing:
# ticks
min-wait-time: 100
max-wait-time: 600
# Size settings
size:
# Some effects would increase/decrease size so the option decides whether they could ignore the limit
restricted-size-range: true
# Competition settings
competition:
# Use redis for cross server data synchronization
@@ -226,8 +366,7 @@ mechanics:
server-group: default
# Increase this value would allow you to use more placeholders like {4_player} {5_score} in sacrifice of some performance
placeholder-limit: 3
# If a player could get multiple loots from fishing, should the loots spawn at the same time or have delays for each (tick)
# If a player could get multiple loots from fishing, should the loots spawn at the same time or have delay for each (measured in ticks)
multiple-loot-spawn-delay: 4
# Other settings
@@ -235,7 +374,6 @@ other-settings:
# It's recommended to use MiniMessage format. If you insist on using legacy color code "&", enable the support below.
# Disable this would improve performance
legacy-color-code-support: true
# Thread pool settings
thread-pool-settings:
# The size of the core Thread pool, that is, the size of the Thread pool when there is no task to execute
@@ -245,21 +383,16 @@ other-settings:
maximumPoolSize: 10
# If a thread is idle for more than this attribute value, it will exit due to timeout
keepAliveTime: 30
# Event priority: MONITOR HIGHEST HIGH NORMAL LOW LOWEST
event-priority: NORMAL
# Save the data from cache to file periodically to minimize the data loss if server crashes
# -1 to disable
data-saving-interval: 600
# Log the consumption of time on data saving
log-data-saving: true
# Lock player's data if a player is playing on a server that connected to database
# If you can ensure low database link latency and fast processing, you can consider disabling this option to improve performance
lock-data: true
# Requires PlaceholderAPI to work
placeholder-register:
'{record}': '%fishingstats_size-record_{loot}%'
@@ -267,7 +400,6 @@ other-settings:
'{date}': '%server_time_yyyy-MM-dd-HH:mm:ss%'
# Requires player expansion
'{yaw}': '%player_yaw%'
# CustomFishing supports using items/blocks from other plugins
# If items share the same id, they would inherit the effects
# Check the wiki for examples
@@ -276,13 +408,11 @@ other-settings:
- vanilla
block-detection-order:
- vanilla
# Custom durability format
custom-durability-format:
- ''
- '<gray>Durability</gray><white>: {dur} <gray>/</gray> {max}</white>'
# Offset characters' unicodes
# Offset characters
# Never edit this unless you know what you are doing
offset-characters:
font: customfishing:offset_chars

View File

@@ -26,14 +26,14 @@ beginner_rod:
- '<gray> - novice angler''s best friend.'
- ''
- '<#FFD700>Effects:'
- '<gray> - Increase the hook time'
- '<gray> - Increase the waiting time'
- '<gray> - Reduces the challenge of fishing'
custom-model-data: 50001
max-durability: 64
effects:
effect_1:
type: wait-time-multiplier
value: 1.8
value: 1.5
effect_2:
type: difficulty
value: -8
@@ -117,8 +117,8 @@ bone_rod:
- '<gray> - regular rods.'
- ''
- '<#FFD700>Effects:'
- '<gray> - Fishing in lava'
- '<gray> - Sometimes skeleton would grab the hook'
- '<gray> - Fish in lava'
- '<gray> - Attract skeletons'
custom-model-data: 50005
max-durability: 32
effects:
@@ -140,7 +140,7 @@ magical_rod:
- ''
- '<#FFD700>Effects:'
- '<gray> - Get an enchantment book from fishing.'
- '<gray> - Require a long time to get hooked.'
- '<gray> - The waiting time is very long.'
- ''
- '<#CD5C5C>Requirements:'
- '<gray> - 1x book bait'
@@ -193,7 +193,7 @@ master_rod:
- '<gray> - time it takes for a fish to bite.'
- ''
- '<#FFD700>Effects:'
- '<gray> - Reduce the hook time'
- '<gray> - Reduce the waiting time'
- '<gray> - Increase the challenge of fishing'
- '<gray> - Higher chance of getting quality fish'
custom-model-data: 50007

View File

@@ -1,158 +0,0 @@
config-version: '${config_version}'
# Container title
title: '<gradient:#A52A2A:#800000:#A52A2A>Fish Market</gradient>'
limitation:
enable: true
# Support expression and placeholders
earnings: '10000'
# Market menu layout
layout:
- 'AAAAAAAAA'
- 'AIIIIIIIA'
- 'AIIIIIIIA'
- 'AIIIIIIIA'
- 'AAAABAAAA'
# Price formula (For CustomFishing loots)
price-formula: '{BASE} + {BONUS} * {SIZE}'
# Item price (For vanilla items & other plugin items that have CustomModelData)
item-price:
# Vanilla Items
COD: 10
PUFFERFISH: 10
SALMON: 10
TROPICAL_FISH: 10
# PAPER (CustomModelData: 999)
PAPER:999: 5
# Slots to put items in
item-slot:
symbol: 'I'
allow-items-with-no-price: true
# This is an icon that allows players to sell all the fish from their inventory and fishingbag
# You can enable it by putting the symbol into layout
sell-all-icons:
symbol: 'S'
# Should the fish in fishing bag be sold
fishingbag: true
allow-icon:
material: IRON_BLOCK
display:
name: '<#00CED1><b>● <!b>Ship the fish'
lore:
- '<font:uniform><gradient:#E6E6FA:#48D1CC:#E6E6FA>You will get <green>{money_formatted} coins</green> by selling the fish from inventory and bag</gradient></font>'
action:
sound_action:
type: sound
value:
key: 'minecraft:block.amethyst_block.place'
source: 'player'
volume: 1
pitch: 1
message_action:
type: message
value: 'You earned {money_formatted} coins by selling the fish! You can still get {rest_formatted} coins from market today'
command_action:
type: command
value: 'money give {player} {money}'
# Requires Vault and any economy plugin
# money_action:
# type: give-money
# value: '{money}'
deny-icon:
material: REDSTONE_BLOCK
display:
name: '<red><b>● <!b>Denied trade'
lore:
- '<font:uniform><gradient:#E6E6FA:red:#E6E6FA>Nothing to sell!</gradient></font>'
action:
sound_action:
type: sound
value:
key: 'minecraft:entity.villager.no'
source: 'player'
volume: 1
pitch: 1
limit-icon:
material: REDSTONE_BLOCK
display:
name: '<red><b>● <!b>Denied trade'
lore:
- '<font:uniform><gradient:#E6E6FA:red:#E6E6FA>The worth of items exceeds the money that can be earned for the rest of today!</gradient></font>'
action:
sound_action:
type: sound
value:
key: 'minecraft:block.anvil.land'
source: 'player'
volume: 1
pitch: 1
# Sell icon
sell-icons:
symbol: 'B'
allow-icon:
material: IRON_BLOCK
display:
name: '<#00CED1><b>● <!b>Ship the fish'
lore:
- '<font:uniform><gradient:#E6E6FA:#48D1CC:#E6E6FA>You will get <green>{money_formatted} coins</green> by selling the fish</gradient></font>'
action:
sound_action:
type: sound
value:
key: 'minecraft:block.amethyst_block.place'
source: 'player'
volume: 1
pitch: 1
message_action:
type: message
value: 'You earned {money_formatted} coins by selling the fish! You can still get {rest_formatted} coins from market today'
command_action:
type: command
value: 'money give {player} {money}'
# Requires Vault and any economy plugin
# money_action:
# type: give-money
# value: '{money}'
deny-icon:
material: REDSTONE_BLOCK
display:
name: '<red><b>● <!b>Denied trade'
lore:
- '<font:uniform><gradient:#E6E6FA:red:#E6E6FA>Nothing to sell!</gradient></font>'
action:
sound_action:
type: sound
value:
key: 'minecraft:entity.villager.no'
source: 'player'
volume: 1
pitch: 1
limit-icon:
material: REDSTONE_BLOCK
display:
name: '<red><b>● <!b>Denied trade'
lore:
- '<font:uniform><gradient:#E6E6FA:red:#E6E6FA>The worth of items exceeds the money that can be earned for the rest of today!</gradient></font>'
action:
sound_action:
type: sound
value:
key: 'minecraft:block.anvil.land'
source: 'player'
volume: 1
pitch: 1
# Decorative icons
decorative-icons:
glass-pane:
symbol: 'A'
material: BLACK_STAINED_GLASS_PANE
display:
name: ' '

View File

@@ -1,7 +1,43 @@
# Don"t change this
config-version: "31"
command.prefix: "<gradient:#0070B3:#A0EACF>[CustomFishing] </gradient>"
exception.invalid_syntax: "<red>Invalid syntax. Correct syntax: <white><arg:0></white></red>"
exception.invalid_argument: "<red>Invalid argument. Reason: <white><arg:0></white></red>"
exception.invalid_sender: "<red><arg:0> is not allowed to execute that command. Must be of type <arg:1></red>"
exception.unexpected: "<red>An internal error occurred while attempting to perform this command</red>"
exception.no_permission: "<red>I'm sorry, but you do not have permission to perform this command</red>"
exception.no_such_command: "Unknown command."
argument.entity.notfound.player: "<red><lang:argument.entity.notfound.player></red>"
argument.entity.notfound.entity: "<red><lang:argument.entity.notfound.entity></red>"
argument.parse.failure.time: "<red>'<arg:0>' is not a valid time format</red>"
argument.parse.failure.material: "<red>'<arg:0>' is not a valid material name</red>"
argument.parse.failure.enchantment: "<red>'<arg:0>' is not a valid enchantment</red>"
argument.parse.failure.offlineplayer: "<red>No player found for input '<arg:0>'</red>"
argument.parse.failure.player: "<red>No player found for input '<arg:0>'</red>"
argument.parse.failure.world: "<red>'<arg:0>' is not a valid Minecraft world</red>"
argument.parse.failure.location.invalid_format: "<red>'<arg:0>' is not a valid location. Required format is '<arg:1> <arg:2> <arg:3></red>"
argument.parse.failure.location.mixed_local_absolute: "<red>Cannot mix local and absolute coordinates. (either all coordinates use '^' or none do)</red>"
argument.parse.failure.namespacedkey.namespace: "<red>Invalid namespace '<arg:0>'. Must be [a-z0-9._-]</red>"
argument.parse.failure.namespacedkey.key: "<red>Invalid key '<arg:0>'. Must be [a-z0-9/._-]</red>"
argument.parse.failure.namespacedkey.need_namespace: "<red>Invalid input '<arg:0>', requires an explicit namespace</red>"
argument.parse.failure.boolean: "<red>Could not parse boolean from '<arg:0>'</red>"
argument.parse.failure.number: "<red>'<arg:0>' is not a valid number in the range <arg:1> to <arg:2></red>"
argument.parse.failure.char: "<red>'<arg:0>' is not a valid character</red>"
argument.parse.failure.string: "<red>'<arg:0>' is not a valid string of type <arg:1></red>"
argument.parse.failure.uuid: "<red>'<arg:0>' is not a valid UUID</red>"
argument.parse.failure.enum: "<red>'<arg:0>' is not one of the following: <arg:1></red>"
argument.parse.failure.regex: "<red>'<arg:0>' does not match '<arg:1>'</red>"
argument.parse.failure.flag.unknown: "<red>Unknown flag '<arg:0>'</red>"
argument.parse.failure.flag.duplicate_flag: "<red>Duplicate flag '<arg:0>'</red>"
argument.parse.failure.flag.no_flag_started: "<red>No flag started. Don't know what to do with '<arg:0>'</red>"
argument.parse.failure.flag.missing_argument: "<red>Missing argument for '<arg:0>'</red>"
argument.parse.failure.flag.no_permission: "<red>You don't have permission to use '<arg:0>'</red>"
argument.parse.failure.color: "<red>'<arg:0>' is not a valid color</red>"
argument.parse.failure.duration: "<red>'<arg:0>' is not a duration format</red>"
argument.parse.failure.aggregate.missing: "<red>Missing component '<arg:0>'</red>"
argument.parse.failure.aggregate.failure: "<red>Invalid component '<arg:0>': <arg:1></red>"
argument.parse.failure.either: "<red>Could not resolve <arg:1> or <arg:2> from '<arg:0>'</red>"
argument.parse.failure.namedtextcolor: "<red>'<arg:0>' is not a named text color</red>"
command.reload.success: "<white>Reloaded. Took <green><arg:0></green>ms.</white>"
command.item.failure.not_exist: "<red>Item [<arg:0>] not exists.</red>"
command.item.give.success: "<white>Successfully given <arg:0> <arg:1>x <arg:2>.</white>"
@@ -13,6 +49,7 @@ command.competition.failure.not_exist: "<red>Competition <arg:0> does not exist.
command.competition.failure.no_competition: "<red>There's no competition ongoing.</red>"
command.competition.stop.success: "<white>Stopped the current competition.</white>"
command.competition.end.success: "<white>Ended the current competition.</white>"
command.competition.start.success: "<white>Started the competition.</white>"
command.bag.edit.failure.unsafe: "<red>Cannot edit a player's fishing bag if they're active on another linked server.</red>"
command.bag.edit.failure.never_played: "<red>The player hasn't joined the server before. Can't modify a nonexistent player's fishing bag.</red>"
command.bag.open.success: "<white>Successfully opened the fishing bag for <arg:0></white>"