9
0
mirror of https://github.com/Xiao-MoMi/Custom-Fishing.git synced 2026-01-04 15:41:35 +00:00

checkpoint - 30

This commit is contained in:
XiaoMoMi
2024-07-08 04:46:23 +08:00
parent ddd1417121
commit a3191bc693
34 changed files with 541 additions and 132 deletions

View File

@@ -25,6 +25,9 @@ import net.kyori.adventure.text.Component;
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
import net.momirealms.customfishing.api.mechanic.action.*;
import net.momirealms.customfishing.api.mechanic.context.ContextKeys;
import net.momirealms.customfishing.api.mechanic.effect.Effect;
import net.momirealms.customfishing.api.mechanic.fishing.CustomFishingHook;
import net.momirealms.customfishing.api.mechanic.fishing.FishingGears;
import net.momirealms.customfishing.api.mechanic.misc.placeholder.BukkitPlaceholderManager;
import net.momirealms.customfishing.api.mechanic.misc.value.MathValue;
import net.momirealms.customfishing.api.mechanic.misc.value.TextValue;
@@ -783,7 +786,7 @@ public class BukkitActionManager implements ActionManager<Player> {
return context -> {
if (Math.random() > chance) return;
Player owner = context.getHolder();
Location location = position ? requireNonNull(context.arg(ContextKeys.HOOK_LOCATION)).clone() : owner.getLocation().clone();
Location location = position ? requireNonNull(context.arg(ContextKeys.OTHER_LOCATION)).clone() : owner.getLocation().clone();
location.add(x.evaluate(context), y.evaluate(context) - 1, z.evaluate(context));
if (opposite) location.setYaw(-owner.getLocation().getYaw());
else location.setYaw((float) yaw.evaluate(context));
@@ -832,7 +835,7 @@ public class BukkitActionManager implements ActionManager<Player> {
return context -> {
if (Math.random() > chance) return;
Player owner = context.getHolder();
Location location = position ? requireNonNull(context.arg(ContextKeys.HOOK_LOCATION)).clone() : owner.getLocation().clone();
Location location = position ? requireNonNull(context.arg(ContextKeys.OTHER_LOCATION)).clone() : owner.getLocation().clone();
location.add(x.evaluate(context), y.evaluate(context), z.evaluate(context));
FakeArmorStand armorStand = SparrowHeart.getInstance().createFakeArmorStand(location);
armorStand.invisible(true);
@@ -874,16 +877,27 @@ public class BukkitActionManager implements ActionManager<Player> {
if (Math.random() > chance) return;
String previous = context.arg(ContextKeys.SURROUNDING);
context.arg(ContextKeys.SURROUNDING, surrounding);
Collection<String> loots = plugin.getLootManager().getWeightedLoots(context).keySet();
Collection<String> loots = plugin.getLootManager().getWeightedLoots(Effect.newInstance(), context).keySet();
StringJoiner stringJoiner = new StringJoiner(TranslationManager.miniMessageTranslation(MessageConstants.COMMAND_FISH_FINDER_SPLIT_CHAR.build().key()));
for (String loot : loots) {
stringJoiner.add(loot);
plugin.getLootManager().getLoot(loot).ifPresent(lootIns -> {
System.out.println("loot: " + loot + " : " + lootIns.showInFinder());
if (lootIns.showInFinder()) {
if (!lootIns.nick().equals("UNDEFINED")) {
stringJoiner.add(lootIns.nick());
}
}
});
}
if (previous == null) {
context.remove(ContextKeys.SURROUNDING);
} else {
context.arg(ContextKeys.SURROUNDING, previous);
}
context.arg(ContextKeys.SURROUNDING, previous);
if (loots.isEmpty()) {
plugin.getSenderFactory().wrap(context.getHolder()).sendMessage(TranslationManager.render(MessageConstants.COMMAND_FISH_FINDER_NO_LOOT.build()));
} else {
plugin.getSenderFactory().wrap(context.getHolder()).sendMessage(TranslationManager.render(MessageConstants.COMMAND_FISH_FINDER_POSSIBLE_LOOTS.arguments(Component.text(stringJoiner.toString())).build()));
plugin.getSenderFactory().wrap(context.getHolder()).sendMessage(TranslationManager.render(MessageConstants.COMMAND_FISH_FINDER_POSSIBLE_LOOTS.arguments(AdventureHelper.miniMessage(stringJoiner.toString())).build()));
}
};
});

View File

@@ -59,6 +59,11 @@ public class BukkitBagManager implements BagManager, Listener {
private Action<Player>[] collectLootActions;
private Action<Player>[] bagFullActions;
private boolean bagStoreLoots;
private boolean bagStoreRods;
private boolean bagStoreBaits;
private boolean bagStoreHooks;
private boolean bagStoreUtils;
private final HashSet<MechanicType> storedTypes = new HashSet<>();
private boolean enable;
private String bagTitle;
private List<Material> bagWhiteListItems = new ArrayList<>();
@@ -78,6 +83,7 @@ public class BukkitBagManager implements BagManager, Listener {
@Override
public void unload() {
HandlerList.unregisterAll(this);
storedTypes.clear();
}
@Override
@@ -137,10 +143,20 @@ public class BukkitBagManager implements BagManager, Listener {
enable = config.getBoolean("enable", true);
bagTitle = config.getString("bag-title", "");
bagStoreLoots = config.getBoolean("can-store-loot", false);
bagStoreRods = config.getBoolean("can-store-rod", true);
bagStoreBaits = config.getBoolean("can-store-bait", true);
bagStoreHooks = config.getBoolean("can-store-hook", true);
bagStoreUtils = config.getBoolean("can-store-util", true);
bagWhiteListItems = config.getStringList("whitelist-items").stream().map(it -> Material.valueOf(it.toUpperCase(Locale.ENGLISH))).toList();
collectLootActions = plugin.getActionManager().parseActions(config.getSection("collect-actions"));
bagFullActions = plugin.getActionManager().parseActions(config.getSection("full-actions"));
collectRequirements = plugin.getRequirementManager().parseRequirements(config.getSection("collect-requirements"), false);
if (bagStoreLoots) storedTypes.add(MechanicType.LOOT);
if (bagStoreRods) storedTypes.add(MechanicType.ROD);
if (bagStoreBaits) storedTypes.add(MechanicType.BAIT);
if (bagStoreHooks) storedTypes.add(MechanicType.HOOK);
if (bagStoreUtils) storedTypes.add(MechanicType.UTIL);
}
@Override
@@ -205,15 +221,16 @@ public class BukkitBagManager implements BagManager, Listener {
if (movedItem == null || movedItem.getType() == Material.AIR || bagWhiteListItems.contains(movedItem.getType()))
return;
String id = plugin.getItemManager().getItemID(movedItem);
MechanicType type = MechanicType.getTypeByID(id);
List<MechanicType> type = MechanicType.getTypeByID(id);
if (type == null) {
event.setCancelled(true);
return;
}
if (type == MechanicType.LOOT && bagStoreLoots)
return;
if (type == MechanicType.BAIT || type == MechanicType.ROD || type == MechanicType.UTIL || type == MechanicType.HOOK)
return;
for (MechanicType mechanicType : type) {
if (storedTypes.contains(mechanicType)) {
return;
}
}
event.setCancelled(true);
}

View File

@@ -227,7 +227,7 @@ public class BukkitBlockManager implements BlockManager, Listener {
} else {
blockData = blockProviders.get("vanilla").blockData(context, blockID, config.dataModifier());
}
Location hookLocation = requireNonNull(context.arg(ContextKeys.HOOK_LOCATION));
Location hookLocation = requireNonNull(context.arg(ContextKeys.OTHER_LOCATION));
Location playerLocation = requireNonNull(context.getHolder()).getLocation();
FallingBlock fallingBlock = hookLocation.getWorld().spawn(hookLocation, FallingBlock.class, (fb -> fb.setBlockData(blockData)));
fallingBlock.getPersistentDataContainer().set(

View File

@@ -39,6 +39,7 @@ public class BukkitCommandManager extends AbstractCommandManager<CommandSender>
new SellFishCommand(this),
new GetItemCommand(this),
new GiveItemCommand(this),
new ImportItemCommand(this),
new EndCompetitionCommand(this),
new StopCompetitionCommand(this),
new StartCompetitionCommand(this),

View File

@@ -0,0 +1,86 @@
/*
* 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.bukkit.command.feature;
import dev.dejvokep.boostedyaml.YamlDocument;
import dev.dejvokep.boostedyaml.block.implementation.Section;
import net.kyori.adventure.text.Component;
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
import net.momirealms.customfishing.bukkit.command.BukkitCommandFeature;
import net.momirealms.customfishing.bukkit.util.ItemStackUtils;
import net.momirealms.customfishing.common.command.CustomFishingCommandManager;
import net.momirealms.customfishing.common.locale.MessageConstants;
import org.bukkit.Material;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.incendo.cloud.Command;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.parser.standard.StringParser;
import java.io.File;
import java.io.IOException;
import java.util.Locale;
import java.util.Map;
@SuppressWarnings("DuplicatedCode")
public class ImportItemCommand extends BukkitCommandFeature<CommandSender> {
public ImportItemCommand(CustomFishingCommandManager<CommandSender> commandManager) {
super(commandManager);
}
@Override
public Command.Builder<? extends CommandSender> assembleCommand(CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
return builder
.senderType(Player.class)
.required("id", StringParser.stringParser())
.flag(manager.flagBuilder("silent").withAliases("s").build())
.handler(context -> {
Player player = context.sender();
ItemStack itemStack = player.getInventory().getItemInMainHand();
String id = context.get("id");
if (itemStack.getType() == Material.AIR) {
handleFeedback(context, MessageConstants.COMMAND_ITEM_IMPORT_FAILURE_NO_ITEM);
return;
}
File saved = new File(BukkitCustomFishingPlugin.getInstance().getDataFolder(), "imported_items.yml");
if (!saved.exists()) {
try {
saved.createNewFile();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
YamlDocument document = BukkitCustomFishingPlugin.getInstance().getConfigManager().loadData(saved);
Map<String, Object> map = ItemStackUtils.itemStackToMap(itemStack);
document.set(id, map);
try {
document.save(saved);
handleFeedback(context, MessageConstants.COMMAND_ITEM_IMPORT_SUCCESS, Component.text(id));
} catch (IOException e) {
throw new RuntimeException(e);
}
});
}
@Override
public String getFeatureID() {
return "import_item";
}
}

View File

@@ -17,6 +17,7 @@
package net.momirealms.customfishing.bukkit.config;
import com.saicone.rtag.RtagItem;
import dev.dejvokep.boostedyaml.YamlDocument;
import dev.dejvokep.boostedyaml.block.implementation.Section;
import dev.dejvokep.boostedyaml.dvs.versioning.BasicVersioning;
@@ -35,6 +36,7 @@ import net.momirealms.customfishing.api.mechanic.effect.Effect;
import net.momirealms.customfishing.api.mechanic.effect.EffectProperties;
import net.momirealms.customfishing.api.mechanic.event.EventManager;
import net.momirealms.customfishing.api.mechanic.item.MechanicType;
import net.momirealms.customfishing.api.mechanic.item.tag.TagEditor;
import net.momirealms.customfishing.api.mechanic.loot.Loot;
import net.momirealms.customfishing.api.mechanic.misc.value.MathValue;
import net.momirealms.customfishing.api.mechanic.misc.value.TextValue;
@@ -52,8 +54,10 @@ import net.momirealms.customfishing.api.mechanic.totem.block.type.TypeCondition;
import net.momirealms.customfishing.api.util.OffsetUtils;
import net.momirealms.customfishing.bukkit.totem.particle.DustParticleSetting;
import net.momirealms.customfishing.bukkit.totem.particle.ParticleSetting;
import net.momirealms.customfishing.bukkit.util.ItemStackUtils;
import net.momirealms.customfishing.common.dependency.DependencyProperties;
import net.momirealms.customfishing.common.helper.AdventureHelper;
import net.momirealms.customfishing.common.item.AbstractItem;
import net.momirealms.customfishing.common.item.Item;
import net.momirealms.customfishing.common.util.*;
import org.bukkit.*;
@@ -65,7 +69,9 @@ import org.bukkit.event.EventPriority;
import org.bukkit.inventory.ItemStack;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
@@ -94,9 +100,9 @@ public class BukkitConfigManager extends ConfigManager {
@Override
public void load() {
String configVersion = DependencyProperties.getDependencyVersion("config");
try {
try (InputStream inputStream = new FileInputStream(resolveConfig("config.yml").toFile())) {
MAIN_CONFIG = YamlDocument.create(
resolveConfig("config.yml").toFile(),
inputStream,
plugin.getResourceStream("config.yml"),
GeneralSettings.builder()
.setRouteSeparator('.')
@@ -287,26 +293,6 @@ public class BukkitConfigManager extends ConfigManager {
}
private void registerBuiltInItemProperties() {
Function<Object, BiConsumer<Item<ItemStack>, Context<Player>>> f2 = arg -> {
Section section = (Section) arg;
boolean stored = Objects.equals(section.getNameAsString(), "stored-random-enchantments");
List<Tuple<Double, String, Short>> enchantments = getPossibleEnchantments(section);
return (item, context) -> {
HashSet<String> ids = new HashSet<>();
for (Tuple<Double, String, Short> pair : enchantments) {
if (Math.random() < pair.left() && !ids.contains(pair.mid())) {
if (stored) {
item.addStoredEnchantment(Key.fromString(pair.mid()), pair.right());
} else {
item.addEnchantment(Key.fromString(pair.mid()), pair.right());
}
ids.add(pair.mid());
}
}
};
};
this.registerItemParser(f2, 4850, "random-stored-enchantments");
this.registerItemParser(f2, 4750, "random-enchantments");
Function<Object, BiConsumer<Item<ItemStack>, Context<Player>>> f1 = arg -> {
Section section = (Section) arg;
boolean stored = Objects.equals(section.getNameAsString(), "stored-enchantment-pool");
@@ -365,6 +351,26 @@ public class BukkitConfigManager extends ConfigManager {
};
this.registerItemParser(f1, 4800, "stored-enchantment-pool");
this.registerItemParser(f1, 4700, "enchantment-pool");
Function<Object, BiConsumer<Item<ItemStack>, Context<Player>>> f2 = arg -> {
Section section = (Section) arg;
boolean stored = Objects.equals(section.getNameAsString(), "stored-random-enchantments");
List<Tuple<Double, String, Short>> enchantments = getPossibleEnchantments(section);
return (item, context) -> {
HashSet<String> ids = new HashSet<>();
for (Tuple<Double, String, Short> pair : enchantments) {
if (Math.random() < pair.left() && !ids.contains(pair.mid())) {
if (stored) {
item.addStoredEnchantment(Key.fromString(pair.mid()), pair.right());
} else {
item.addEnchantment(Key.fromString(pair.mid()), pair.right());
}
ids.add(pair.mid());
}
}
};
};
this.registerItemParser(f2, 4850, "random-stored-enchantments");
this.registerItemParser(f2, 4750, "random-enchantments");
this.registerItemParser(arg -> {
Section section = (Section) arg;
Map<Key, Short> map = getEnchantments(section);
@@ -432,6 +438,16 @@ public class BukkitConfigManager extends ConfigManager {
context.arg(ContextKeys.PRICE_FORMATTED, String.format("%.2f", price));
};
}, 1_500, "price");
this.registerItemParser(arg -> {
Section section = (Section) arg;
ArrayList<TagEditor> editors = new ArrayList<>();
ItemStackUtils.sectionToEditor(section, editors);
return (item, context) -> {
for (TagEditor editor : editors) {
editor.apply(((AbstractItem<RtagItem, ItemStack>) item).getRTagItem(), context);
}
};
}, 1_750, "nbt");
}
private void registerBuiltInEffectModifierParser() {

View File

@@ -104,7 +104,7 @@ public class BukkitEntityManager implements EntityManager {
public Entity summonEntityLoot(Context<Player> context) {
String id = context.arg(ContextKeys.ID);
EntityConfig config = requireNonNull(entities.get(id), "Entity " + id + " not found");
Location hookLocation = requireNonNull(context.arg(ContextKeys.HOOK_LOCATION));
Location hookLocation = requireNonNull(context.arg(ContextKeys.OTHER_LOCATION));
Location playerLocation = requireNonNull(context.getHolder().getLocation());
String entityID = config.entityID();
Entity entity;

View File

@@ -20,11 +20,14 @@ package net.momirealms.customfishing.bukkit.event;
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
import net.momirealms.customfishing.api.mechanic.action.ActionTrigger;
import net.momirealms.customfishing.api.mechanic.context.Context;
import net.momirealms.customfishing.api.mechanic.context.ContextKeys;
import net.momirealms.customfishing.api.mechanic.event.EventCarrier;
import net.momirealms.customfishing.api.mechanic.event.EventManager;
import net.momirealms.customfishing.api.mechanic.item.MechanicType;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
@@ -78,14 +81,15 @@ public class BukkitEventManager implements EventManager, Listener {
if (itemStack.getType() == Material.AIR || itemStack.getAmount() == 0)
return;
String id = this.plugin.getItemManager().getItemID(itemStack);
Optional.ofNullable(this.carriers.get(id)).ifPresent(carrier -> {
carrier.trigger(Context.player(event.getPlayer()), ActionTrigger.INTERACT);
});
Context<Player> context = Context.player(event.getPlayer());
Block clicked = event.getClickedBlock();
context.arg(ContextKeys.OTHER_LOCATION, clicked == null ? event.getPlayer().getLocation() : clicked.getLocation());
trigger(context, id, MechanicType.UTIL, ActionTrigger.INTERACT);
}
@EventHandler (ignoreCancelled = true)
public void onConsumeItem(PlayerItemConsumeEvent event) {
Optional.ofNullable(carriers.get(plugin.getItemManager().getItemID(event.getItem())))
.ifPresent(carrier -> carrier.trigger(Context.player(event.getPlayer()), ActionTrigger.CONSUME));
Context<Player> context = Context.player(event.getPlayer());
trigger(context, plugin.getItemManager().getItemID(event.getItem()), MechanicType.LOOT, ActionTrigger.CONSUME);
}
}

View File

@@ -159,18 +159,6 @@ public class BukkitItemManager implements ItemManager, Listener {
return (String) factory.wrap(itemStack).getTag("CustomFishing", "id").orElse(null);
}
@Nullable
@Override
public MechanicType getItemType(@NotNull ItemStack itemStack) {
return MechanicType.getTypeByID(getCustomFishingItemID(itemStack));
}
@Nullable
@Override
public MechanicType getItemType(@NotNull String id) {
return MechanicType.getTypeByID(id);
}
@Nullable
@Override
public org.bukkit.entity.Item dropItemLoot(@NotNull Context<Player> context, ItemStack rod, FishHook hook) {
@@ -188,7 +176,7 @@ public class BukkitItemManager implements ItemManager, Listener {
Player player = context.getHolder();
Location playerLocation = player.getLocation();
Location hookLocation = requireNonNull(context.arg(ContextKeys.HOOK_LOCATION));
Location hookLocation = requireNonNull(context.arg(ContextKeys.OTHER_LOCATION));
double d0 = playerLocation.getX() - hookLocation.getX();
double d1 = playerLocation.getY() - hookLocation.getY();

View File

@@ -129,8 +129,21 @@ public class BukkitLootManager implements LootManager {
}
@Override
public HashMap<String, Double> getWeightedLoots(Context<Player> context) {
return null;
public HashMap<String, Double> getWeightedLoots(Effect effect, Context<Player> context) {
HashMap<String, Double> lootWeightMap = new HashMap<>();
for (ConditionalElement<List<Pair<String, BiFunction<Context<Player>, Double, Double>>>, Player> conditionalElement : lootConditions.values()) {
modifyWeightMap(lootWeightMap, context, conditionalElement);
}
for (Pair<String, BiFunction<Context<Player>, Double, Double>> pair : effect.weightOperations()) {
double previous = lootWeightMap.getOrDefault(pair.left(), 0d);
if (previous > 0)
lootWeightMap.put(pair.left(), pair.right().apply(context, previous));
}
for (Pair<String, BiFunction<Context<Player>, Double, Double>> pair : effect.weightOperationsIgnored()) {
double previous = lootWeightMap.getOrDefault(pair.left(), 0d);
lootWeightMap.put(pair.left(), pair.right().apply(context, previous));
}
return lootWeightMap;
}
@Nullable

View File

@@ -665,7 +665,7 @@ public class BukkitRequirementManager implements RequirementManager<Player> {
registerRequirement("ice-fishing", (args, actions, runActions) -> {
boolean iceFishing = (boolean) args;
return context -> {
Location location = requireNonNull(context.arg(ContextKeys.HOOK_LOCATION));
Location location = requireNonNull(context.arg(ContextKeys.OTHER_LOCATION));
int water = 0, ice = 0;
for (int i = -2; i <= 2; i++)
for (int j = -1; j <= 2; j++)
@@ -727,7 +727,7 @@ public class BukkitRequirementManager implements RequirementManager<Player> {
registerRequirement("biome", (args, actions, runActions) -> {
HashSet<String> biomes = new HashSet<>(ListUtils.toList(args));
return context -> {
Location location = requireNonNull(Optional.ofNullable(context.arg(ContextKeys.HOOK_LOCATION)).orElse(context.arg(ContextKeys.LOCATION)));
Location location = requireNonNull(Optional.ofNullable(context.arg(ContextKeys.OTHER_LOCATION)).orElse(context.arg(ContextKeys.LOCATION)));
String currentBiome = SparrowHeart.getInstance().getBiomeResourceLocation(location);
if (biomes.contains(currentBiome))
return true;
@@ -738,7 +738,7 @@ public class BukkitRequirementManager implements RequirementManager<Player> {
registerRequirement("!biome", (args, actions, runActions) -> {
HashSet<String> biomes = new HashSet<>(ListUtils.toList(args));
return context -> {
Location location = requireNonNull(Optional.ofNullable(context.arg(ContextKeys.HOOK_LOCATION)).orElse(context.arg(ContextKeys.LOCATION)));
Location location = requireNonNull(Optional.ofNullable(context.arg(ContextKeys.OTHER_LOCATION)).orElse(context.arg(ContextKeys.LOCATION)));
String currentBiome = SparrowHeart.getInstance().getBiomeResourceLocation(location);
if (!biomes.contains(currentBiome))
return true;

View File

@@ -17,10 +17,17 @@
package net.momirealms.customfishing.bukkit.util;
import com.saicone.rtag.RtagMirror;
import com.saicone.rtag.item.ItemObject;
import com.saicone.rtag.tag.TagCompound;
import com.saicone.rtag.item.ItemTagStream;
import dev.dejvokep.boostedyaml.block.implementation.Section;
import net.momirealms.customfishing.api.mechanic.item.tag.TagEditor;
import net.momirealms.customfishing.api.mechanic.item.tag.TagListType;
import net.momirealms.customfishing.api.mechanic.item.tag.TagValueType;
import net.momirealms.customfishing.api.mechanic.misc.value.MathValue;
import net.momirealms.customfishing.api.mechanic.misc.value.TextValue;
import net.momirealms.customfishing.common.util.ArrayUtils;
import net.momirealms.customfishing.common.util.Pair;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.io.BukkitObjectInputStream;
import org.bukkit.util.io.BukkitObjectOutputStream;
@@ -29,7 +36,7 @@ import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Map;
import java.util.*;
public class ItemStackUtils {
@@ -69,24 +76,208 @@ public class ItemStackUtils {
}
}
public static Map<String, Object> toReadableMap(ItemStack item) {
return toMap(item);
public static Map<String, Object> itemStackToMap(ItemStack itemStack) {
Map<String, Object> map = ItemTagStream.INSTANCE.toMap(itemStack);
map.remove("rtagDataVersion");
map.remove("count");
map.remove("id");
map.put("material", itemStack.getType().name().toLowerCase(Locale.ENGLISH));
map.put("amount", itemStack.getAmount());
Object tag = map.remove("tags");
if (tag != null) {
map.put("nbt", tag);
}
return map;
}
private static Map<String, Object> toMap(ItemStack object) {
return TagCompound.getValue(RtagMirror.INSTANCE, toCompound(object));
}
private static Object toCompound(ItemStack object) {
if (object == null) {
return null;
} else {
Object compound = extract(object);
return TagCompound.isTagCompound(compound) ? compound : null;
// TODO Improve the map parser and refactor this method to make it more readable
public static void sectionToEditor(Section section, List<TagEditor> tagEditors, String... route) {
for (Map.Entry<String, Object> entry : section.getStringRouteMappedValues(false).entrySet()) {
Object value = entry.getValue();
String key = entry.getKey();
String[] currentRoute = ArrayUtils.appendElementToArray(route, key);
if (value instanceof Section inner) {
sectionToEditor(inner, tagEditors, currentRoute);
} else if (value instanceof List<?> list) {
TagListType type = getListType(list);
if (type == TagListType.TAG) {
// List<TagMap> maps = new ArrayList<>();
// for (Object o : list) {
// Map<String, Object> map = (Map<String, Object>) o;
//
// }
tagEditors.add(((item, context) -> {
// List<Map<String, Object>> parsed = maps.stream().map(render -> render.apply(context)).toList();
item.set(list, (Object[]) currentRoute);
}));
} else {
Object first = list.get(0);
if (first instanceof String str) {
Pair<TagValueType, String> pair = toTypeAndData(str);
switch (pair.left()) {
case INT -> {
List<MathValue<Player>> values = new ArrayList<>();
for (Object o : list) {
values.add(MathValue.auto(toTypeAndData((String) o).right()));
}
tagEditors.add(((item, context) -> {
List<Integer> integers = values.stream().map(unparsed -> (int) unparsed.evaluate(context)).toList();
item.set(integers, (Object[]) currentRoute);
}));
}
case BYTE -> {
List<MathValue<Player>> values = new ArrayList<>();
for (Object o : list) {
values.add(MathValue.auto(toTypeAndData((String) o).right()));
}
tagEditors.add(((item, context) -> {
List<Byte> bytes = values.stream().map(unparsed -> (byte) unparsed.evaluate(context)).toList();
item.set(bytes, (Object[]) currentRoute);
}));
}
case LONG -> {
List<MathValue<Player>> values = new ArrayList<>();
for (Object o : list) {
values.add(MathValue.auto(toTypeAndData((String) o).right()));
}
tagEditors.add(((item, context) -> {
List<Long> longs = values.stream().map(unparsed -> (long) unparsed.evaluate(context)).toList();
item.set(longs, (Object[]) currentRoute);
}));
}
case FLOAT -> {
List<MathValue<Player>> values = new ArrayList<>();
for (Object o : list) {
values.add(MathValue.auto(toTypeAndData((String) o).right()));
}
tagEditors.add(((item, context) -> {
List<Float> floats = values.stream().map(unparsed -> (float) unparsed.evaluate(context)).toList();
item.set(floats, (Object[]) currentRoute);
}));
}
case DOUBLE -> {
List<MathValue<Player>> values = new ArrayList<>();
for (Object o : list) {
values.add(MathValue.auto(toTypeAndData((String) o).right()));
}
tagEditors.add(((item, context) -> {
List<Double> doubles = values.stream().map(unparsed -> (double) unparsed.evaluate(context)).toList();
item.set(doubles, (Object[]) currentRoute);
}));
}
case STRING -> {
List<TextValue<Player>> values = new ArrayList<>();
for (Object o : list) {
values.add(TextValue.auto(toTypeAndData((String) o).right()));
}
tagEditors.add(((item, context) -> {
List<String> texts = values.stream().map(unparsed -> unparsed.render(context)).toList();
item.set(texts, (Object[]) currentRoute);
}));
}
}
} else {
tagEditors.add(((item, context) -> {
item.set(list, (Object[]) currentRoute);
}));
}
}
} else if (value instanceof String str) {
Pair<TagValueType, String> pair = toTypeAndData(str);
switch (pair.left()) {
case INT -> {
MathValue<Player> mathValue = MathValue.auto(pair.right());
tagEditors.add(((item, context) -> {
item.set((int) mathValue.evaluate(context), (Object[]) currentRoute);
}));
}
case BYTE -> {
MathValue<Player> mathValue = MathValue.auto(pair.right());
tagEditors.add(((item, context) -> {
item.set((byte) mathValue.evaluate(context), (Object[]) currentRoute);
}));
}
case LONG -> {
MathValue<Player> mathValue = MathValue.auto(pair.right());
tagEditors.add(((item, context) -> {
item.set((long) mathValue.evaluate(context), (Object[]) currentRoute);
}));
}
case SHORT -> {
MathValue<Player> mathValue = MathValue.auto(pair.right());
tagEditors.add(((item, context) -> {
item.set((short) mathValue.evaluate(context), (Object[]) currentRoute);
}));
}
case DOUBLE -> {
MathValue<Player> mathValue = MathValue.auto(pair.right());
tagEditors.add(((item, context) -> {
item.set((double) mathValue.evaluate(context), (Object[]) currentRoute);
}));
}
case FLOAT -> {
MathValue<Player> mathValue = MathValue.auto(pair.right());
tagEditors.add(((item, context) -> {
item.set((float) mathValue.evaluate(context), (Object[]) currentRoute);
}));
}
case STRING -> {
TextValue<Player> textValue = TextValue.auto(pair.right());
tagEditors.add(((item, context) -> {
item.set(textValue.render(context), (Object[]) currentRoute);
}));
}
case INTARRAY -> {
String[] split = splitValue(str);
int[] array = Arrays.stream(split).mapToInt(Integer::parseInt).toArray();
tagEditors.add(((item, context) -> {
item.set(array, (Object[]) currentRoute);
}));
}
case BYTEARRAY -> {
String[] split = splitValue(str);
byte[] bytes = new byte[split.length];
for (int i = 0; i < split.length; i++){
bytes[i] = Byte.parseByte(split[i]);
}
tagEditors.add(((item, context) -> {
item.set(bytes, (Object[]) currentRoute);
}));
}
}
} else {
tagEditors.add(((item, context) -> {
item.set(value, (Object[]) currentRoute);
}));
}
}
}
private static Object extract(ItemStack object) {
return ItemObject.save(ItemObject.asNMSCopy(object));
private static TagListType getListType(List<?> list) {
Object o = list.get(0);
if (o instanceof Map<?, ?> map) {
return TagListType.TAG;
} else {
return TagListType.VALUE;
}
}
public static Pair<TagValueType, String> toTypeAndData(String str) {
String[] parts = str.split("\\s+", 2);
if (parts.length == 1) {
return Pair.of(TagValueType.STRING, parts[0]);
}
if (parts.length != 2) {
throw new IllegalArgumentException("Invalid value format: " + str);
}
TagValueType type = TagValueType.valueOf(parts[0].substring(1, parts[0].length() - 1).toUpperCase(Locale.ENGLISH));
String data = parts[1];
return Pair.of(type, data);
}
private static String[] splitValue(String value) {
return value.substring(value.indexOf('[') + 1, value.lastIndexOf(']'))
.replaceAll("\\s", "")
.split(",");
}
}

View File

@@ -159,8 +159,12 @@ mechanics:
# Other whitelist-items
whitelist-items:
- fishing_rod
# Can fishing bag store fishing loots?
# Decide the items that can be stored in bag
can-store-loot: false
can-store-rod: true
can-store-bait: true
can-store-hook: true
can-store-util: true
# Requirements for automatically collecting
collect-requirements:
permission: fishingbag.collectloot

View File

@@ -42,6 +42,8 @@ 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>"
command.item.get.success: "<white>Successfully got <arg:0>x <arg:1>.</white>"
command.item.import.failure.no_item: "<red>You can't import air</red>"
command.item.import.success: "<white>Item [<arg:0>] has been saved to /plugins/CustomFishing/imported_items.yml</white>"
command.fish_finder.possible_loots: "<white>Possible loots here: <arg:0></white>"
command.fish_finder.no_loot: "<white>No loot found here</white>"
command.fish_finder.split_char: ", "