mirror of
https://github.com/Xiao-MoMi/Custom-Fishing.git
synced 2025-12-28 19:39:06 +00:00
2.0-backup-4
This commit is contained in:
@@ -34,17 +34,23 @@ public class CommandManagerImpl implements CommandManager {
|
||||
)
|
||||
.register();
|
||||
|
||||
if (CustomFishingPlugin.get().getBagManager().isBagEnabled()) {
|
||||
new CommandAPICommand("sellfish")
|
||||
.withPermission("customfishing.sellfish")
|
||||
.executesPlayer((player, args) -> {
|
||||
plugin.getMarketManager().openMarketGUI(player);
|
||||
})
|
||||
.register();
|
||||
|
||||
if (plugin.getBagManager().isBagEnabled()) {
|
||||
FishingBagCommand.INSTANCE.getBagCommand().register();
|
||||
}
|
||||
}
|
||||
|
||||
private CommandAPICommand getReloadCommand() {
|
||||
return new CommandAPICommand("reload")
|
||||
.withPermission("customfishing.command.reload")
|
||||
.executes((sender, args) -> {
|
||||
long time = System.currentTimeMillis();
|
||||
CustomFishingPlugin.get().reload();
|
||||
plugin.reload();
|
||||
AdventureManagerImpl.getInstance().sendMessageWithPrefix(sender, Locale.MSG_Reload.replace("{time}", String.valueOf(System.currentTimeMillis()-time)));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -313,6 +313,7 @@ public class ActionManagerImpl implements ActionManager {
|
||||
condition.getPlayer().addPotionEffect(potionEffect);
|
||||
};
|
||||
}
|
||||
LogUtils.warn("Illegal value format found at action: potion-effect");
|
||||
return null;
|
||||
});
|
||||
}
|
||||
@@ -332,6 +333,7 @@ public class ActionManagerImpl implements ActionManager {
|
||||
AdventureManagerImpl.getInstance().sendSound(condition.getPlayer(), sound);
|
||||
};
|
||||
}
|
||||
LogUtils.warn("Illegal value format found at action: sound");
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -223,17 +223,15 @@ public class BlockManagerImpl implements BlockManager, Listener {
|
||||
} else {
|
||||
blockData = blockLibraryMap.get("vanilla").getBlockData(player, blockID, config.getDataModifier());
|
||||
}
|
||||
plugin.getScheduler().runTaskSync(() -> {
|
||||
FallingBlock fallingBlock = hookLocation.getWorld().spawnFallingBlock(hookLocation, blockData);
|
||||
fallingBlock.getPersistentDataContainer().set(
|
||||
Objects.requireNonNull(NamespacedKey.fromString("block", CustomFishingPlugin.get())),
|
||||
PersistentDataType.STRING,
|
||||
loot.getID() + ";" + player.getName()
|
||||
);
|
||||
Vector vector = playerLocation.subtract(hookLocation).toVector().multiply((config.getHorizontalVector()) - 1);
|
||||
vector = vector.setY((vector.getY() + 0.2) * config.getVerticalVector());
|
||||
fallingBlock.setVelocity(vector);
|
||||
}, hookLocation);
|
||||
FallingBlock fallingBlock = hookLocation.getWorld().spawnFallingBlock(hookLocation, blockData);
|
||||
fallingBlock.getPersistentDataContainer().set(
|
||||
Objects.requireNonNull(NamespacedKey.fromString("block", CustomFishingPlugin.get())),
|
||||
PersistentDataType.STRING,
|
||||
loot.getID() + ";" + player.getName()
|
||||
);
|
||||
Vector vector = playerLocation.subtract(hookLocation).toVector().multiply((config.getHorizontalVector()) - 1);
|
||||
vector = vector.setY((vector.getY() + 0.2) * config.getVerticalVector());
|
||||
fallingBlock.setVelocity(vector);
|
||||
}
|
||||
|
||||
private void registerDirectional() {
|
||||
|
||||
@@ -2,7 +2,6 @@ package net.momirealms.customfishing.mechanic.fishing;
|
||||
|
||||
import com.destroystokyo.paper.event.player.PlayerJumpEvent;
|
||||
import de.tr7zw.changeme.nbtapi.NBTItem;
|
||||
import io.papermc.paper.event.player.AsyncChatEvent;
|
||||
import net.momirealms.customfishing.CustomFishingPluginImpl;
|
||||
import net.momirealms.customfishing.api.common.Pair;
|
||||
import net.momirealms.customfishing.api.event.LavaFishingEvent;
|
||||
@@ -434,7 +433,7 @@ public class FishingManagerImpl implements Listener, FishingManager {
|
||||
if (bonus != null)
|
||||
tempFishingState.getEffect().merge(bonus);
|
||||
|
||||
if (gamingPlayer.isSucceeded())
|
||||
if (gamingPlayer.isSuccessful())
|
||||
success(tempFishingState, fishHook);
|
||||
else
|
||||
fail(tempFishingState);
|
||||
@@ -472,10 +471,6 @@ public class FishingManagerImpl implements Listener, FishingManager {
|
||||
var fishingPreparation = state.getPreparation();
|
||||
var player = fishingPreparation.getPlayer();
|
||||
|
||||
int amount = (int) effect.getMultipleLootChance();
|
||||
amount += Math.random() < (effect.getMultipleLootChance() - amount) ? 2 : 1;
|
||||
|
||||
fishingPreparation.insertArg("{amount}", String.valueOf(amount));
|
||||
fishingPreparation.insertArg("{score}", String.format("%.2f", loot.getScore() * effect.getScoreMultiplier()));
|
||||
fishingPreparation.insertArg("{size-multiplier}", String.format("%.2f", effect.getSizeMultiplier()));
|
||||
fishingPreparation.insertArg("{x}", String.valueOf(hook.getLocation().getBlockX()));
|
||||
@@ -483,35 +478,39 @@ public class FishingManagerImpl implements Listener, FishingManager {
|
||||
fishingPreparation.insertArg("{z}", String.valueOf(hook.getLocation().getBlockZ()));
|
||||
fishingPreparation.insertArg("{loot}", loot.getID());
|
||||
fishingPreparation.insertArg("{nick}", loot.getNick());
|
||||
fishingPreparation.insertArg("{score}", String.format("%.2f", loot.getScore()));
|
||||
|
||||
switch (loot.getType()) {
|
||||
case LOOT -> {
|
||||
// build the items for multiple times instead of using setAmount() to make sure that each item is unique
|
||||
if (loot.getID().equals("vanilla")) {
|
||||
ItemStack itemStack = vanillaLootMap.remove(player.getUniqueId());
|
||||
if (itemStack != null) {
|
||||
fishingPreparation.insertArg("{loot}", "<lang:item.minecraft." + itemStack.getType().toString().toLowerCase() + ">");
|
||||
plugin.getScheduler().runTaskSync(() -> {
|
||||
switch (loot.getType()) {
|
||||
case LOOT -> {
|
||||
int amount = (int) effect.getMultipleLootChance();
|
||||
amount += Math.random() < (effect.getMultipleLootChance() - amount) ? 2 : 1;
|
||||
fishingPreparation.insertArg("{amount}", String.valueOf(amount));
|
||||
// build the items for multiple times instead of using setAmount() to make sure that each item is unique
|
||||
if (loot.getID().equals("vanilla")) {
|
||||
ItemStack itemStack = vanillaLootMap.remove(player.getUniqueId());
|
||||
if (itemStack != null) {
|
||||
fishingPreparation.insertArg("{loot}", "<lang:item.minecraft." + itemStack.getType().toString().toLowerCase() + ">");
|
||||
for (int i = 0; i < amount; i++) {
|
||||
plugin.getItemManager().dropItem(hook.getLocation(), player.getLocation(), itemStack.clone());
|
||||
doSuccessActions(loot, fishingPreparation, player);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < amount; i++) {
|
||||
plugin.getItemManager().dropItem(hook.getLocation(), player.getLocation(), itemStack.clone());
|
||||
doActions(loot, fishingPreparation, player);
|
||||
plugin.getItemManager().dropItem(player, hook.getLocation(), player.getLocation(), loot, fishingPreparation.getArgs());
|
||||
doSuccessActions(loot, fishingPreparation, player);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < amount; i++) {
|
||||
plugin.getItemManager().dropItem(player, hook.getLocation(), player.getLocation(), loot, fishingPreparation.getArgs());
|
||||
doActions(loot, fishingPreparation, player);
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
case MOB -> plugin.getMobManager().summonMob(hook.getLocation(), player.getLocation(), loot);
|
||||
case BLOCK -> plugin.getBlockManager().summonBlock(player, hook.getLocation(), player.getLocation(), loot);
|
||||
}
|
||||
case MOB -> plugin.getMobManager().summonMob(hook.getLocation(), player.getLocation(), loot);
|
||||
case BLOCK -> plugin.getBlockManager().summonBlock(player, hook.getLocation(), player.getLocation(), loot);
|
||||
}
|
||||
doActions(loot, fishingPreparation, player);
|
||||
doSuccessActions(loot, fishingPreparation, player);
|
||||
}, hook.getLocation());
|
||||
}
|
||||
|
||||
private void doActions(Loot loot, FishingPreparation fishingPreparation, Player player) {
|
||||
private void doSuccessActions(Loot loot, FishingPreparation fishingPreparation, Player player) {
|
||||
Action[] globalActions = LootManagerImpl.globalLootProperties.getActions(ActionTrigger.SUCCESS);
|
||||
if (globalActions != null)
|
||||
for (Action action : globalActions)
|
||||
@@ -565,7 +564,12 @@ public class FishingManagerImpl implements Listener, FishingManager {
|
||||
|
||||
@Override
|
||||
public void startFishingGame(Player player, GameSettings settings, Game game) {
|
||||
this.gamingPlayerMap.put(player.getUniqueId(), game.start(player, settings, this));
|
||||
Optional<FishHook> hook = getHook(player.getUniqueId());
|
||||
if (hook.isPresent()) {
|
||||
this.gamingPlayerMap.put(player.getUniqueId(), game.start(player, hook.get(), settings));
|
||||
} else {
|
||||
LogUtils.warn("It seems that player " + player.getName() + " is not fishing. Fishing game failed to start.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -165,7 +165,7 @@ public class GameManagerImpl implements GameManager {
|
||||
var barImage = section.getString("subtitle.bar");
|
||||
var pointerImage = section.getString("subtitle.pointer");
|
||||
|
||||
return (player, settings, manager) -> new AbstractGamingPlayer(player, settings, manager) {
|
||||
return (player, fishHook, settings) -> new AbstractGamingPlayer(player, fishHook, settings) {
|
||||
|
||||
private int progress;
|
||||
private boolean face;
|
||||
@@ -205,7 +205,7 @@ public class GameManagerImpl implements GameManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSucceeded() {
|
||||
public boolean isSuccessful() {
|
||||
int last = progress / widthPerSection;
|
||||
return (Math.random() < successRate[last]);
|
||||
}
|
||||
@@ -234,7 +234,7 @@ public class GameManagerImpl implements GameManager {
|
||||
var barImage = section.getString("subtitle.bar");
|
||||
var tip = section.getString("tip");
|
||||
|
||||
return (player, settings, manager) -> new AbstractGamingPlayer(player, settings, manager) {
|
||||
return (player, fishHook, settings) -> new AbstractGamingPlayer(player, fishHook, settings) {
|
||||
private double hold_time;
|
||||
private double judgement_position;
|
||||
private double fish_position;
|
||||
@@ -278,8 +278,8 @@ public class GameManagerImpl implements GameManager {
|
||||
hold_time -= punishment * 33;
|
||||
}
|
||||
if (hold_time >= time_requirement) {
|
||||
succeeded = true;
|
||||
manager.processGameResult(this);
|
||||
setGameResult(true);
|
||||
endGame();
|
||||
return;
|
||||
}
|
||||
hold_time = Math.max(0, Math.min(hold_time, time_requirement));
|
||||
@@ -376,7 +376,7 @@ public class GameManagerImpl implements GameManager {
|
||||
var barImage = section.getString("subtitle.bar");
|
||||
var tip = section.getString("tip");
|
||||
|
||||
return (player, settings, manager) -> new AbstractGamingPlayer(player, settings, manager) {
|
||||
return (player, fishHook, settings) -> new AbstractGamingPlayer(player, fishHook, settings) {
|
||||
|
||||
private int fish_position = fishStartPosition;
|
||||
private double strain;
|
||||
@@ -401,13 +401,13 @@ public class GameManagerImpl implements GameManager {
|
||||
if (player.isSneaking()) pull();
|
||||
else loosen();
|
||||
if (fish_position < successPosition - fishIconWidth - 1) {
|
||||
super.succeeded = true;
|
||||
manager.processGameResult(this);
|
||||
setGameResult(true);
|
||||
endGame();
|
||||
return;
|
||||
}
|
||||
if (fish_position + fishIconWidth > barEffectiveWidth || strain >= ultimateTension) {
|
||||
super.succeeded = false;
|
||||
manager.processGameResult(this);
|
||||
setGameResult(false);
|
||||
endGame();
|
||||
return;
|
||||
}
|
||||
showUI();
|
||||
|
||||
@@ -266,12 +266,10 @@ public class ItemManagerImpl implements ItemManager {
|
||||
|
||||
@Override
|
||||
public void dropItem(Location hookLocation, Location playerLocation, ItemStack itemStack) {
|
||||
plugin.getScheduler().runTaskSync(() -> {
|
||||
Entity itemEntity = hookLocation.getWorld().dropItem(hookLocation, itemStack);
|
||||
Vector vector = playerLocation.subtract(hookLocation).toVector().multiply(0.105);
|
||||
vector = vector.setY((vector.getY() + 0.2) * 1.18);
|
||||
itemEntity.setVelocity(vector);
|
||||
}, hookLocation);
|
||||
Entity itemEntity = hookLocation.getWorld().dropItem(hookLocation, itemStack);
|
||||
Vector vector = playerLocation.subtract(hookLocation).toVector().multiply(0.105);
|
||||
vector = vector.setY((vector.getY() + 0.2) * 1.18);
|
||||
itemEntity.setVelocity(vector);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -291,7 +289,7 @@ public class ItemManagerImpl implements ItemManager {
|
||||
return Pair.of(Float.parseFloat(split[0]), Float.parseFloat(split[1]));
|
||||
}
|
||||
|
||||
public static class CFBuilder implements ItemBuilder, BuildableItem {
|
||||
public static class CFBuilder implements ItemBuilder {
|
||||
|
||||
private final String library;
|
||||
private final String id;
|
||||
@@ -438,6 +436,7 @@ public class ItemManagerImpl implements ItemManager {
|
||||
|
||||
@Override
|
||||
public ItemBuilder price(float base, float bonus) {
|
||||
if (base == 0 && bonus == 0) return this;
|
||||
editors.put("price", (player, nbtItem, placeholders) -> {
|
||||
if (base != 0) {
|
||||
placeholders.put("{base}", String.format("%.2f", base));
|
||||
@@ -463,7 +462,7 @@ public class ItemManagerImpl implements ItemManager {
|
||||
editors.put("size", (player, nbtItem, placeholders) -> {
|
||||
NBTCompound cfCompound = nbtItem.getOrCreateCompound("CustomFishing");
|
||||
float random = size.left() + ThreadLocalRandom.current().nextFloat(size.right() - size.left());
|
||||
float bonus = Float.parseFloat(placeholders.getOrDefault("size-multiplier", "1.0"));
|
||||
float bonus = Float.parseFloat(placeholders.getOrDefault("{size-multiplier}", "1.0"));
|
||||
random *= bonus;
|
||||
cfCompound.setFloat("size", random);
|
||||
placeholders.put("{size}", String.format("%.2f", random));
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.momirealms.customfishing.mechanic.market;
|
||||
|
||||
import net.momirealms.customfishing.adventure.AdventureManagerImpl;
|
||||
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;
|
||||
@@ -20,10 +21,12 @@ public class MarketGUI {
|
||||
private final Inventory inventory;
|
||||
private final MarketManagerImpl manager;
|
||||
private final Player owner;
|
||||
private final EarningData earningData;
|
||||
|
||||
public MarketGUI(MarketManagerImpl manager, Player player) {
|
||||
public MarketGUI(MarketManagerImpl manager, Player player, EarningData earningData) {
|
||||
this.manager = manager;
|
||||
this.owner = player;
|
||||
this.earningData = earningData;
|
||||
this.itemsCharMap = new HashMap<>();
|
||||
this.itemsSlotMap = new HashMap<>();
|
||||
var holder = new MarketGUIHolder();
|
||||
@@ -45,8 +48,10 @@ public class MarketGUI {
|
||||
for (int index = 0; index < 9; index++) {
|
||||
char symbol = content.charAt(index);
|
||||
MarketGUIElement element = itemsCharMap.get(symbol);
|
||||
element.addSlot(index + line * 9);
|
||||
itemsSlotMap.put(index + line * 9, element);
|
||||
if (element != null) {
|
||||
element.addSlot(index + line * 9);
|
||||
itemsSlotMap.put(index + line * 9, element);
|
||||
}
|
||||
}
|
||||
line++;
|
||||
}
|
||||
@@ -82,35 +87,48 @@ public class MarketGUI {
|
||||
return itemsCharMap.get(slot);
|
||||
}
|
||||
|
||||
public void refresh() {
|
||||
public MarketGUI refresh() {
|
||||
double totalWorth = getTotalWorth();
|
||||
MarketDynamicGUIElement functionElement = (MarketDynamicGUIElement) getElement(manager.getFunctionSlot());
|
||||
if (functionElement == null) {
|
||||
return this;
|
||||
}
|
||||
if (totalWorth <= 0) {
|
||||
addElement(new MarketDynamicGUIElement(
|
||||
manager.getFunctionSlot(),
|
||||
functionElement.setItemStack(
|
||||
manager.getFunctionIconDenyBuilder().build(owner,
|
||||
Map.of("{worth}", String.format("%.2f", totalWorth)
|
||||
,"{player}", owner.getName())
|
||||
Map.of("{money}", String.format("%.2f", totalWorth)
|
||||
,"{player}", owner.getName()
|
||||
,"{rest}", String.format("%.2f", manager.getEarningLimit() - earningData.earnings))
|
||||
)
|
||||
));
|
||||
);
|
||||
} else if (manager.getEarningLimit() != -1 && (manager.getEarningLimit() - earningData.earnings < totalWorth)) {
|
||||
functionElement.setItemStack(
|
||||
manager.getFunctionIconLimitBuilder().build(owner,
|
||||
Map.of("{money}", String.format("%.2f", totalWorth)
|
||||
,"{player}", owner.getName()
|
||||
,"{rest}", String.format("%.2f", manager.getEarningLimit() - earningData.earnings))
|
||||
)
|
||||
);
|
||||
} else {
|
||||
addElement(new MarketDynamicGUIElement(
|
||||
manager.getFunctionSlot(),
|
||||
functionElement.setItemStack(
|
||||
manager.getFunctionIconAllowBuilder().build(owner,
|
||||
Map.of("{worth}", String.format("%.2f", totalWorth)
|
||||
,"{player}", owner.getName())
|
||||
Map.of("{money}", String.format("%.2f", totalWorth)
|
||||
,"{player}", owner.getName()
|
||||
,"{rest}", String.format("%.2f", manager.getEarningLimit() - earningData.earnings))
|
||||
)
|
||||
));
|
||||
);
|
||||
}
|
||||
for (Map.Entry<Integer, MarketGUIElement> entry : itemsSlotMap.entrySet()) {
|
||||
if (entry.getValue() instanceof MarketDynamicGUIElement dynamicGUIElement) {
|
||||
this.inventory.setItem(entry.getKey(), dynamicGUIElement.getItemStack().clone());
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public double getTotalWorth() {
|
||||
double money = 0d;
|
||||
MarketGUIElement itemElement = getElement(manager.getItemSlot());
|
||||
MarketGUIElement itemElement = getElement(manager.getItemSlot());;
|
||||
if (itemElement == null) {
|
||||
LogUtils.warn("No item slot available. Please check if GUI layout contains the item slot symbol.");
|
||||
return money;
|
||||
@@ -137,4 +155,36 @@ public class MarketGUI {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getEmptyItemSlot() {
|
||||
MarketGUIElement itemElement = getElement(manager.getItemSlot());
|
||||
if (itemElement == null) {
|
||||
return -1;
|
||||
}
|
||||
for (int slot : itemElement.getSlots()) {
|
||||
ItemStack itemStack = inventory.getItem(slot);
|
||||
if (itemStack == null || itemStack.getType() == Material.AIR) {
|
||||
return slot;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void returnItems() {
|
||||
MarketGUIElement itemElement = getElement(manager.getItemSlot());
|
||||
if (itemElement == null) {
|
||||
return;
|
||||
}
|
||||
for (int slot : itemElement.getSlots()) {
|
||||
ItemStack itemStack = inventory.getItem(slot);
|
||||
if (itemStack != null && itemStack.getType() != Material.AIR) {
|
||||
owner.getInventory().addItem(itemStack);
|
||||
inventory.setItem(slot, new ItemStack(Material.AIR));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public EarningData getEarningData() {
|
||||
return earningData;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
package net.momirealms.customfishing.mechanic.market;
|
||||
|
||||
import com.willfp.eco.core.map.MutableListMap;
|
||||
import de.tr7zw.changeme.nbtapi.NBTItem;
|
||||
import net.momirealms.customfishing.api.CustomFishingPlugin;
|
||||
import net.momirealms.customfishing.api.data.EarningData;
|
||||
import net.momirealms.customfishing.api.data.InventoryData;
|
||||
import net.momirealms.customfishing.api.data.user.OnlineUser;
|
||||
import net.momirealms.customfishing.api.manager.MarketManager;
|
||||
import net.momirealms.customfishing.api.mechanic.action.Action;
|
||||
import net.momirealms.customfishing.api.mechanic.condition.Condition;
|
||||
import net.momirealms.customfishing.api.mechanic.item.BuildableItem;
|
||||
import net.momirealms.customfishing.api.mechanic.item.ItemBuilder;
|
||||
import net.momirealms.customfishing.api.mechanic.market.MarketGUIHolder;
|
||||
import net.momirealms.customfishing.api.util.LogUtils;
|
||||
import net.momirealms.customfishing.util.ConfigUtils;
|
||||
import net.objecthunter.exp4j.Expression;
|
||||
import net.objecthunter.exp4j.ExpressionBuilder;
|
||||
@@ -14,12 +19,12 @@ import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
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.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.*;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
@@ -34,13 +39,18 @@ public class MarketManagerImpl implements MarketManager, Listener {
|
||||
private String[] layout;
|
||||
private String title;
|
||||
private String formula;
|
||||
private final HashMap<Character, ItemBuilder> decorativeIcons;
|
||||
private final HashMap<Character, BuildableItem> decorativeIcons;
|
||||
private char itemSlot;
|
||||
private char functionSlot;
|
||||
private BuildableItem functionIconAllowBuilder;
|
||||
private BuildableItem functionIconDenyBuilder;
|
||||
private BuildableItem functionIconLimitBuilder;
|
||||
private Action[] denyActions;
|
||||
private Action[] allowActions;
|
||||
private Action[] limitActions;
|
||||
private double earningLimit;
|
||||
private ConcurrentHashMap<UUID, MarketGUI> marketGUIMap;
|
||||
private boolean allowItemWithNoPrice;
|
||||
private final ConcurrentHashMap<UUID, MarketGUI> marketGUIMap;
|
||||
|
||||
public MarketManagerImpl(CustomFishingPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
@@ -54,7 +64,6 @@ public class MarketManagerImpl implements MarketManager, Listener {
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
|
||||
public void unload() {
|
||||
HandlerList.unregisterAll(this);
|
||||
this.priceMap.clear();
|
||||
@@ -70,6 +79,17 @@ public class MarketManagerImpl implements MarketManager, Listener {
|
||||
this.layout = config.getStringList("layout").toArray(new String[0]);
|
||||
this.title = config.getString("title", "market.title");
|
||||
this.formula = config.getString("price-formula", "{base} + {bonus} * {size}");
|
||||
this.itemSlot = config.getString("item-slot.symbol", "I").charAt(0);
|
||||
this.functionSlot = config.getString("functional-icons.symbol", "B").charAt(0);
|
||||
this.functionIconAllowBuilder = plugin.getItemManager().getItemBuilder(config.getConfigurationSection("functional-icons.allow-icon"), "gui", "allow");
|
||||
this.functionIconDenyBuilder = plugin.getItemManager().getItemBuilder(config.getConfigurationSection("functional-icons.deny-icon"), "gui", "deny");
|
||||
this.functionIconLimitBuilder = plugin.getItemManager().getItemBuilder(config.getConfigurationSection("functional-icons.limit-icon"), "gui", "limit");
|
||||
this.allowActions = plugin.getActionManager().getActions(config.getConfigurationSection("functional-icons.allow-icon.action"));
|
||||
this.denyActions = plugin.getActionManager().getActions(config.getConfigurationSection("functional-icons.deny-icon.action"));
|
||||
this.limitActions = plugin.getActionManager().getActions(config.getConfigurationSection("functional-icons.limit-icon.action"));
|
||||
this.earningLimit = config.getBoolean("limitation.enable", true) ? config.getDouble("limitation.earnings", 100) : -1;
|
||||
this.allowItemWithNoPrice = config.getBoolean("item-slot.allow-items-with-no-price", true);
|
||||
|
||||
ConfigurationSection priceSection = config.getConfigurationSection("item-price");
|
||||
if (priceSection != null) {
|
||||
for (Map.Entry<String, Object> entry : priceSection.getValues(false).entrySet()) {
|
||||
@@ -88,9 +108,70 @@ public class MarketManagerImpl implements MarketManager, Listener {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openMarketGUI(Player player) {
|
||||
MarketGUI gui = new MarketGUI(this, player);
|
||||
OnlineUser user = plugin.getStorageManager().getOnlineUser(player.getUniqueId());
|
||||
if (user == null) {
|
||||
LogUtils.warn("Player " + player.getName() + "'s market data is not loaded yet.");
|
||||
return;
|
||||
}
|
||||
|
||||
MarketGUI gui = new MarketGUI(this, player, user.getEarningData());
|
||||
gui.addElement(new MarketGUIElement(getItemSlot(), new ItemStack(Material.AIR)));
|
||||
gui.addElement(new MarketDynamicGUIElement(getFunctionSlot(), new ItemStack(Material.AIR)));
|
||||
for (Map.Entry<Character, BuildableItem> entry : decorativeIcons.entrySet()) {
|
||||
gui.addElement(new MarketGUIElement(entry.getKey(), entry.getValue().build(player)));
|
||||
}
|
||||
gui.build().refresh().show(player);
|
||||
marketGUIMap.put(player.getUniqueId(), gui);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onCloseInv(InventoryCloseEvent event) {
|
||||
if (!(event.getPlayer() instanceof Player player))
|
||||
return;
|
||||
if (!(event.getInventory().getHolder() instanceof MarketGUIHolder))
|
||||
return;
|
||||
MarketGUI gui = marketGUIMap.remove(player.getUniqueId());
|
||||
if (gui != null)
|
||||
gui.returnItems();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onQuit(PlayerQuitEvent event) {
|
||||
MarketGUI gui = marketGUIMap.remove(event.getPlayer().getUniqueId());
|
||||
if (gui != null)
|
||||
gui.returnItems();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onDragInv(InventoryDragEvent event) {
|
||||
if (event.isCancelled())
|
||||
return;
|
||||
Inventory inventory = event.getInventory();
|
||||
if (!(inventory.getHolder() instanceof MarketGUIHolder holder))
|
||||
return;
|
||||
Player player = (Player) event.getWhoClicked();
|
||||
MarketGUI gui = marketGUIMap.get(player.getUniqueId());
|
||||
if (gui == null) {
|
||||
event.setCancelled(true);
|
||||
player.closeInventory();
|
||||
return;
|
||||
}
|
||||
|
||||
MarketGUIElement element = gui.getElement(itemSlot);
|
||||
if (element == null) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
List<Integer> slots = element.getSlots();
|
||||
for (int dragSlot : event.getRawSlots()) {
|
||||
if (!slots.contains(dragSlot)) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@@ -100,62 +181,91 @@ public class MarketManagerImpl implements MarketManager, Listener {
|
||||
Inventory clickedInv = event.getClickedInventory();
|
||||
if (clickedInv == null)
|
||||
return;
|
||||
HumanEntity human = event.getWhoClicked();
|
||||
if (!(clickedInv.getHolder() instanceof MarketGUIHolder holder))
|
||||
Player player = (Player) event.getWhoClicked();
|
||||
if (!(event.getInventory().getHolder() instanceof MarketGUIHolder holder))
|
||||
return;
|
||||
|
||||
MarketGUI gui = marketGUIMap.get(human.getUniqueId());
|
||||
MarketGUI gui = marketGUIMap.get(player.getUniqueId());
|
||||
if (gui == null) {
|
||||
event.setCancelled(true);
|
||||
human.closeInventory();
|
||||
player.closeInventory();
|
||||
return;
|
||||
}
|
||||
|
||||
int slot = event.getSlot();
|
||||
MarketGUIElement element = gui.getElement(slot);
|
||||
if (element == null) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
if (clickedInv != player.getInventory()) {
|
||||
EarningData data = gui.getEarningData();
|
||||
if (data.date != getDate()) {
|
||||
data.date = getDate();
|
||||
data.earnings = 0;
|
||||
}
|
||||
|
||||
if (element.getSymbol() == itemSlot) {
|
||||
plugin.getScheduler().runTaskSyncLater(gui::refresh, human.getLocation(), 50, TimeUnit.MILLISECONDS);
|
||||
return;
|
||||
}
|
||||
int slot = event.getSlot();
|
||||
MarketGUIElement element = gui.getElement(slot);
|
||||
if (element == null) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (element.getSymbol() == functionSlot) {
|
||||
event.setCancelled(true);
|
||||
double worth = gui.getTotalWorth();
|
||||
if (worth > 0) {
|
||||
double remainingToEarn = getRemainingMoneyToEarn(human.getUniqueId());
|
||||
if (remainingToEarn < worth) {
|
||||
if (element.getSymbol() != itemSlot) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
if (element.getSymbol() == functionSlot) {
|
||||
double worth = gui.getTotalWorth();
|
||||
Condition condition = new Condition(player, new HashMap<>(Map.of(
|
||||
"{money}", String.format("%.2f", worth)
|
||||
,"{rest}", String.format("%.2f", (earningLimit - data.earnings))
|
||||
)));
|
||||
if (worth > 0) {
|
||||
if (earningLimit != -1 && (earningLimit - data.earnings) < worth) {
|
||||
// can't earn more money
|
||||
if (limitActions != null) {
|
||||
for (Action action : limitActions) {
|
||||
action.trigger(condition);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// clear items
|
||||
gui.clearWorthyItems();
|
||||
data.earnings += worth;
|
||||
condition.insertArg("{rest}", String.format("%.2f", (earningLimit - data.earnings)));
|
||||
if (allowActions != null) {
|
||||
for (Action action : allowActions) {
|
||||
action.trigger(condition);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
gui.clearWorthyItems();
|
||||
this.setRemainMoneyToEarn(human.getUniqueId(), remainingToEarn + worth);
|
||||
// nothing to sell
|
||||
if (denyActions != null) {
|
||||
for (Action action : denyActions) {
|
||||
action.trigger(condition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ItemStack current = event.getCurrentItem();
|
||||
if (!allowItemWithNoPrice) {
|
||||
double price = getItemPrice(current);
|
||||
if (price <= 0) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ((event.getClick() == ClickType.SHIFT_LEFT || event.getClick() == ClickType.SHIFT_RIGHT)
|
||||
&& (current != null && current.getType() != Material.AIR)) {
|
||||
event.setCancelled(true);
|
||||
int slot = gui.getEmptyItemSlot();
|
||||
if (slot != -1) {
|
||||
gui.getInventory().setItem(slot, current.clone());
|
||||
current.setAmount(0);
|
||||
}
|
||||
}
|
||||
plugin.getScheduler().runTaskSyncLater(gui::refresh, human.getLocation(), 50, TimeUnit.MILLISECONDS);
|
||||
return;
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
public double getRemainingMoneyToEarn(UUID uuid) {
|
||||
OnlineUser user = plugin.getStorageManager().getOnlineUser(uuid);
|
||||
if (user == null) {
|
||||
return -1;
|
||||
}
|
||||
return earningLimit - user.getEarningData().earnings;
|
||||
}
|
||||
|
||||
public void setRemainMoneyToEarn(UUID uuid, double remaining) {
|
||||
OnlineUser user = plugin.getStorageManager().getOnlineUser(uuid);
|
||||
if (user == null) {
|
||||
return;
|
||||
}
|
||||
user.getEarningData().earnings = remaining;
|
||||
plugin.getScheduler().runTaskSyncLater(gui::refresh, player.getLocation(), 50, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -171,13 +281,13 @@ public class MarketManagerImpl implements MarketManager, Listener {
|
||||
NBTItem nbtItem = new NBTItem(itemStack);
|
||||
Double price = nbtItem.getDouble("Price");
|
||||
if (price != null && price != 0) {
|
||||
return price;
|
||||
return price * itemStack.getAmount();
|
||||
}
|
||||
String itemID = itemStack.getType().name();
|
||||
if (nbtItem.hasTag("CustomModelData")) {
|
||||
itemID = itemID + ":" + nbtItem.getInteger("CustomModelData");
|
||||
}
|
||||
return priceMap.getOrDefault(itemID, 0d);
|
||||
return priceMap.getOrDefault(itemID, 0d) * itemStack.getAmount();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -212,6 +322,14 @@ public class MarketManagerImpl implements MarketManager, Listener {
|
||||
return title;
|
||||
}
|
||||
|
||||
public double getEarningLimit() {
|
||||
return earningLimit;
|
||||
}
|
||||
|
||||
public BuildableItem getFunctionIconLimitBuilder() {
|
||||
return functionIconLimitBuilder;
|
||||
}
|
||||
|
||||
public BuildableItem getFunctionIconAllowBuilder() {
|
||||
return functionIconAllowBuilder;
|
||||
}
|
||||
|
||||
@@ -125,20 +125,18 @@ public class MobManagerImpl implements MobManager {
|
||||
return;
|
||||
}
|
||||
String mobID = config.getMobID();
|
||||
plugin.getScheduler().runTaskSync(() -> {
|
||||
Entity entity;
|
||||
if (mobID.contains(":")) {
|
||||
String[] split = mobID.split(":", 2);
|
||||
String identification = split[0];
|
||||
String id = split[1];
|
||||
MobLibrary library = mobLibraryMap.get(identification);
|
||||
entity = library.spawn(hookLocation, id, config.getPropertyMap());
|
||||
} else {
|
||||
entity = mobLibraryMap.get("vanilla").spawn(hookLocation, mobID, config.getPropertyMap());
|
||||
}
|
||||
Vector vector = playerLocation.subtract(hookLocation).toVector().multiply((config.getHorizontalVector()) - 1);
|
||||
vector = vector.setY((vector.getY() + 0.2) * config.getVerticalVector());
|
||||
entity.setVelocity(vector);
|
||||
}, hookLocation);
|
||||
Entity entity;
|
||||
if (mobID.contains(":")) {
|
||||
String[] split = mobID.split(":", 2);
|
||||
String identification = split[0];
|
||||
String id = split[1];
|
||||
MobLibrary library = mobLibraryMap.get(identification);
|
||||
entity = library.spawn(hookLocation, id, config.getPropertyMap());
|
||||
} else {
|
||||
entity = mobLibraryMap.get("vanilla").spawn(hookLocation, mobID, config.getPropertyMap());
|
||||
}
|
||||
Vector vector = playerLocation.subtract(hookLocation).toVector().multiply((config.getHorizontalVector()) - 1);
|
||||
vector = vector.setY((vector.getY() + 0.2) * config.getVerticalVector());
|
||||
entity.setVelocity(vector);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
# Container title
|
||||
title: '<gradient:#A52A2A:#800000:#A52A2A>Fish Market</gradient>'
|
||||
|
||||
limitation:
|
||||
enable: true
|
||||
earnings: 10000
|
||||
|
||||
# Market menu layout
|
||||
layout:
|
||||
- 'AAAAAAAAA'
|
||||
@@ -25,22 +29,29 @@ item-price:
|
||||
# Slots to put items in
|
||||
item-slot:
|
||||
symbol: 'I'
|
||||
allow-items-with-no-price: true
|
||||
|
||||
# Functional icon
|
||||
functional-icons:
|
||||
symbol: 'B'
|
||||
sell-icon:
|
||||
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}$</green> by selling the fish</gradient></font>'
|
||||
- '<dark_gray>You can earn {rest}'
|
||||
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}$ by selling the fish! You can still get {remains}$ from market today'
|
||||
value: 'You earned {money}$ by selling the fish! You can still get {rest}$ from market today'
|
||||
command_action:
|
||||
type: command
|
||||
value: 'money give {player} {money}'
|
||||
@@ -53,6 +64,25 @@ functional-icons:
|
||||
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:
|
||||
|
||||
Reference in New Issue
Block a user