9
0
mirror of https://github.com/Xiao-MoMi/Custom-Fishing.git synced 2026-01-06 15:51:50 +00:00
This commit is contained in:
XiaoMoMi
2023-09-20 05:16:24 +08:00
parent a0bb0e4726
commit 524203c617
27 changed files with 711 additions and 234 deletions

View File

@@ -37,6 +37,7 @@ import net.momirealms.customfishing.mechanic.effect.EffectManagerImpl;
import net.momirealms.customfishing.mechanic.entity.EntityManagerImpl;
import net.momirealms.customfishing.mechanic.fishing.FishingManagerImpl;
import net.momirealms.customfishing.mechanic.game.GameManagerImpl;
import net.momirealms.customfishing.mechanic.hook.HookManagerImpl;
import net.momirealms.customfishing.mechanic.item.ItemManagerImpl;
import net.momirealms.customfishing.mechanic.loot.LootManagerImpl;
import net.momirealms.customfishing.mechanic.market.MarketManagerImpl;
@@ -100,6 +101,7 @@ public class CustomFishingPluginImpl extends CustomFishingPlugin {
this.statisticsManager = new StatisticsManagerImpl(this);
this.coolDownManager = new CoolDownManager(this);
this.totemManager = new TotemManagerImpl(this);
this.hookManager = new HookManagerImpl(this);
this.reload();
if (CFConfig.updateChecker)
this.versionManager.checkUpdate().thenAccept(result -> {
@@ -129,6 +131,7 @@ public class CustomFishingPluginImpl extends CustomFishingPlugin {
((StatisticsManagerImpl) this.statisticsManager).disable();
((ActionManagerImpl) this.actionManager).disable();
((TotemManagerImpl) this.totemManager).disable();
((HookManagerImpl) this.hookManager).disable();
this.coolDownManager.disable();
this.commandManager.unload();
HandlerList.unregisterAll(this);
@@ -170,6 +173,8 @@ public class CustomFishingPluginImpl extends CustomFishingPlugin {
((StatisticsManagerImpl) this.statisticsManager).load();
((PlaceholderManagerImpl) this.placeholderManager).unload();
((PlaceholderManagerImpl) this.placeholderManager).load();
((HookManagerImpl) this.hookManager).unload();
((HookManagerImpl) this.hookManager).load();
this.commandManager.unload();
this.commandManager.load();
this.coolDownManager.unload();
@@ -177,24 +182,24 @@ public class CustomFishingPluginImpl extends CustomFishingPlugin {
}
private void loadDependencies() {
String libRepo = TimeZone.getDefault().getID().startsWith("Asia") ?
String mavenRepo = TimeZone.getDefault().getID().startsWith("Asia") ?
"https://maven.aliyun.com/repository/public/" : "https://repo.maven.apache.org/maven2/";
LibraryLoader.loadDependencies(
"org.apache.commons:commons-pool2:2.11.1", libRepo,
"redis.clients:jedis:4.4.2", libRepo,
"dev.dejvokep:boosted-yaml:1.3.1", libRepo,
"com.zaxxer:HikariCP:5.0.1", libRepo,
"net.objecthunter:exp4j:0.4.8", libRepo,
"org.mariadb.jdbc:mariadb-java-client:3.1.4", libRepo,
"mysql:mysql-connector-java:8.0.30", libRepo,
"commons-io:commons-io:2.13.0", libRepo,
"com.google.code.gson:gson:2.10.1", libRepo,
"com.h2database:h2:2.2.220", libRepo,
"org.mongodb:mongodb-driver-sync:4.10.2", libRepo,
"org.mongodb:mongodb-driver-core:4.10.2", libRepo,
"org.mongodb:bson:4.10.2", libRepo,
"org.xerial:sqlite-jdbc:3.42.0.0", libRepo,
"dev.jorel:commandapi-bukkit-shade:9.1.0", libRepo
"org.apache.commons:commons-pool2:2.11.1", mavenRepo,
"redis.clients:jedis:5.0.0", mavenRepo,
"dev.dejvokep:boosted-yaml:1.3.1", mavenRepo,
"com.zaxxer:HikariCP:5.0.1", mavenRepo,
"net.objecthunter:exp4j:0.4.8", mavenRepo,
"org.mariadb.jdbc:mariadb-java-client:3.2.0", mavenRepo,
"mysql:mysql-connector-java:8.0.30", mavenRepo,
"commons-io:commons-io:2.13.0", mavenRepo,
"com.google.code.gson:gson:2.10.1", mavenRepo,
"com.h2database:h2:2.2.220", mavenRepo,
"org.mongodb:mongodb-driver-sync:4.10.2", mavenRepo,
"org.mongodb:mongodb-driver-core:4.10.2", mavenRepo,
"org.mongodb:bson:4.10.2", mavenRepo,
"org.xerial:sqlite-jdbc:3.42.0.0", mavenRepo,
"dev.jorel:commandapi-bukkit-shade:9.1.0", mavenRepo
);
}

View File

@@ -27,8 +27,8 @@ import net.momirealms.customfishing.api.CustomFishingPlugin;
import net.momirealms.customfishing.api.common.Key;
import net.momirealms.customfishing.api.mechanic.condition.Condition;
import net.momirealms.customfishing.api.mechanic.item.BuildableItem;
import net.momirealms.customfishing.mechanic.item.ItemManagerImpl;
import net.momirealms.customfishing.setting.CFLocale;
import net.momirealms.customfishing.util.ItemUtils;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
@@ -48,7 +48,8 @@ public class ItemCommand {
getSubCommand("item"),
getSubCommand("util"),
getSubCommand("bait"),
getSubCommand("rod")
getSubCommand("rod"),
getSubCommand("hook")
);
}
@@ -80,7 +81,7 @@ public class ItemCommand {
int amount = (int) args.getOrDefault("amount", 1);
ItemStack item = CustomFishingPlugin.get().getItemManager().build(player, namespace, id, new Condition(player).getArgs());
if (item != null) {
int actual = ItemManagerImpl.giveCertainAmountOfItem(player, item, amount);
int actual = ItemUtils.giveCertainAmountOfItem(player, item, amount);
AdventureManagerImpl.getInstance().sendMessageWithPrefix(player, CFLocale.MSG_Get_Item.replace("{item}", id).replace("{amount}", String.valueOf(actual)));
} else {
AdventureManagerImpl.getInstance().sendMessageWithPrefix(player, CFLocale.MSG_Item_Not_Exists);
@@ -106,7 +107,7 @@ public class ItemCommand {
assert players != null;
for (Player player : players) {
ItemStack item = CustomFishingPlugin.get().getItemManager().build(player, namespace, id, new Condition(player).getArgs());
int actual = ItemManagerImpl.giveCertainAmountOfItem(player, item, amount);
int actual = ItemUtils.giveCertainAmountOfItem(player, item, amount);
AdventureManagerImpl.getInstance().sendMessageWithPrefix(sender, CFLocale.MSG_Give_Item.replace("{item}", id).replace("{amount}", String.valueOf(actual)).replace("{player}", player.getName()));
}
} else {

View File

@@ -88,7 +88,7 @@ public final class LibraryLoader {
}
public static void load(Dependency d) {
LogUtils.info(String.format("Loading dependency %s:%s:%s from %s", d.groupId, d.artifactId, d.version, d.repoUrl));
LogUtils.info(String.format("Loading dependency %s:%s:%s", d.groupId, d.artifactId, d.version));
String name = d.artifactId() + "-" + d.version();
File saveLocation = new File(getLibFolder(d), name + ".jar");
if (!saveLocation.exists()) {

View File

@@ -34,7 +34,6 @@ import net.momirealms.customfishing.api.mechanic.requirement.Requirement;
import net.momirealms.customfishing.api.util.LogUtils;
import net.momirealms.customfishing.compatibility.VaultHook;
import net.momirealms.customfishing.compatibility.papi.PlaceholderManagerImpl;
import net.momirealms.customfishing.mechanic.item.ItemManagerImpl;
import net.momirealms.customfishing.setting.CFLocale;
import net.momirealms.customfishing.util.*;
import org.bukkit.Bukkit;
@@ -463,9 +462,9 @@ public class ActionManagerImpl implements ActionManager {
Player player = condition.getPlayer();
ItemStack itemStack = player.getInventory().getItem(slot);
if (amount > 0) {
ItemUtils.addDurability(itemStack, amount);
ItemUtils.addDurability(itemStack, amount, true);
} else {
ItemUtils.loseDurability(itemStack, -amount);
ItemUtils.loseDurability(itemStack, -amount, true);
}
};
} else {
@@ -483,7 +482,7 @@ public class ActionManagerImpl implements ActionManager {
return condition -> {
if (Math.random() > chance) return;
Player player = condition.getPlayer();
ItemManagerImpl.giveCertainAmountOfItem(player, CustomFishingPlugin.get().getItemManager().buildAnyItemByID(player, id), amount);
ItemUtils.giveCertainAmountOfItem(player, CustomFishingPlugin.get().getItemManager().buildAnyItemByID(player, id), amount);
};
} else {
LogUtils.warn("Illegal value format found at action: give-item");

View File

@@ -134,7 +134,6 @@ public class BlockManagerImpl implements BlockManager, Listener {
public void load() {
this.loadConfig();
Bukkit.getPluginManager().registerEvents(this, plugin);
LogUtils.info("Loaded " + blockConfigMap.size() + " blocks.");
}
private void registerInbuiltProperties() {

View File

@@ -64,7 +64,6 @@ public class CompetitionManagerImpl implements CompetitionManager {
1,
TimeUnit.SECONDS
);
LogUtils.info("Loaded " + commandConfigMap.size() + " competitions.");
}
public void unload() {

View File

@@ -72,7 +72,7 @@ public class EffectManagerImpl implements EffectManager {
@SuppressWarnings("DuplicatedCode")
public void load() {
Deque<File> fileDeque = new ArrayDeque<>();
for (String type : List.of("rod", "bait", "enchant", "util", "totem")) {
for (String type : List.of("rod", "bait", "enchant", "util", "totem", "hook")) {
File typeFolder = new File(plugin.getDataFolder() + File.separator + "contents" + File.separator + type);
if (!typeFolder.exists()) {
if (!typeFolder.mkdirs()) return;

View File

@@ -48,7 +48,6 @@ public class EntityManagerImpl implements EntityManager {
public void load() {
this.loadConfig();
LogUtils.info("Loaded " + entityConfigMap.size() + " entities.");
}
public void unload() {

View File

@@ -229,7 +229,7 @@ public class FishingManagerImpl implements Listener, FishingManager {
if (compound != null && compound.hasTag("max_dur")) {
event.setCancelled(true);
hook.remove();
ItemUtils.loseDurability(itemStack, 2);
ItemUtils.loseDurability(itemStack, 2, true);
}
}
}
@@ -330,7 +330,7 @@ public class FishingManagerImpl implements Listener, FishingManager {
if (nbtCompound != null && nbtCompound.hasTag("max_dur")) {
event.getHook().remove();
event.setCancelled(true);
ItemUtils.loseDurability(itemStack, 5);
ItemUtils.loseDurability(itemStack, 5, true);
}
}
}
@@ -479,7 +479,8 @@ public class FishingManagerImpl implements Listener, FishingManager {
if (damageEvent.isCancelled()) {
break outer;
}
ItemUtils.loseDurability(rod, 1);
ItemUtils.reduceHookDurability(rod, false);
ItemUtils.loseDurability(rod, 1, true);
}
fishHook.remove();
@@ -518,6 +519,8 @@ public class FishingManagerImpl implements Listener, FishingManager {
GlobalSettings.triggerLootActions(ActionTrigger.FAILURE, fishingPreparation);
loot.triggerActions(ActionTrigger.FAILURE, fishingPreparation);
fishingPreparation.triggerActions(ActionTrigger.FAILURE);
ItemUtils.reduceHookDurability(fishingPreparation.getRodItemStack(), true);
}
public void success(TempFishingState state, FishHook hook) {
@@ -687,6 +690,17 @@ public class FishingManagerImpl implements Listener, FishingManager {
}
}
@Override
public boolean hasPlayerCastHook(UUID uuid) {
FishHook fishHook = hookCacheMap.get(uuid);
if (fishHook == null) return false;
if (!fishHook.isValid()) {
hookCacheMap.remove(uuid);
return false;
}
return true;
}
@Override
public void setTempFishingState(Player player, TempFishingState tempFishingState) {
tempFishingStateMap.put(player.getUniqueId(), tempFishingState);

View File

@@ -161,6 +161,9 @@ public class HookCheckTimerTask implements Runnable {
this.loot = nextLoot;
fishingPreparation.insertArg("{nick}", nextLoot.getNick());
fishingPreparation.insertArg("{loot}", nextLoot.getID());
fishingPreparation.insertArg("{x}", String.valueOf(fishHook.getLocation().getBlockX()));
fishingPreparation.insertArg("{y}", String.valueOf(fishHook.getLocation().getBlockY()));
fishingPreparation.insertArg("{z}", String.valueOf(fishHook.getLocation().getBlockZ()));
CustomFishingPlugin.get().getScheduler().runTaskAsync(() -> manager.setTempFishingState(fishingPreparation.getPlayer(), new TempFishingState(
initialEffect,
fishingPreparation,

View File

@@ -162,7 +162,7 @@ public class GameManagerImpl implements GameManager {
var totalWidth = chances.size() * widthPerSection - 1;
var pointerOffset = section.getInt("arguments.pointer-offset");
var pointerWidth = section.getInt("arguments.pointer-width");
var title = section.getString("title");
var title = section.getStringList("title");
var font = section.getString("subtitle.font");
var barImage = section.getString("subtitle.bar");
var pointerImage = section.getString("subtitle.pointer");
@@ -171,6 +171,7 @@ public class GameManagerImpl implements GameManager {
private int progress;
private boolean face;
private String sendTitle = title.get(ThreadLocalRandom.current().nextInt(title.size()));
@Override
public void arrangeTask() {
@@ -203,7 +204,7 @@ public class GameManagerImpl implements GameManager {
+ OffsetUtils.getOffsetChars(pointerOffset + progress)
+ FontUtils.surroundWithFont(pointerImage, font)
+ OffsetUtils.getOffsetChars(totalWidth - progress - pointerWidth);
AdventureManagerImpl.getInstance().sendTitle(player, title, bar,0,500,0);
AdventureManagerImpl.getInstance().sendTitle(player, sendTitle, bar,0,500,0);
}
@Override

View File

@@ -0,0 +1,195 @@
/*
* 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.hook;
import de.tr7zw.changeme.nbtapi.NBTCompound;
import de.tr7zw.changeme.nbtapi.NBTItem;
import net.momirealms.customfishing.api.CustomFishingPlugin;
import net.momirealms.customfishing.api.manager.HookManager;
import net.momirealms.customfishing.api.manager.RequirementManager;
import net.momirealms.customfishing.api.mechanic.condition.Condition;
import net.momirealms.customfishing.api.mechanic.effect.EffectCarrier;
import net.momirealms.customfishing.api.mechanic.hook.HookSetting;
import net.momirealms.customfishing.util.ItemUtils;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.*;
public class HookManagerImpl implements Listener, HookManager {
private final CustomFishingPlugin plugin;
private final HashMap<String, HookSetting> hookSettingMap;
public HookManagerImpl(CustomFishingPlugin plugin) {
this.plugin = plugin;
this.hookSettingMap = new HashMap<>();
}
public void load() {
Bukkit.getPluginManager().registerEvents(this, plugin);
loadConfig();
}
public void unload() {
HandlerList.unregisterAll(this);
hookSettingMap.clear();
}
public void disable() {
unload();
}
@SuppressWarnings("DuplicatedCode")
private void loadConfig() {
Deque<File> fileDeque = new ArrayDeque<>();
for (String type : List.of("hook")) {
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);
for (Map.Entry<String, Object> entry : config.getValues(false).entrySet()) {
if (entry.getValue() instanceof ConfigurationSection section) {
var setting = new HookSetting.Builder(entry.getKey())
.durability(section.getInt("max-durability", 16))
.lore(section.getStringList("lore-on-rod").stream().map(it -> "<!i>" + it).toList())
.build();
hookSettingMap.put(entry.getKey(), setting);
}
}
}
@Nullable
@Override
public HookSetting getHookSetting(String id) {
return hookSettingMap.get(id);
}
@EventHandler
public void onDragDrop(InventoryClickEvent event) {
if (event.isCancelled())
return;
final Player player = (Player) event.getWhoClicked();
if (event.getClickedInventory() != player.getInventory())
return;
ItemStack clicked = event.getCurrentItem();
if (clicked == null || clicked.getType() != Material.FISHING_ROD)
return;
if (player.getGameMode() != GameMode.SURVIVAL)
return;
ItemStack cursor = event.getCursor();
if (cursor == null || cursor.getType() == Material.AIR) {
if (event.getClick() == ClickType.RIGHT) {
if (plugin.getFishingManager().hasPlayerCastHook(player.getUniqueId())) {
return;
}
NBTItem nbtItem = new NBTItem(clicked);
NBTCompound cfCompound = nbtItem.getCompound("CustomFishing");
if (cfCompound == null)
return;
if (cfCompound.hasTag("hook_id")) {
event.setCancelled(true);
ItemStack hook = cfCompound.getItemStack("hook_item");
ItemUtils.setDurability(hook, cfCompound.getInteger("hook_dur"), true);
cfCompound.removeKey("hook_id");
cfCompound.removeKey("hook_item");
cfCompound.removeKey("hook_dur");
event.setCursor(hook);
ItemUtils.updateNBTItemLore(nbtItem);
clicked.setItemMeta(nbtItem.getItem().getItemMeta());
}
}
return;
}
String hookID = plugin.getItemManager().getAnyItemID(cursor);
HookSetting setting = getHookSetting(hookID);
if (setting == null)
return;
Condition condition = new Condition(player, new HashMap<>());
condition.insertArg("{rod}", plugin.getItemManager().getAnyItemID(clicked));
EffectCarrier effectCarrier = plugin.getEffectManager().getEffect("hook", hookID);
if (effectCarrier != null) {
if (!RequirementManager.isRequirementsMet(effectCarrier.getRequirements(), condition)) {
return;
}
}
event.setCancelled(true);
NBTItem rodNBTItem = new NBTItem(clicked);
NBTCompound cfCompound = rodNBTItem.getOrCreateCompound("CustomFishing");
String previousHookID = cfCompound.getString("hook_id");
ItemStack clonedHook = cursor.clone();
clonedHook.setAmount(1);
cursor.setAmount(cursor.getAmount() - 1);
if (previousHookID != null && !previousHookID.equals("")) {
int previousHookDurability = cfCompound.getInteger("hook_dur");
ItemStack previousItemStack = cfCompound.getItemStack("hook_item");
ItemUtils.setDurability(previousItemStack, previousHookDurability, true);
if (cursor.getAmount() == 0) {
event.setCursor(previousItemStack);
} else {
ItemUtils.giveCertainAmountOfItem(player, previousItemStack, 1);
}
}
cfCompound.setString("hook_id", hookID);
cfCompound.setItemStack("hook_item", clonedHook);
cfCompound.setInteger("hook_dur", ItemUtils.getDurability(clonedHook));
ItemUtils.updateNBTItemLore(rodNBTItem);
clicked.setItemMeta(rodNBTItem.getItem().getItemMeta());
}
}

View File

@@ -60,9 +60,7 @@ import org.bukkit.event.player.PlayerItemConsumeEvent;
import org.bukkit.event.player.PlayerItemMendEvent;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -89,7 +87,6 @@ public class ItemManagerImpl implements ItemManager, Listener {
public void load() {
this.loadItemsFromPluginFolder();
LogUtils.info("Loaded " + buildableItemMap.size() + " items.");
Bukkit.getPluginManager().registerEvents(this, plugin);
}
@@ -117,7 +114,7 @@ public class ItemManagerImpl implements ItemManager, Listener {
@SuppressWarnings("DuplicatedCode")
public void loadItemsFromPluginFolder() {
Deque<File> fileDeque = new ArrayDeque<>();
for (String type : List.of("item", "bait", "rod", "util")) {
for (String type : List.of("item", "bait", "rod", "util", "hook")) {
File typeFolder = new File(plugin.getDataFolder() + File.separator + "contents" + File.separator + type);
if (!typeFolder.exists()) {
if (!typeFolder.mkdirs()) return;
@@ -216,6 +213,13 @@ public class ItemManagerImpl implements ItemManager, Listener {
}
}
@Override
public boolean isCustomFishingItem(ItemStack itemStack) {
if (itemStack == null || itemStack.getType() == Material.AIR) return false;
NBTItem nbtItem = new NBTItem(itemStack);
return nbtItem.hasTag("CustomFishing");
}
@Nullable
@Override
public String getItemID(ItemStack itemStack) {
@@ -269,6 +273,7 @@ public class ItemManagerImpl implements ItemManager, Listener {
for (ItemBuilder.ItemPropertyEditor editor : builder.getEditors()) {
editor.edit(player, nbtItem, placeholders);
}
ItemUtils.updateNBTItemLore(nbtItem);
return nbtItem.getItem();
}
@@ -631,70 +636,6 @@ public class ItemManagerImpl implements ItemManager, Listener {
}
}
public static int giveCertainAmountOfItem(Player player, ItemStack itemStack, int amount) {
PlayerInventory inventory = player.getInventory();
ItemMeta meta = itemStack.getItemMeta();
int maxStackSize = itemStack.getMaxStackSize();
if (amount > maxStackSize * 100) {
LogUtils.warn("Detected too many items spawning. Lowering the amount to " + (maxStackSize * 100));
amount = maxStackSize * 100;
}
int actualAmount = amount;
for (ItemStack other : inventory.getStorageContents()) {
if (other != null) {
if (other.getType() == itemStack.getType() && other.getItemMeta().equals(meta)) {
if (other.getAmount() < maxStackSize) {
int delta = maxStackSize - other.getAmount();
if (amount > delta) {
other.setAmount(maxStackSize);
amount -= delta;
} else {
other.setAmount(amount + other.getAmount());
return actualAmount;
}
}
}
}
}
if (amount > 0) {
for (ItemStack other : inventory.getStorageContents()) {
if (other == null) {
if (amount > maxStackSize) {
amount -= maxStackSize;
ItemStack cloned = itemStack.clone();
cloned.setAmount(maxStackSize);
inventory.addItem(cloned);
} else {
ItemStack cloned = itemStack.clone();
cloned.setAmount(amount);
inventory.addItem(cloned);
return actualAmount;
}
}
}
}
if (amount > 0) {
for (int i = 0; i < amount / maxStackSize; i++) {
ItemStack cloned = itemStack.clone();
cloned.setAmount(maxStackSize);
player.getWorld().dropItem(player.getLocation(), cloned);
}
int left = amount % maxStackSize;
if (left != 0) {
ItemStack cloned = itemStack.clone();
cloned.setAmount(left);
player.getWorld().dropItem(player.getLocation(), cloned);
}
}
return actualAmount;
}
@EventHandler
public void onPickUp(PlayerAttemptPickupItemEvent event) {
if (event.isCancelled()) return;
@@ -756,7 +697,7 @@ public class ItemManagerImpl implements ItemManager, Listener {
NBTCompound compound = nbtItem.getCompound("CustomFishing");
if (compound == null) return;
event.setCancelled(true);
ItemUtils.addDurability(itemStack, event.getRepairAmount());
ItemUtils.addDurability(itemStack, event.getRepairAmount(), true);
}
@EventHandler
@@ -782,11 +723,4 @@ public class ItemManagerImpl implements ItemManager, Listener {
action.trigger(condition);
}
}
@Override
public boolean isCustomFishingItem(ItemStack itemStack) {
if (itemStack == null || itemStack.getType() == Material.AIR) return false;
NBTItem nbtItem = new NBTItem(itemStack);
return nbtItem.hasTag("CustomFishing");
}
}

View File

@@ -22,7 +22,7 @@ import net.momirealms.customfishing.api.data.EarningData;
import net.momirealms.customfishing.api.mechanic.market.MarketGUIHolder;
import net.momirealms.customfishing.api.util.InventoryUtils;
import net.momirealms.customfishing.api.util.LogUtils;
import net.momirealms.customfishing.mechanic.item.ItemManagerImpl;
import net.momirealms.customfishing.util.ItemUtils;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
@@ -197,7 +197,7 @@ public class MarketGUI {
for (int slot : itemElement.getSlots()) {
ItemStack itemStack = inventory.getItem(slot);
if (itemStack != null && itemStack.getType() != Material.AIR) {
ItemManagerImpl.giveCertainAmountOfItem(owner, itemStack, itemStack.getAmount());
ItemUtils.giveCertainAmountOfItem(owner, itemStack, itemStack.getAmount());
inventory.setItem(slot, new ItemStack(Material.AIR));
}
}

View File

@@ -145,6 +145,8 @@ public class RequirementManagerImpl implements RequirementManager {
this.registerRegexRequirement();
this.registerItemInHandRequirement();
this.registerMoneyRequirement();
this.registerInBagRequirement();
this.registerHookRequirement();
}
public ConditionalElement getConditionalElements(ConfigurationSection section) {
@@ -950,6 +952,40 @@ public class RequirementManagerImpl implements RequirementManager {
});
}
private void registerHookRequirement() {
registerRequirement("hook", (args, actions, advanced) -> {
List<String> hooks = ConfigUtils.stringListArgs(args);
return condition -> {
String id = condition.getArg("{hook}");
if (hooks.contains(id)) return true;
if (advanced) triggerActions(actions, condition);
return false;
};
});
registerRequirement("!hook", (args, actions, advanced) -> {
List<String> hooks = ConfigUtils.stringListArgs(args);
return condition -> {
String id = condition.getArg("{hook}");
if (!hooks.contains(id)) return true;
if (advanced) triggerActions(actions, condition);
return false;
};
});
}
private void registerInBagRequirement() {
registerRequirement("in-fishingbag", (args, actions, advanced) -> {
boolean arg = (boolean) args;
return condition -> {
String inBag = condition.getArg("{in-bag}");
if (inBag == null && !arg) return true;
if (inBag != null && inBag.equals(String.valueOf(arg))) return true;
if (advanced) triggerActions(actions, condition);
return false;
};
});
}
private void registerPluginLevelRequirement() {
registerRequirement("plugin-level", (args, actions, advanced) -> {
if (args instanceof ConfigurationSection section) {

View File

@@ -21,7 +21,6 @@ import net.momirealms.customfishing.api.CustomFishingPlugin;
import net.momirealms.customfishing.api.data.user.OnlineUser;
import net.momirealms.customfishing.api.manager.StatisticsManager;
import net.momirealms.customfishing.api.mechanic.statistic.Statistics;
import net.momirealms.customfishing.api.util.LogUtils;
import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.Nullable;
@@ -40,7 +39,6 @@ public class StatisticsManagerImpl implements StatisticsManager {
public void load() {
this.loadCategoriesFromPluginFolder();
LogUtils.info("Loaded " + categoryMap.size() + " categories.");
}
public void unload() {

View File

@@ -40,7 +40,7 @@ import java.util.Objects;
public class CFConfig {
// config version
public static String configVersion = "26";
public static String configVersion = "27";
// language
public static String language;
@@ -89,6 +89,8 @@ public class CFConfig {
// Legacy color code support
public static boolean legacyColorSupport;
// Durability lore
public static List<String> durabilityLore;
public static void load() {
try {
@@ -147,6 +149,8 @@ public class CFConfig {
lockData = config.getBoolean("other-settings.lock-data", true);
legacyColorSupport = config.getBoolean("other-settings.legacy-color-code-support", false);
durabilityLore = config.getStringList("other-settings.custom-durability-format").stream().map(it -> "<!i>" + it).toList();
OffsetUtils.loadConfig(config.getConfigurationSection("other-settings.offset-characters"));
}
}

View File

@@ -19,66 +19,254 @@ package net.momirealms.customfishing.util;
import de.tr7zw.changeme.nbtapi.NBTCompound;
import de.tr7zw.changeme.nbtapi.NBTItem;
import de.tr7zw.changeme.nbtapi.NBTList;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.ScoreComponent;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import net.momirealms.customfishing.adventure.AdventureManagerImpl;
import net.momirealms.customfishing.api.CustomFishingPlugin;
import net.momirealms.customfishing.api.mechanic.hook.HookSetting;
import net.momirealms.customfishing.api.util.LogUtils;
import net.momirealms.customfishing.setting.CFConfig;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta;
public class ItemUtils {
public static void loseDurability(ItemStack itemStack, int amount) {
if (itemStack.getItemMeta() instanceof Damageable damageable) {
if (damageable.isUnbreakable()) {
return;
}
int unBreakingLevel = itemStack.getEnchantmentLevel(Enchantment.DURABILITY);
if (Math.random() > (double) 1 / (unBreakingLevel + 1)) {
return;
}
public static NBTItem updateNBTItemLore(NBTItem nbtItem) {
NBTCompound cfCompound = nbtItem.getCompound("CustomFishing");
if (cfCompound == null)
return nbtItem;
NBTItem nbtItem = new NBTItem(itemStack);
NBTCompound cfCompound = nbtItem.getCompound("CustomFishing");
if (cfCompound != null && cfCompound.hasTag("max_dur")) {
int max = cfCompound.getInteger("max_dur");
int current = cfCompound.getInteger("cur_dur") - amount;
cfCompound.setInteger("cur_dur", current);
int damage = (int) (itemStack.getType().getMaxDurability() * (1 - ((double) current / max)));
nbtItem.setInteger("Damage", damage);
if (current > 0) {
itemStack.setItemMeta(nbtItem.getItem().getItemMeta());
} else {
itemStack.setAmount(0);
}
boolean hasLoreUpdate = cfCompound.hasTag("hook_id") || cfCompound.hasTag("max_dur");
if (!hasLoreUpdate) return nbtItem;
NBTCompound displayCompound = nbtItem.getOrCreateCompound("display");
NBTList<String> lore = displayCompound.getStringList("Lore");
lore.removeIf(it -> GsonComponentSerializer.gson().deserialize(it) instanceof ScoreComponent scoreComponent && scoreComponent.name().equals("cf"));
if (cfCompound.hasTag("hook_id")) {
String hookID = cfCompound.getString("hook_id");
HookSetting setting = CustomFishingPlugin.get().getHookManager().getHookSetting(hookID);
if (setting == null) {
cfCompound.removeKey("hook_id");
cfCompound.removeKey("hook_item");
cfCompound.removeKey("hook_dur");
} else {
int damage = damageable.getDamage() + amount;
if (damage > itemStack.getType().getMaxDurability()) {
itemStack.setAmount(0);
} else {
damageable.setDamage(damage);
itemStack.setItemMeta(damageable);
for (String newLore : setting.getLore()) {
ScoreComponent.Builder builder = Component.score().name("cf").objective("hook");
builder.append(AdventureManagerImpl.getInstance().getComponentFromMiniMessage(
newLore.replace("{dur}", String.valueOf(cfCompound.getInteger("hook_dur")))
.replace("{max}", String.valueOf(setting.getMaxDurability()))
));
lore.add(GsonComponentSerializer.gson().serialize(builder.build()));
}
}
}
if (cfCompound.hasTag("max_dur")) {
int max = cfCompound.getInteger("max_dur");
int current = cfCompound.getInteger("cur_dur");
for (String newLore : CFConfig.durabilityLore) {
ScoreComponent.Builder builder = Component.score().name("cf").objective("durability");
builder.append(AdventureManagerImpl.getInstance().getComponentFromMiniMessage(
newLore.replace("{dur}", String.valueOf(current))
.replace("{max}", String.valueOf(max))
));
lore.add(GsonComponentSerializer.gson().serialize(builder.build()));
}
}
return nbtItem;
}
public static void addDurability(ItemStack itemStack, int amount) {
if (itemStack.getItemMeta() instanceof Damageable damageable) {
if (damageable.isUnbreakable()) {
return;
public static void updateItemLore(ItemStack itemStack) {
if (itemStack == null || itemStack.getType() == Material.AIR)
return;
NBTItem nbtItem = updateNBTItemLore(new NBTItem(itemStack));
itemStack.setItemMeta(nbtItem.getItem().getItemMeta());
}
public static void reduceHookDurability(ItemStack itemStack, boolean updateLore) {
if (itemStack == null || itemStack.getType() == Material.AIR)
return;
NBTItem nbtItem = new NBTItem(itemStack);
NBTCompound cfCompound = nbtItem.getCompound("CustomFishing");
if (cfCompound != null && cfCompound.hasTag("hook_dur")) {
int hookDur = cfCompound.getInteger("hook_dur");
if (hookDur > 0) {
cfCompound.setInteger("hook_dur", hookDur - 1);
} else if (hookDur != -1) {
cfCompound.removeKey("hook_id");
cfCompound.removeKey("hook_dur");
cfCompound.removeKey("hook_id");
}
NBTItem nbtItem = new NBTItem(itemStack);
NBTCompound cfCompound = nbtItem.getCompound("CustomFishing");
if (cfCompound != null && cfCompound.hasTag("max_dur")) {
int max = cfCompound.getInteger("max_dur");
int current = Math.min(max, cfCompound.getInteger("cur_dur") + amount);
cfCompound.setInteger("cur_dur", current);
int damage = (int) (itemStack.getType().getMaxDurability() * (1 - ((double) current / max)));
nbtItem.setInteger("Damage", damage);
}
if (updateLore) updateNBTItemLore(nbtItem);
itemStack.setItemMeta(nbtItem.getItem().getItemMeta());
}
public static void loseDurability(ItemStack itemStack, int amount, boolean updateLore) {
if (itemStack == null || itemStack.getType() == Material.AIR)
return;
int unBreakingLevel = itemStack.getEnchantmentLevel(Enchantment.DURABILITY);
if (Math.random() > (double) 1 / (unBreakingLevel + 1)) {
return;
}
NBTItem nbtItem = new NBTItem(itemStack);
if (nbtItem.getByte("Unbreakable") == 1) {
return;
}
NBTCompound cfCompound = nbtItem.getCompound("CustomFishing");
if (cfCompound != null && cfCompound.hasTag("max_dur")) {
int max = cfCompound.getInteger("max_dur");
int current = cfCompound.getInteger("cur_dur") - amount;
cfCompound.setInteger("cur_dur", current);
int damage = (int) (itemStack.getType().getMaxDurability() * (1 - ((double) current / max)));
nbtItem.setInteger("Damage", damage);
if (current > 0) {
if (updateLore) updateNBTItemLore(nbtItem);
itemStack.setItemMeta(nbtItem.getItem().getItemMeta());
} else {
int damage = Math.max(damageable.getDamage() - amount, 0);
damageable.setDamage(damage);
itemStack.setItemMeta(damageable);
itemStack.setAmount(0);
}
} else {
int damage = nbtItem.getInteger("Damage") + amount;
if (damage > itemStack.getType().getMaxDurability()) {
itemStack.setAmount(0);
} else {
nbtItem.setInteger("Damage", damage);
itemStack.setItemMeta(nbtItem.getItem().getItemMeta());
}
}
}
public static void addDurability(ItemStack itemStack, int amount, boolean updateLore) {
if (itemStack == null || itemStack.getType() == Material.AIR)
return;
NBTItem nbtItem = new NBTItem(itemStack);
if (nbtItem.getByte("Unbreakable") == 1) {
return;
}
NBTCompound cfCompound = nbtItem.getCompound("CustomFishing");
if (cfCompound != null && cfCompound.hasTag("max_dur")) {
int max = cfCompound.getInteger("max_dur");
int current = Math.min(max, cfCompound.getInteger("cur_dur") + amount);
cfCompound.setInteger("cur_dur", current);
int damage = (int) (itemStack.getType().getMaxDurability() * (1 - ((double) current / max)));
nbtItem.setInteger("Damage", damage);
if (updateLore) updateNBTItemLore(nbtItem);
} else {
int damage = Math.max(nbtItem.getInteger("Damage") - amount, 0);
nbtItem.setInteger("Damage", damage);
}
itemStack.setItemMeta(nbtItem.getItem().getItemMeta());
}
public static void setDurability(ItemStack itemStack, int amount, boolean updateLore) {
if (itemStack == null || itemStack.getType() == Material.AIR)
return;
if (amount <= 0) {
itemStack.setAmount(0);
return;
}
NBTItem nbtItem = new NBTItem(itemStack);
if (nbtItem.getByte("Unbreakable") == 1) {
return;
}
NBTCompound cfCompound = nbtItem.getCompound("CustomFishing");
if (cfCompound != null && cfCompound.hasTag("max_dur")) {
int max = cfCompound.getInteger("max_dur");
amount = Math.min(amount, max);
cfCompound.setInteger("cur_dur", amount);
int damage = (int) (itemStack.getType().getMaxDurability() * (1 - ((double) amount / max)));
nbtItem.setInteger("Damage", damage);
if (updateLore) updateNBTItemLore(nbtItem);
} else {
nbtItem.setInteger("Damage", itemStack.getType().getMaxDurability() - amount);
}
itemStack.setItemMeta(nbtItem.getItem().getItemMeta());
}
public static int getDurability(ItemStack itemStack) {
if (!(itemStack.getItemMeta() instanceof Damageable damageable))
return -1;
if (damageable.isUnbreakable())
return -1;
NBTItem nbtItem = new NBTItem(itemStack);
NBTCompound cfCompound = nbtItem.getCompound("CustomFishing");
if (cfCompound != null && cfCompound.hasTag("max_dur")) {
return cfCompound.getInteger("cur_dur");
} else {
return itemStack.getType().getMaxDurability() - damageable.getDamage();
}
}
public static int giveCertainAmountOfItem(Player player, ItemStack itemStack, int amount) {
PlayerInventory inventory = player.getInventory();
ItemMeta meta = itemStack.getItemMeta();
int maxStackSize = itemStack.getMaxStackSize();
if (amount > maxStackSize * 100) {
LogUtils.warn("Detected too many items spawning. Lowering the amount to " + (maxStackSize * 100));
amount = maxStackSize * 100;
}
int actualAmount = amount;
for (ItemStack other : inventory.getStorageContents()) {
if (other != null) {
if (other.getType() == itemStack.getType() && other.getItemMeta().equals(meta)) {
if (other.getAmount() < maxStackSize) {
int delta = maxStackSize - other.getAmount();
if (amount > delta) {
other.setAmount(maxStackSize);
amount -= delta;
} else {
other.setAmount(amount + other.getAmount());
return actualAmount;
}
}
}
}
}
if (amount > 0) {
for (ItemStack other : inventory.getStorageContents()) {
if (other == null) {
if (amount > maxStackSize) {
amount -= maxStackSize;
ItemStack cloned = itemStack.clone();
cloned.setAmount(maxStackSize);
inventory.addItem(cloned);
} else {
ItemStack cloned = itemStack.clone();
cloned.setAmount(amount);
inventory.addItem(cloned);
return actualAmount;
}
}
}
}
if (amount > 0) {
for (int i = 0; i < amount / maxStackSize; i++) {
ItemStack cloned = itemStack.clone();
cloned.setAmount(maxStackSize);
player.getWorld().dropItem(player.getLocation(), cloned);
}
int left = amount % maxStackSize;
if (left != 0) {
ItemStack cloned = itemStack.clone();
cloned.setAmount(left);
player.getWorld().dropItem(player.getLocation(), cloned);
}
}
return actualAmount;
}
}

View File

@@ -1,6 +1,6 @@
# Developer: @Xiao-MoMi
# Wiki: https://mo-mi.gitbook.io/xiaomomi-plugins/
config-version: '26'
config-version: '27'
# Debug
debug: false
@@ -168,6 +168,10 @@ other-settings:
block-detection-order:
- vanilla
custom-durability-format:
- ''
- '<gray>Durability</gray><white>: {dur} <gray>/</gray> {max}</white>'
# Offset characters' unicodes
# Never edit this unless you know what you are doing
offset-characters:

View File

@@ -0,0 +1,25 @@
delicate_hook:
material: SHEARS
display:
name: '<#1E90FF>Delicate hook'
lore:
- ''
- '<#7FFFD4>Desciption:'
- '<gray> - An embodiment of craftsmanship and allure, the hook'
- '<gray> - is not your average piece of tackle. Polished to'
- '<gray> - perfection and intricately designed, it gleams in the'
- '<gray> - water, irresistibly drawing high-quality fish closer.'
- ''
- '<#FFD700>Effects:'
- '<gray> - Increase the chance of getting high quality fish'
max-durability: 16
lore-on-rod:
- ''
- '<#7FFFAA>Equipped hook:'
- '<gray> - Delicate hook: <white>{dur}<white> times left'
effects:
group:
type: group-mod
value:
- silver_star:+1
- golden_star:+1

View File

@@ -29,6 +29,7 @@ beginner_rod:
- '<gray> - Increase the hook time'
- '<gray> - Reduces the challenge of fishing'
custom-model-data: 50001
max-durability: 64
effects:
time_effect:
type: hook-time
@@ -51,6 +52,7 @@ silver_rod:
- '<#FFD700>Effects:'
- '<gray> - Increase the chance of getting silver star fish'
custom-model-data: 50002
max-durability: 96
effects:
group:
type: group-mod
@@ -71,6 +73,7 @@ golden_rod:
- '<#FFD700>Effects:'
- '<gray> - Increase the chance of getting golden star fish'
custom-model-data: 50003
max-durability: 80
effects:
group:
type: group-mod
@@ -93,6 +96,7 @@ star_rod:
- '<#FFD700>Effects:'
- '<gray> - +15s Game Time'
custom-model-data: 50004
max-durability: 128
effects:
time_effect:
type: game-time
@@ -116,6 +120,7 @@ bone_rod:
- '<gray> - Fishing in lava'
- '<gray> - Sometimes skeleton would grab the hook'
custom-model-data: 50005
max-durability: 32
effects:
lava:
type: lava-fishing
@@ -141,6 +146,7 @@ magical_rod:
- '<gray> - 1x book bait'
- '<gray> - 10 exp levels'
custom-model-data: 50006
max-durability: 16
requirements:
requirement_1:
type: level
@@ -191,6 +197,7 @@ master_rod:
- '<gray> - Increase the challenge of fishing'
- '<gray> - Higher chance of getting quality fish'
custom-model-data: 50007
max-durability: 128
effects:
time_effect:
type: hook-time