mirror of
https://github.com/Xiao-MoMi/Custom-Fishing.git
synced 2025-12-26 18:39:11 +00:00
checkpoint - 10
This commit is contained in:
@@ -47,6 +47,8 @@ dependencies {
|
||||
compileOnly("org.incendo:cloud-core:${rootProject.properties["cloud_core_version"]}")
|
||||
compileOnly("org.incendo:cloud-minecraft-extras:${rootProject.properties["cloud_minecraft_extras_version"]}")
|
||||
compileOnly("org.incendo:cloud-paper:${rootProject.properties["cloud_paper_version"]}")
|
||||
// expression
|
||||
compileOnly("net.objecthunter:exp4j:${rootProject.properties["exp4j_version"]}")
|
||||
}
|
||||
|
||||
tasks {
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
package net.momirealms.customfishing.bukkit;
|
||||
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import net.momirealms.customfishing.api.mechanic.config.ConfigManager;
|
||||
import net.momirealms.customfishing.api.mechanic.misc.cooldown.CoolDownManager;
|
||||
import net.momirealms.customfishing.api.mechanic.misc.placeholder.BukkitPlaceholderManager;
|
||||
import net.momirealms.customfishing.bukkit.action.BukkitActionManager;
|
||||
import net.momirealms.customfishing.bukkit.bag.BukkitBagManager;
|
||||
import net.momirealms.customfishing.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.customfishing.bukkit.competition.BukkitCompetitionManager;
|
||||
import net.momirealms.customfishing.bukkit.config.BukkitConfigManager;
|
||||
import net.momirealms.customfishing.bukkit.effect.BukkitEffectManager;
|
||||
import net.momirealms.customfishing.bukkit.entity.BukkitEntityManager;
|
||||
import net.momirealms.customfishing.bukkit.event.BukkitEventManager;
|
||||
import net.momirealms.customfishing.bukkit.hook.BukkitHookManager;
|
||||
import net.momirealms.customfishing.bukkit.integration.BukkitIntegrationManager;
|
||||
import net.momirealms.customfishing.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.customfishing.bukkit.loot.BukkitLootManager;
|
||||
import net.momirealms.customfishing.bukkit.market.BukkitMarketManager;
|
||||
import net.momirealms.customfishing.bukkit.requirement.BukkitRequirementManager;
|
||||
import net.momirealms.customfishing.bukkit.sender.BukkitSenderFactory;
|
||||
import net.momirealms.customfishing.bukkit.statistic.BukkitStatisticsManager;
|
||||
import net.momirealms.customfishing.bukkit.storage.BukkitStorageManager;
|
||||
import net.momirealms.customfishing.common.dependency.Dependency;
|
||||
import net.momirealms.customfishing.common.dependency.DependencyManagerImpl;
|
||||
import net.momirealms.customfishing.common.helper.VersionHelper;
|
||||
import net.momirealms.customfishing.common.locale.TranslationManager;
|
||||
import net.momirealms.customfishing.common.plugin.classpath.ClassPathAppender;
|
||||
import net.momirealms.customfishing.common.plugin.classpath.ReflectionClassPathAppender;
|
||||
import net.momirealms.customfishing.common.plugin.logging.JavaPluginLogger;
|
||||
import net.momirealms.customfishing.common.plugin.logging.PluginLogger;
|
||||
import org.bstats.bukkit.Metrics;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
public class BukkitCustomFishingPluginImpl extends BukkitCustomFishingPlugin {
|
||||
|
||||
private final ClassPathAppender classPathAppender;
|
||||
private final PluginLogger logger;
|
||||
|
||||
public BukkitCustomFishingPluginImpl(Plugin boostrap) {
|
||||
super(boostrap);
|
||||
VersionHelper.init(getServerVersion());
|
||||
this.classPathAppender = new ReflectionClassPathAppender(this);
|
||||
this.logger = new JavaPluginLogger(getBoostrap().getLogger());
|
||||
this.eventManager = new BukkitEventManager(this);
|
||||
this.configManager = new BukkitConfigManager(this);
|
||||
this.requirementManager = new BukkitRequirementManager(this);
|
||||
this.actionManager = new BukkitActionManager(this);
|
||||
this.senderFactory = new BukkitSenderFactory(this);
|
||||
this.placeholderManager = new BukkitPlaceholderManager(this);
|
||||
this.itemManager = new BukkitItemManager(this);
|
||||
this.integrationManager = new BukkitIntegrationManager(this);
|
||||
this.competitionManager = new BukkitCompetitionManager(this);
|
||||
this.marketManager = new BukkitMarketManager(this);
|
||||
this.storageManager = new BukkitStorageManager(this);
|
||||
this.lootManager = new BukkitLootManager(this);
|
||||
this.coolDownManager = new CoolDownManager(this);
|
||||
this.entityManager = new BukkitEntityManager(this);
|
||||
this.blockManager = new BukkitBlockManager(this);
|
||||
this.statisticsManager = new BukkitStatisticsManager(this);
|
||||
this.effectManager = new BukkitEffectManager(this);
|
||||
this.hookManager = new BukkitHookManager(this);
|
||||
this.bagManager = new BukkitBagManager(this);
|
||||
this.dependencyManager = new DependencyManagerImpl(this);
|
||||
this.translationManager = new TranslationManager(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
this.dependencyManager.loadDependencies(
|
||||
List.of(Dependency.BOOSTED_YAML,
|
||||
Dependency.BSTATS_BASE,
|
||||
Dependency.BSTATS_BUKKIT,
|
||||
Dependency.CAFFEINE,
|
||||
Dependency.CLOUD_CORE,
|
||||
Dependency.CLOUD_SERVICES,
|
||||
Dependency.CLOUD_BUKKIT,
|
||||
Dependency.CLOUD_PAPER,
|
||||
Dependency.CLOUD_BRIGADIER,
|
||||
Dependency.CLOUD_MINECRAFT_EXTRAS,
|
||||
Dependency.GSON,
|
||||
Dependency.COMMONS_POOL_2,
|
||||
Dependency.JEDIS,
|
||||
Dependency.EXP4J,
|
||||
Dependency.MYSQL_DRIVER,
|
||||
Dependency.MARIADB_DRIVER,
|
||||
Dependency.SQLITE_DRIVER,
|
||||
Dependency.H2_DRIVER,
|
||||
Dependency.MONGODB_DRIVER_CORE,
|
||||
Dependency.MONGODB_DRIVER_SYNC,
|
||||
Dependency.MONGODB_DRIVER_BSON,
|
||||
Dependency.HIKARI_CP)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
this.reload();
|
||||
if (ConfigManager.metrics()) new Metrics((JavaPlugin) getBoostrap(), 16648);
|
||||
if (ConfigManager.checkUpdate()) {
|
||||
VersionHelper.UPDATE_CHECKER.apply(this).thenAccept(result -> {
|
||||
if (!result) this.getPluginLogger().info("You are using the latest version.");
|
||||
else this.getPluginLogger().warn("Update is available: https://polymart.org/resource/2723");
|
||||
});
|
||||
}
|
||||
this.integrationManager.load();
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
this.eventManager.reload();
|
||||
this.configManager.reload();
|
||||
this.requirementManager.reload();
|
||||
this.actionManager.reload();
|
||||
this.placeholderManager.reload();
|
||||
this.itemManager.reload();
|
||||
this.competitionManager.reload();
|
||||
this.marketManager.reload();
|
||||
this.storageManager.reload();
|
||||
this.lootManager.reload();
|
||||
this.coolDownManager.reload();
|
||||
this.entityManager.reload();
|
||||
this.blockManager.reload();
|
||||
this.statisticsManager.reload();
|
||||
this.effectManager.reload();
|
||||
this.hookManager.reload();
|
||||
this.bagManager.reload();
|
||||
this.translationManager.reload();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
this.eventManager.disable();
|
||||
this.configManager.disable();
|
||||
this.requirementManager.disable();
|
||||
this.actionManager.disable();
|
||||
this.placeholderManager.disable();
|
||||
this.itemManager.disable();
|
||||
this.competitionManager.disable();
|
||||
this.marketManager.disable();
|
||||
this.storageManager.disable();
|
||||
this.lootManager.disable();
|
||||
this.coolDownManager.disable();
|
||||
this.entityManager.disable();
|
||||
this.blockManager.disable();
|
||||
this.statisticsManager.disable();
|
||||
this.effectManager.disable();
|
||||
this.hookManager.disable();
|
||||
this.bagManager.disable();
|
||||
this.integrationManager.disable();
|
||||
this.initialized = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getResourceStream(String filePath) {
|
||||
return getBoostrap().getResource(filePath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginLogger getPluginLogger() {
|
||||
return logger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassPathAppender getClassPathAppender() {
|
||||
return classPathAppender;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getDataDirectory() {
|
||||
return getBoostrap().getDataFolder().toPath().toAbsolutePath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerVersion() {
|
||||
return Bukkit.getServer().getBukkitVersion().split("-")[0];
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public String getPluginVersion() {
|
||||
return getBoostrap().getDescription().getVersion();
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,6 @@ import net.momirealms.customfishing.api.mechanic.misc.value.MathValue;
|
||||
import net.momirealms.customfishing.api.mechanic.misc.value.TextValue;
|
||||
import net.momirealms.customfishing.api.mechanic.requirement.Requirement;
|
||||
import net.momirealms.customfishing.bukkit.integration.VaultHook;
|
||||
import net.momirealms.customfishing.bukkit.util.ItemUtils;
|
||||
import net.momirealms.customfishing.bukkit.util.LocationUtils;
|
||||
import net.momirealms.customfishing.bukkit.util.PlayerUtils;
|
||||
import net.momirealms.customfishing.common.helper.AdventureHelper;
|
||||
@@ -52,6 +51,16 @@ public class BukkitActionManager implements ActionManager<Player> {
|
||||
public BukkitActionManager(BukkitCustomFishingPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.registerBuiltInActions();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
this.actionFactoryMap.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
this.loadExpansions();
|
||||
}
|
||||
|
||||
@@ -393,11 +402,11 @@ public class BukkitActionManager implements ActionManager<Player> {
|
||||
if (Math.random() > chance) return;
|
||||
Player player = context.getHolder();
|
||||
ItemStack itemStack = player.getInventory().getItem(slot);
|
||||
if (amount > 0) {
|
||||
ItemUtils.increaseDurability(itemStack, amount, true);
|
||||
} else {
|
||||
ItemUtils.decreaseDurability(context.getHolder(), itemStack, -amount, true);
|
||||
}
|
||||
// if (amount > 0) {
|
||||
// ItemUtils.increaseDurability(itemStack, amount, true);
|
||||
// } else {
|
||||
// ItemUtils.decreaseDurability(context.getHolder(), itemStack, -amount, true);
|
||||
// }
|
||||
};
|
||||
} else {
|
||||
plugin.getPluginLogger().warn("Invalid value type: " + args.getClass().getSimpleName() + " found at durability action which should be Section");
|
||||
|
||||
@@ -65,7 +65,7 @@ public class BukkitBlockManager implements BlockManager, Listener {
|
||||
private final HashMap<String, BlockStateModifierFactory> stateFactories = new HashMap<>();
|
||||
private BlockProvider[] blockDetectArray;
|
||||
|
||||
public BukkitBlockManager(BukkitCustomFishingPluginImpl plugin) {
|
||||
public BukkitBlockManager(BukkitCustomFishingPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.registerInbuiltProperties();
|
||||
this.registerBlockProvider(new BlockProvider() {
|
||||
@@ -88,13 +88,6 @@ public class BukkitBlockManager implements BlockManager, Listener {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerBlock(@NotNull String id, @NotNull BlockConfig block) {
|
||||
if (blocks.containsKey(id)) return false;
|
||||
blocks.put(id, block);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin.getBoostrap());
|
||||
@@ -122,6 +115,13 @@ public class BukkitBlockManager implements BlockManager, Listener {
|
||||
this.blockDetectArray = list.toArray(new BlockProvider[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerBlock(@NotNull BlockConfig block) {
|
||||
if (blocks.containsKey(block.id())) return false;
|
||||
blocks.put(block.id(), block);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Event handler for the EntityChangeBlockEvent.
|
||||
* This method is triggered when an entity changes a block, typically when a block falls or lands.
|
||||
@@ -230,8 +230,8 @@ public class BukkitBlockManager implements BlockManager, Listener {
|
||||
PersistentDataType.STRING,
|
||||
id + ";" + context.getHolder().getName()
|
||||
);
|
||||
Vector vector = playerLocation.subtract(hookLocation).toVector().multiply((config.horizontalVector().evaluate(context)) - 1);
|
||||
vector = vector.setY((vector.getY() + 0.2) * config.verticalVector().evaluate(context));
|
||||
Vector vector = playerLocation.subtract(hookLocation).toVector().multiply(1.2 - 1);
|
||||
vector = vector.setY((vector.getY() + 0.2) * 1.2);
|
||||
fallingBlock.setVelocity(vector);
|
||||
return fallingBlock;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ public class ReloadCommand extends BukkitCommandFeature<CommandSender> {
|
||||
.flag(manager.flagBuilder("silent"))
|
||||
.handler(context -> {
|
||||
BukkitCustomFishingPlugin.getInstance().reload();
|
||||
handleFeedback(context.sender(), MessageConstants.COMMAND_RELOAD);
|
||||
handleFeedback(context.sender(), MessageConstants.COMMAND_RELOAD_SUCCESS);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -27,9 +27,9 @@ import java.util.*;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public class BukkitConfigLoader extends ConfigManager {
|
||||
public class BukkitConfigManager extends ConfigManager {
|
||||
|
||||
public BukkitConfigLoader(BukkitCustomFishingPlugin plugin) {
|
||||
public BukkitConfigManager(BukkitCustomFishingPlugin plugin) {
|
||||
super(plugin);
|
||||
this.registerBuiltInItemProperties();
|
||||
this.registerBuiltInBaseEffectParser();
|
||||
@@ -438,4 +438,11 @@ public class BukkitConfigLoader extends ConfigManager {
|
||||
return builder -> builder.statisticsKeys(keys);
|
||||
}, "statistics");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveResource(String filePath) {
|
||||
if (!new File(plugin.getDataFolder(), filePath).exists()) {
|
||||
plugin.getBoostrap().saveResource(filePath, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,9 +76,9 @@ public class BukkitEntityManager implements EntityManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerEntity(String id, EntityConfig entity) {
|
||||
if (entities.containsKey(id)) return false;
|
||||
this.entities.put(id, entity);
|
||||
public boolean registerEntity(EntityConfig entity) {
|
||||
if (entities.containsKey(entity.id())) return false;
|
||||
this.entities.put(entity.id(), entity);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -99,17 +99,17 @@ public class BukkitEntityManager implements EntityManager {
|
||||
EntityConfig config = requireNonNull(entities.get(id), "Entity " + id + " not found");
|
||||
Location hookLocation = requireNonNull(context.arg(ContextKeys.HOOK_LOCATION));
|
||||
Location playerLocation = requireNonNull(context.getHolder().getLocation());
|
||||
String entityID = config.getEntityID();
|
||||
String entityID = config.entityID();
|
||||
Entity entity;
|
||||
if (entityID.contains(":")) {
|
||||
String[] split = entityID.split(":", 2);
|
||||
EntityProvider provider = requireNonNull(entityProviders.get(split[0]), "EntityProvider " + split[0] + " doesn't exist");
|
||||
entity = requireNonNull(provider.spawn(hookLocation, split[1], config.getPropertyMap()), "Entity " + entityID + " doesn't exist");
|
||||
entity = requireNonNull(provider.spawn(hookLocation, split[1], config.propertyMap()), "Entity " + entityID + " doesn't exist");
|
||||
} else {
|
||||
entity = entityProviders.get("vanilla").spawn(hookLocation, entityID, config.getPropertyMap());
|
||||
entity = entityProviders.get("vanilla").spawn(hookLocation, entityID, config.propertyMap());
|
||||
}
|
||||
Vector vector = playerLocation.subtract(hookLocation).toVector().multiply((config.getHorizontalVector()) - 1);
|
||||
vector = vector.setY((vector.getY() + 0.2) * config.getVerticalVector());
|
||||
Vector vector = playerLocation.subtract(hookLocation).toVector().multiply(config.horizontalVector().evaluate(context) - 1);
|
||||
vector = vector.setY((vector.getY() + 0.2) * config.verticalVector().evaluate(context));
|
||||
entity.setVelocity(vector);
|
||||
return entity;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,9 @@ package net.momirealms.customfishing.bukkit.gui.icon;
|
||||
import net.momirealms.customfishing.bukkit.adventure.ShadedAdventureComponentWrapper;
|
||||
import net.momirealms.customfishing.bukkit.gui.Icon;
|
||||
import net.momirealms.customfishing.bukkit.gui.page.file.FileSelector;
|
||||
import net.momirealms.customfishing.common.helper.AdventureHelper;
|
||||
import net.momirealms.customfishing.common.locale.MessageConstants;
|
||||
import net.momirealms.customfishing.common.locale.TranslationManager;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
@@ -44,10 +47,8 @@ public class BackToFolderItem extends AbstractItem implements Icon {
|
||||
public ItemProvider getItemProvider() {
|
||||
if (file != null && (file.getPath().startsWith("plugins\\CustomFishing\\contents") || file.getPath().startsWith("plugins/CustomFishing/contents"))) {
|
||||
return new ItemBuilder(Material.ORANGE_STAINED_GLASS_PANE)
|
||||
.setDisplayName(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
CFLocale.GUI_BACK_TO_PARENT_FOLDER
|
||||
)))
|
||||
.setLore(List.of(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
.setDisplayName(new ShadedAdventureComponentWrapper(TranslationManager.render(MessageConstants.GUI_BACK_TO_PARENT_FOLDER.build())))
|
||||
.setLore(List.of(new ShadedAdventureComponentWrapper(AdventureHelper.miniMessage(
|
||||
"<#FFA500>-> " + file.getName()
|
||||
))));
|
||||
} else {
|
||||
|
||||
@@ -19,6 +19,8 @@ package net.momirealms.customfishing.bukkit.gui.icon;
|
||||
|
||||
import net.momirealms.customfishing.bukkit.adventure.ShadedAdventureComponentWrapper;
|
||||
import net.momirealms.customfishing.bukkit.gui.ParentPage;
|
||||
import net.momirealms.customfishing.common.locale.MessageConstants;
|
||||
import net.momirealms.customfishing.common.locale.TranslationManager;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
@@ -39,9 +41,7 @@ public class BackToPageItem extends AbstractItem {
|
||||
@Override
|
||||
public ItemProvider getItemProvider() {
|
||||
return new ItemBuilder(Material.ORANGE_STAINED_GLASS_PANE)
|
||||
.setDisplayName(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
CFLocale.GUI_BACK_TO_PARENT_PAGE
|
||||
)));
|
||||
.setDisplayName(new ShadedAdventureComponentWrapper(TranslationManager.render(MessageConstants.GUI_BACK_TO_PARENT_PAGE.build())));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -17,8 +17,11 @@
|
||||
|
||||
package net.momirealms.customfishing.bukkit.gui.icon;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.customfishing.bukkit.adventure.ShadedAdventureComponentWrapper;
|
||||
import net.momirealms.customfishing.bukkit.gui.Icon;
|
||||
import net.momirealms.customfishing.common.locale.MessageConstants;
|
||||
import net.momirealms.customfishing.common.locale.TranslationManager;
|
||||
import org.bukkit.Material;
|
||||
import xyz.xenondevs.invui.gui.PagedGui;
|
||||
import xyz.xenondevs.invui.item.ItemProvider;
|
||||
@@ -34,15 +37,13 @@ public class NextPageItem extends PageItem implements Icon {
|
||||
@Override
|
||||
public ItemProvider getItemProvider(PagedGui<?> gui) {
|
||||
ItemBuilder builder = new ItemBuilder(Material.GREEN_STAINED_GLASS_PANE);
|
||||
builder.setDisplayName(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
CFLocale.GUI_NEXT_PAGE
|
||||
)))
|
||||
.addLoreLines(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
gui.hasNextPage()
|
||||
? CFLocale.GUI_GOTO_NEXT_PAGE
|
||||
.replace("{0}", String.valueOf(gui.getCurrentPage() + 2))
|
||||
.replace("{1}", String.valueOf(gui.getPageAmount()))
|
||||
: CFLocale.GUI_CANNOT_GOTO_NEXT_PAGE
|
||||
builder.setDisplayName(new ShadedAdventureComponentWrapper(TranslationManager.render(MessageConstants.GUI_NEXT_PAGE.build())))
|
||||
.addLoreLines(new ShadedAdventureComponentWrapper(TranslationManager.render( gui.hasNextPage()
|
||||
? MessageConstants.GUI_GOTO_NEXT_PAGE.arguments(
|
||||
Component.text(gui.getCurrentPage() + 2),
|
||||
Component.text(gui.getPageAmount())
|
||||
).build() :
|
||||
MessageConstants.GUI_CANNOT_GOTO_NEXT_PAGE.build()
|
||||
)));
|
||||
return builder;
|
||||
}
|
||||
|
||||
@@ -17,8 +17,11 @@
|
||||
|
||||
package net.momirealms.customfishing.bukkit.gui.icon;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.customfishing.bukkit.adventure.ShadedAdventureComponentWrapper;
|
||||
import net.momirealms.customfishing.bukkit.gui.Icon;
|
||||
import net.momirealms.customfishing.common.locale.MessageConstants;
|
||||
import net.momirealms.customfishing.common.locale.TranslationManager;
|
||||
import org.bukkit.Material;
|
||||
import xyz.xenondevs.invui.gui.PagedGui;
|
||||
import xyz.xenondevs.invui.item.ItemProvider;
|
||||
@@ -34,16 +37,13 @@ public class PreviousPageItem extends PageItem implements Icon {
|
||||
@Override
|
||||
public ItemProvider getItemProvider(PagedGui<?> gui) {
|
||||
ItemBuilder builder = new ItemBuilder(Material.RED_STAINED_GLASS_PANE);
|
||||
builder.setDisplayName(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
CFLocale.GUI_PREVIOUS_PAGE
|
||||
)))
|
||||
.addLoreLines(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
gui.hasPreviousPage()
|
||||
? CFLocale.GUI_GOTO_PREVIOUS_PAGE
|
||||
.replace("{0}", String.valueOf(gui.getCurrentPage()))
|
||||
.replace("{1}", String.valueOf(gui.getPageAmount()))
|
||||
: CFLocale.GUI_CANNOT_GOTO_PREVIOUS_PAGE
|
||||
)));
|
||||
builder.setDisplayName(new ShadedAdventureComponentWrapper(TranslationManager.render(MessageConstants.GUI_PREVIOUS_PAGE.build())))
|
||||
.addLoreLines(new ShadedAdventureComponentWrapper(TranslationManager.render( gui.hasPreviousPage()
|
||||
? MessageConstants.GUI_GOTO_PREVIOUS_PAGE.arguments(
|
||||
Component.text(gui.getCurrentPage()),
|
||||
Component.text(gui.getPageAmount())
|
||||
).build()
|
||||
: MessageConstants.GUI_CANNOT_GOTO_PREVIOUS_PAGE.build())));
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,9 +17,12 @@
|
||||
|
||||
package net.momirealms.customfishing.bukkit.gui.icon.property.item;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.customfishing.bukkit.adventure.ShadedAdventureComponentWrapper;
|
||||
import net.momirealms.customfishing.bukkit.gui.SectionPage;
|
||||
import net.momirealms.customfishing.bukkit.gui.page.property.AmountEditor;
|
||||
import net.momirealms.customfishing.common.locale.MessageConstants;
|
||||
import net.momirealms.customfishing.common.locale.TranslationManager;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
@@ -40,24 +43,19 @@ public class AmountItem extends AbstractItem {
|
||||
@Override
|
||||
public ItemProvider getItemProvider() {
|
||||
ItemBuilder itemBuilder = new ItemBuilder(Material.IRON_NUGGET)
|
||||
.setDisplayName(new ShadedAdventureComponentWrapper(AdventureHelper.getComponentFromMiniMessage(
|
||||
CFLocale.GUI_ITEM_AMOUNT
|
||||
)))
|
||||
.setDisplayName(new ShadedAdventureComponentWrapper(TranslationManager.render(MessageConstants.GUI_ITEM_AMOUNT.build())))
|
||||
.setAmount(itemPage.getSection().getInt("amount", 1));
|
||||
if (itemPage.getSection().contains("amount")) {
|
||||
itemBuilder.addLoreLines(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
CFLocale.GUI_CURRENT_VALUE + itemPage.getSection().getInt("amount")
|
||||
itemBuilder.addLoreLines(new ShadedAdventureComponentWrapper(TranslationManager.render(
|
||||
MessageConstants.GUI_CURRENT_VALUE.arguments(
|
||||
Component.text(itemPage.getSection().getInt("amount"))
|
||||
).build()
|
||||
)))
|
||||
.addLoreLines("");
|
||||
itemBuilder.addLoreLines(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
CFLocale.GUI_LEFT_CLICK_EDIT
|
||||
))).addLoreLines(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
CFLocale.GUI_RIGHT_CLICK_RESET
|
||||
)));
|
||||
itemBuilder.addLoreLines(new ShadedAdventureComponentWrapper(TranslationManager.render(MessageConstants.GUI_LEFT_CLICK_EDIT.build())))
|
||||
.addLoreLines(new ShadedAdventureComponentWrapper(TranslationManager.render(MessageConstants.GUI_RIGHT_CLICK_RESET.build())));
|
||||
} else {
|
||||
itemBuilder.addLoreLines(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
CFLocale.GUI_LEFT_CLICK_EDIT
|
||||
)));
|
||||
itemBuilder.addLoreLines(new ShadedAdventureComponentWrapper(TranslationManager.render(MessageConstants.GUI_LEFT_CLICK_EDIT.build())));
|
||||
}
|
||||
return itemBuilder;
|
||||
}
|
||||
|
||||
@@ -17,9 +17,12 @@
|
||||
|
||||
package net.momirealms.customfishing.bukkit.gui.icon.property.item;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.customfishing.bukkit.adventure.ShadedAdventureComponentWrapper;
|
||||
import net.momirealms.customfishing.bukkit.gui.SectionPage;
|
||||
import net.momirealms.customfishing.bukkit.gui.page.property.CustomModelDataEditor;
|
||||
import net.momirealms.customfishing.common.locale.MessageConstants;
|
||||
import net.momirealms.customfishing.common.locale.TranslationManager;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
@@ -40,23 +43,20 @@ public class CMDItem extends AbstractItem {
|
||||
@Override
|
||||
public ItemProvider getItemProvider() {
|
||||
ItemBuilder itemBuilder = new ItemBuilder(Material.GLOW_INK_SAC)
|
||||
.setDisplayName(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
CFLocale.GUI_ITEM_MODEL_DATA
|
||||
.setDisplayName(new ShadedAdventureComponentWrapper(TranslationManager.render(
|
||||
MessageConstants.GUI_ITEM_CUSTOM_MODEL_DATA.build()
|
||||
)));
|
||||
if (itemPage.getSection().contains("custom-model-data")) {
|
||||
itemBuilder.addLoreLines(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
CFLocale.GUI_CURRENT_VALUE + itemPage.getSection().getInt("custom-model-data")
|
||||
itemBuilder.addLoreLines(new ShadedAdventureComponentWrapper(TranslationManager.render(
|
||||
MessageConstants.GUI_CURRENT_VALUE.arguments(
|
||||
Component.text(itemPage.getSection().getInt("custom-model-data"))
|
||||
).build()
|
||||
)))
|
||||
.addLoreLines("");
|
||||
itemBuilder.addLoreLines(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
CFLocale.GUI_LEFT_CLICK_EDIT
|
||||
))).addLoreLines(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
CFLocale.GUI_RIGHT_CLICK_RESET
|
||||
)));
|
||||
itemBuilder.addLoreLines(new ShadedAdventureComponentWrapper(TranslationManager.render(MessageConstants.GUI_LEFT_CLICK_EDIT.build())))
|
||||
.addLoreLines(new ShadedAdventureComponentWrapper(TranslationManager.render(MessageConstants.GUI_RIGHT_CLICK_RESET.build())));
|
||||
} else {
|
||||
itemBuilder.addLoreLines(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
CFLocale.GUI_LEFT_CLICK_EDIT
|
||||
)));
|
||||
itemBuilder.addLoreLines(new ShadedAdventureComponentWrapper(TranslationManager.render(MessageConstants.GUI_LEFT_CLICK_EDIT.build())));
|
||||
}
|
||||
return itemBuilder;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ package net.momirealms.customfishing.bukkit.gui.icon.property.item;
|
||||
import net.momirealms.customfishing.bukkit.adventure.ShadedAdventureComponentWrapper;
|
||||
import net.momirealms.customfishing.bukkit.gui.SectionPage;
|
||||
import net.momirealms.customfishing.bukkit.gui.page.property.NBTEditor;
|
||||
import net.momirealms.customfishing.bukkit.util.ConfigUtils;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
|
||||
@@ -23,6 +23,8 @@ import net.momirealms.customfishing.bukkit.gui.icon.BackToFolderItem;
|
||||
import net.momirealms.customfishing.bukkit.gui.icon.ScrollDownItem;
|
||||
import net.momirealms.customfishing.bukkit.gui.icon.ScrollUpItem;
|
||||
import net.momirealms.customfishing.bukkit.gui.page.item.ItemSelector;
|
||||
import net.momirealms.customfishing.common.locale.MessageConstants;
|
||||
import net.momirealms.customfishing.common.locale.TranslationManager;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
@@ -79,19 +81,10 @@ public class FileSelector {
|
||||
|
||||
Window window = Window.single()
|
||||
.setViewer(player)
|
||||
.setTitle(new ShadedAdventureComponentWrapper(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
CFLocale.GUI_SELECT_FILE
|
||||
)))
|
||||
.setTitle(new ShadedAdventureComponentWrapper(TranslationManager.render(MessageConstants.GUI_SELECT_FILE.build())))
|
||||
.setGui(gui)
|
||||
.build();
|
||||
|
||||
// gui.playAnimation(new SequentialAnimation(1, true), slotElement -> {
|
||||
// if (slotElement instanceof SlotElement.ItemSlotElement itemSlotElement) {
|
||||
// return !(itemSlotElement.getItem() instanceof Icon);
|
||||
// }
|
||||
// return true;
|
||||
// });
|
||||
|
||||
window.open();
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ package net.momirealms.customfishing.bukkit.gui.page.property;
|
||||
import net.momirealms.customfishing.bukkit.adventure.ShadedAdventureComponentWrapper;
|
||||
import net.momirealms.customfishing.bukkit.gui.SectionPage;
|
||||
import net.momirealms.customfishing.bukkit.gui.icon.BackGroundItem;
|
||||
import net.momirealms.customfishing.bukkit.util.ConfigUtils;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package net.momirealms.customfishing.bukkit.hook;
|
||||
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import net.momirealms.customfishing.api.mechanic.hook.HookConfig;
|
||||
import net.momirealms.customfishing.api.mechanic.hook.HookManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class BukkitHookManager implements HookManager {
|
||||
|
||||
private BukkitCustomFishingPlugin plugin;
|
||||
|
||||
public BukkitHookManager(BukkitCustomFishingPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerHook(HookConfig hook) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Optional<HookConfig> getHook(String id) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,6 @@ import net.momirealms.customfishing.api.mechanic.context.Context;
|
||||
import net.momirealms.customfishing.api.mechanic.context.ContextKeys;
|
||||
import net.momirealms.customfishing.api.mechanic.item.CustomFishingItem;
|
||||
import net.momirealms.customfishing.api.mechanic.item.ItemManager;
|
||||
import net.momirealms.customfishing.bukkit.util.ItemUtils;
|
||||
import net.momirealms.customfishing.bukkit.util.LocationUtils;
|
||||
import net.momirealms.customfishing.common.item.Item;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
@@ -47,9 +47,18 @@ public class BukkitRequirementManager implements RequirementManager<Player> {
|
||||
public BukkitRequirementManager(BukkitCustomFishingPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.registerBuiltInRequirements();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
this.loadExpansions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
this.requirementFactoryMap.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerRequirement(@NotNull String type, @NotNull RequirementFactory<Player> requirementFactory) {
|
||||
if (this.requirementFactoryMap.containsKey(type)) return false;
|
||||
|
||||
@@ -1,63 +1,62 @@
|
||||
/*
|
||||
* 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.requirement;
|
||||
|
||||
import net.momirealms.customfishing.api.common.Pair;
|
||||
import net.momirealms.customfishing.api.mechanic.requirement.Requirement;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class ConditionalElement {
|
||||
|
||||
private final List<Pair<String, WeightModifier>> modifierList;
|
||||
private final HashMap<String, ConditionalElement> subLoots;
|
||||
private final Requirement[] requirements;
|
||||
|
||||
public ConditionalElement(
|
||||
Requirement[] requirements,
|
||||
List<Pair<String, WeightModifier>> modifierList,
|
||||
HashMap<String, ConditionalElement> subElements
|
||||
) {
|
||||
this.modifierList = modifierList;
|
||||
this.requirements = requirements;
|
||||
this.subLoots = subElements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines the weight modifiers for this element.
|
||||
*
|
||||
* @param player The player for whom the modifiers are applied.
|
||||
* @param weightMap The map of weight modifiers.
|
||||
*/
|
||||
synchronized public void combine(Player player, HashMap<String, Double> weightMap) {
|
||||
for (Pair<String, WeightModifier> modifierPair : this.modifierList) {
|
||||
double previous = weightMap.getOrDefault(modifierPair.left(), 0d);
|
||||
weightMap.put(modifierPair.left(), modifierPair.right().modify(player, previous));
|
||||
}
|
||||
}
|
||||
|
||||
public Requirement[] getRequirements() {
|
||||
return requirements;
|
||||
}
|
||||
|
||||
public HashMap<String, ConditionalElement> getSubElements() {
|
||||
return subLoots;
|
||||
}
|
||||
}
|
||||
///*
|
||||
// * 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.requirement;
|
||||
//
|
||||
//import net.momirealms.customfishing.api.mechanic.requirement.Requirement;
|
||||
//import org.bukkit.entity.Player;
|
||||
//
|
||||
//import java.util.HashMap;
|
||||
//import java.util.List;
|
||||
//
|
||||
//public class ConditionalElement {
|
||||
//
|
||||
// private final List<Pair<String, WeightModifier>> modifierList;
|
||||
// private final HashMap<String, ConditionalElement> subLoots;
|
||||
// private final Requirement[] requirements;
|
||||
//
|
||||
// public ConditionalElement(
|
||||
// Requirement[] requirements,
|
||||
// List<Pair<String, WeightModifier>> modifierList,
|
||||
// HashMap<String, ConditionalElement> subElements
|
||||
// ) {
|
||||
// this.modifierList = modifierList;
|
||||
// this.requirements = requirements;
|
||||
// this.subLoots = subElements;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Combines the weight modifiers for this element.
|
||||
// *
|
||||
// * @param player The player for whom the modifiers are applied.
|
||||
// * @param weightMap The map of weight modifiers.
|
||||
// */
|
||||
// synchronized public void combine(Player player, HashMap<String, Double> weightMap) {
|
||||
// for (Pair<String, WeightModifier> modifierPair : this.modifierList) {
|
||||
// double previous = weightMap.getOrDefault(modifierPair.left(), 0d);
|
||||
// weightMap.put(modifierPair.left(), modifierPair.right().modify(player, previous));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public Requirement[] getRequirements() {
|
||||
// return requirements;
|
||||
// }
|
||||
//
|
||||
// public HashMap<String, ConditionalElement> getSubElements() {
|
||||
// return subLoots;
|
||||
// }
|
||||
//}
|
||||
|
||||
@@ -74,6 +74,7 @@ public class BukkitStorageManager implements StorageManager, Listener {
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin.getBoostrap());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
YamlDocument config = plugin.getConfigManager().loadConfig("database.yml");
|
||||
this.serverID = config.getString("unique-server-id", "default");
|
||||
@@ -132,6 +133,7 @@ public class BukkitStorageManager implements StorageManager, Listener {
|
||||
/**
|
||||
* Disables the storage manager and cleans up resources.
|
||||
*/
|
||||
@Override
|
||||
public void disable() {
|
||||
HandlerList.unregisterAll(this);
|
||||
this.dataSource.updateManyPlayersData(onlineUserMap.values(), true);
|
||||
|
||||
@@ -1,86 +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.totem;
|
||||
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import net.momirealms.customfishing.api.mechanic.action.Action;
|
||||
import net.momirealms.customfishing.api.mechanic.action.ActionTrigger;
|
||||
import net.momirealms.customfishing.api.mechanic.totem.TotemConfig;
|
||||
import net.momirealms.customfishing.api.mechanic.totem.TotemParticle;
|
||||
import net.momirealms.customfishing.api.scheduler.CancellableTask;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class ActivatedTotem {
|
||||
|
||||
private final List<CancellableTask> subTasks;
|
||||
private final Location coreLocation;
|
||||
private final TotemConfig totemConfig;
|
||||
private final long expireTime;
|
||||
private final EffectCarrier effectCarrier;
|
||||
|
||||
public ActivatedTotem(Location coreLocation, TotemConfig config) {
|
||||
this.subTasks = new ArrayList<>();
|
||||
this.expireTime = System.currentTimeMillis() + config.getDuration() * 1000L;
|
||||
this.coreLocation = coreLocation.clone().add(0.5,0,0.5);
|
||||
this.totemConfig = config;
|
||||
this.effectCarrier = BukkitCustomFishingPlugin.get().getEffectManager().getEffectCarrier("totem", config.getKey());
|
||||
for (TotemParticle particleSetting : config.getParticleSettings()) {
|
||||
this.subTasks.add(particleSetting.start(coreLocation, config.getRadius()));
|
||||
}
|
||||
}
|
||||
|
||||
public TotemConfig getTotemConfig() {
|
||||
return totemConfig;
|
||||
}
|
||||
|
||||
public Location getCoreLocation() {
|
||||
return coreLocation;
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
for (CancellableTask task : subTasks) {
|
||||
task.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
public long getExpireTime() {
|
||||
return expireTime;
|
||||
}
|
||||
|
||||
public void doTimerAction() {
|
||||
HashMap<String, String> args = new HashMap<>();
|
||||
args.put("{time_left}", String.valueOf((expireTime - System.currentTimeMillis())/1000));
|
||||
PlayerContext playerContext = new PlayerContext(coreLocation, null, args);
|
||||
if (effectCarrier != null) {
|
||||
Action[] actions = effectCarrier.getActions(ActionTrigger.TIMER);
|
||||
if (actions != null) {
|
||||
for (Action action : actions) {
|
||||
action.trigger(playerContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public EffectCarrier getEffectCarrier() {
|
||||
return effectCarrier;
|
||||
}
|
||||
}
|
||||
///*
|
||||
// * 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.totem;
|
||||
//
|
||||
//import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
//import net.momirealms.customfishing.api.mechanic.action.Action;
|
||||
//import net.momirealms.customfishing.api.mechanic.action.ActionTrigger;
|
||||
//import net.momirealms.customfishing.api.mechanic.totem.TotemConfig;
|
||||
//import net.momirealms.customfishing.api.mechanic.totem.TotemParticle;
|
||||
//import net.momirealms.customfishing.common.plugin.scheduler.SchedulerTask;
|
||||
//import org.bukkit.Location;
|
||||
//
|
||||
//import java.util.ArrayList;
|
||||
//import java.util.HashMap;
|
||||
//import java.util.List;
|
||||
//
|
||||
//public class ActivatedTotem {
|
||||
//
|
||||
// private final List<SchedulerTask> subTasks;
|
||||
// private final Location coreLocation;
|
||||
// private final TotemConfig totemConfig;
|
||||
// private final long expireTime;
|
||||
// private final EffectCarrier effectCarrier;
|
||||
//
|
||||
// public ActivatedTotem(Location coreLocation, TotemConfig config) {
|
||||
// this.subTasks = new ArrayList<>();
|
||||
// this.expireTime = System.currentTimeMillis() + config.getDuration() * 1000L;
|
||||
// this.coreLocation = coreLocation.clone().add(0.5,0,0.5);
|
||||
// this.totemConfig = config;
|
||||
// this.effectCarrier = BukkitCustomFishingPlugin.get().getEffectManager().getEffectCarrier("totem", config.getKey());
|
||||
// for (TotemParticle particleSetting : config.getParticleSettings()) {
|
||||
// this.subTasks.add(particleSetting.start(coreLocation, config.getRadius()));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public TotemConfig getTotemConfig() {
|
||||
// return totemConfig;
|
||||
// }
|
||||
//
|
||||
// public Location getCoreLocation() {
|
||||
// return coreLocation;
|
||||
// }
|
||||
//
|
||||
// public void cancel() {
|
||||
// for (CancellableTask task : subTasks) {
|
||||
// task.cancel();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public long getExpireTime() {
|
||||
// return expireTime;
|
||||
// }
|
||||
//
|
||||
// public void doTimerAction() {
|
||||
// HashMap<String, String> args = new HashMap<>();
|
||||
// args.put("{time_left}", String.valueOf((expireTime - System.currentTimeMillis())/1000));
|
||||
// PlayerContext playerContext = new PlayerContext(coreLocation, null, args);
|
||||
// if (effectCarrier != null) {
|
||||
// Action[] actions = effectCarrier.getActions(ActionTrigger.TIMER);
|
||||
// if (actions != null) {
|
||||
// for (Action action : actions) {
|
||||
// action.trigger(playerContext);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public EffectCarrier getEffectCarrier() {
|
||||
// return effectCarrier;
|
||||
// }
|
||||
//}
|
||||
|
||||
@@ -18,11 +18,6 @@
|
||||
package net.momirealms.customfishing.bukkit.totem;
|
||||
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import net.momirealms.customfishing.api.common.Pair;
|
||||
import net.momirealms.customfishing.api.common.SimpleLocation;
|
||||
import net.momirealms.customfishing.api.event.TotemActivateEvent;
|
||||
import net.momirealms.customfishing.api.mechanic.action.Action;
|
||||
import net.momirealms.customfishing.api.mechanic.action.ActionTrigger;
|
||||
import net.momirealms.customfishing.api.mechanic.totem.TotemConfig;
|
||||
import net.momirealms.customfishing.api.mechanic.totem.TotemManager;
|
||||
import net.momirealms.customfishing.api.mechanic.totem.TotemModel;
|
||||
@@ -32,16 +27,16 @@ import net.momirealms.customfishing.api.mechanic.totem.block.property.FaceImpl;
|
||||
import net.momirealms.customfishing.api.mechanic.totem.block.property.HalfImpl;
|
||||
import net.momirealms.customfishing.api.mechanic.totem.block.property.TotemBlockProperty;
|
||||
import net.momirealms.customfishing.api.mechanic.totem.block.type.TypeCondition;
|
||||
import net.momirealms.customfishing.api.scheduler.CancellableTask;
|
||||
import net.momirealms.customfishing.api.util.SimpleLocation;
|
||||
import net.momirealms.customfishing.bukkit.totem.particle.DustParticleSetting;
|
||||
import net.momirealms.customfishing.bukkit.totem.particle.ParticleSetting;
|
||||
import net.momirealms.customfishing.bukkit.util.LocationUtils;
|
||||
import net.momirealms.customfishing.common.plugin.scheduler.SchedulerTask;
|
||||
import net.momirealms.customfishing.common.util.Pair;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.Bisected;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.HandlerList;
|
||||
@@ -49,7 +44,6 @@ import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
@@ -58,382 +52,352 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class BukkitTotemManager implements TotemManager, Listener {
|
||||
|
||||
private final BukkitCustomFishingPlugin plugin;
|
||||
private final HashMap<String, List<TotemConfig>> totemConfigMap;
|
||||
private final List<String> allMaterials;
|
||||
private final ConcurrentHashMap<SimpleLocation, ActivatedTotem> activatedTotems;
|
||||
private CancellableTask timerCheckTask;
|
||||
|
||||
public BukkitTotemManager(BukkitCustomFishingPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.totemConfigMap = new HashMap<>();
|
||||
this.allMaterials = Arrays.stream(Material.values()).map(Enum::name).toList();
|
||||
this.activatedTotems = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
public void load() {
|
||||
this.loadConfig();
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin);
|
||||
this.timerCheckTask = plugin.getScheduler().runTaskAsyncTimer(() -> {
|
||||
long time = System.currentTimeMillis();
|
||||
ArrayList<SimpleLocation> removed = new ArrayList<>();
|
||||
for (Map.Entry<SimpleLocation, ActivatedTotem> entry : activatedTotems.entrySet()) {
|
||||
if (time > entry.getValue().getExpireTime()) {
|
||||
removed.add(entry.getKey());
|
||||
entry.getValue().cancel();
|
||||
} else {
|
||||
entry.getValue().doTimerAction();
|
||||
}
|
||||
}
|
||||
for (SimpleLocation simpleLocation : removed) {
|
||||
activatedTotems.remove(simpleLocation);
|
||||
}
|
||||
}, 1, 1, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public void unload() {
|
||||
this.totemConfigMap.clear();
|
||||
for (ActivatedTotem activatedTotem : activatedTotems.values()) {
|
||||
activatedTotem.cancel();
|
||||
}
|
||||
activatedTotems.clear();
|
||||
HandlerList.unregisterAll(this);
|
||||
if (this.timerCheckTask != null && !this.timerCheckTask.isCancelled())
|
||||
this.timerCheckTask.cancel();
|
||||
}
|
||||
|
||||
public void disable() {
|
||||
unload();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the EffectCarrier associated with an activated totem located near the specified location.
|
||||
*
|
||||
* @param location The location to search for activated totems.
|
||||
* @return The EffectCarrier associated with the nearest activated totem or null if none are found.
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public EffectCarrier getTotemEffect(Location location) {
|
||||
for (ActivatedTotem activatedTotem : activatedTotems.values()) {
|
||||
if (LocationUtils.getDistance(activatedTotem.getCoreLocation(), location) < activatedTotem.getTotemConfig().getRadius()) {
|
||||
return activatedTotem.getEffectCarrier();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBreakTotemCore(BlockBreakEvent event) {
|
||||
if (event.isCancelled())
|
||||
return;
|
||||
Location location = event.getBlock().getLocation();
|
||||
SimpleLocation simpleLocation = SimpleLocation.getByBukkitLocation(location);
|
||||
ActivatedTotem activatedTotem = activatedTotems.remove(simpleLocation);
|
||||
if (activatedTotem != null)
|
||||
activatedTotem.cancel();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInteractBlock(PlayerInteractEvent event) {
|
||||
if (event.isBlockInHand())
|
||||
return;
|
||||
if (event.useItemInHand() == Event.Result.DENY)
|
||||
return;
|
||||
if (event.getAction() != org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK)
|
||||
return;
|
||||
if (event.getHand() != EquipmentSlot.HAND)
|
||||
return;
|
||||
Block block = event.getClickedBlock();
|
||||
assert block != null;
|
||||
String id = plugin.getBlockManager().getAnyPluginBlockID(block);
|
||||
List<TotemConfig> configs = totemConfigMap.get(id);
|
||||
if (configs == null)
|
||||
return;
|
||||
TotemConfig config = null;
|
||||
for (TotemConfig temp : configs) {
|
||||
if (temp.isRightPattern(block.getLocation())) {
|
||||
config = temp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (config == null)
|
||||
return;
|
||||
String totemKey = config.getKey();
|
||||
EffectCarrier carrier = plugin.getEffectManager().getEffectCarrier("totem", totemKey);
|
||||
if (carrier == null)
|
||||
return;
|
||||
PlayerContext playerContext = new PlayerContext(block.getLocation(), event.getPlayer(), new HashMap<>());
|
||||
if (!carrier.isConditionMet(playerContext))
|
||||
return;
|
||||
|
||||
TotemActivateEvent totemActivateEvent = new TotemActivateEvent(event.getPlayer(), block.getLocation(), config);
|
||||
Bukkit.getPluginManager().callEvent(totemActivateEvent);
|
||||
if (totemActivateEvent.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Action[] actions = carrier.getActionMap().get(ActionTrigger.ACTIVATE);
|
||||
if (actions != null)
|
||||
for (Action action : actions) {
|
||||
action.trigger(playerContext);
|
||||
}
|
||||
Location location = block.getLocation();
|
||||
ActivatedTotem activatedTotem = new ActivatedTotem(location, config);
|
||||
SimpleLocation simpleLocation = SimpleLocation.getByBukkitLocation(location);
|
||||
|
||||
ActivatedTotem previous = this.activatedTotems.put(simpleLocation, activatedTotem);
|
||||
if (previous != null) {
|
||||
previous.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
private void loadConfig() {
|
||||
Deque<File> fileDeque = new ArrayDeque<>();
|
||||
for (String type : List.of("totem")) {
|
||||
File typeFolder = new File(plugin.getDataFolder() + File.separator + "contents" + File.separator + type);
|
||||
if (!typeFolder.exists()) {
|
||||
if (!typeFolder.mkdirs()) return;
|
||||
plugin.saveResource("contents" + File.separator + type + File.separator + "default.yml", false);
|
||||
}
|
||||
fileDeque.push(typeFolder);
|
||||
while (!fileDeque.isEmpty()) {
|
||||
File file = fileDeque.pop();
|
||||
File[] files = file.listFiles();
|
||||
if (files == null) continue;
|
||||
for (File subFile : files) {
|
||||
if (subFile.isDirectory()) {
|
||||
fileDeque.push(subFile);
|
||||
} else if (subFile.isFile() && subFile.getName().endsWith(".yml")) {
|
||||
this.loadSingleFile(subFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void loadSingleFile(File file) {
|
||||
YamlConfiguration config = YamlConfiguration.loadConfiguration(file);
|
||||
for (Map.Entry<String, Object> entry : config.getValues(false).entrySet()) {
|
||||
if (entry.getValue() instanceof ConfigurationSection section) {
|
||||
TotemConfig totemConfig = new TotemConfig.Builder(entry.getKey())
|
||||
.setTotemModels(getTotemModels(section.getConfigurationSection("pattern")))
|
||||
.setParticleSettings(getParticleSettings(section.getConfigurationSection("particles")))
|
||||
.setRequirements(plugin.getRequirementManager().parseRequirements(section.getConfigurationSection("requirements"), true))
|
||||
.setRadius(section.getDouble("radius", 8))
|
||||
.setDuration(section.getInt("duration", 300))
|
||||
.build();
|
||||
|
||||
HashSet<String> coreMaterials = new HashSet<>();
|
||||
for (TotemBlock totemBlock : totemConfig.getTotemCore()) {
|
||||
String text = totemBlock.getTypeCondition().getRawText();
|
||||
if (text.startsWith("*")) {
|
||||
String sub = text.substring(1);
|
||||
coreMaterials.addAll(allMaterials.stream().filter(it -> it.endsWith(sub)).toList());
|
||||
} else if (text.endsWith("*")) {
|
||||
String sub = text.substring(0, text.length() - 1);
|
||||
coreMaterials.addAll(allMaterials.stream().filter(it -> it.startsWith(sub)).toList());
|
||||
} else {
|
||||
coreMaterials.add(text);
|
||||
}
|
||||
}
|
||||
for (String material : coreMaterials) {
|
||||
putTotemConfigToMap(material, totemConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void putTotemConfigToMap(String material, TotemConfig totemConfig) {
|
||||
List<TotemConfig> configs = this.totemConfigMap.getOrDefault(material, new ArrayList<>());
|
||||
configs.add(totemConfig);
|
||||
this.totemConfigMap.put(material, configs);
|
||||
}
|
||||
|
||||
public ParticleSetting[] getParticleSettings(ConfigurationSection section) {
|
||||
List<ParticleSetting> particleSettings = new ArrayList<>();
|
||||
if (section != null)
|
||||
for (Map.Entry<String, Object> entry : section.getValues(false).entrySet()) {
|
||||
if (entry.getValue() instanceof ConfigurationSection innerSection) {
|
||||
particleSettings.add(getParticleSetting(innerSection));
|
||||
}
|
||||
}
|
||||
return particleSettings.toArray(new ParticleSetting[0]);
|
||||
}
|
||||
|
||||
public ParticleSetting getParticleSetting(ConfigurationSection section) {
|
||||
Particle particle = Particle.valueOf(section.getString("type","REDSTONE"));
|
||||
String formulaHorizontal = section.getString("polar-coordinates-formula.horizontal");
|
||||
String formulaVertical = section.getString("polar-coordinates-formula.vertical");
|
||||
List<Pair<Double, Double>> ranges = section.getStringList("theta.range")
|
||||
.stream().map(it -> {
|
||||
String[] split = it.split("~");
|
||||
return Pair.of(Double.parseDouble(split[0]) * Math.PI / 180, Double.parseDouble(split[1]) * Math.PI / 180);
|
||||
}).toList();
|
||||
|
||||
double interval = section.getDouble("theta.draw-interval", 3d);
|
||||
int delay = section.getInt("task.delay", 0);
|
||||
int period = section.getInt("task.period", 0);
|
||||
if (particle == Particle.REDSTONE) {
|
||||
String color = section.getString("options.color","0,0,0");
|
||||
String[] colorSplit = color.split(",");
|
||||
return new DustParticleSetting(
|
||||
formulaHorizontal,
|
||||
formulaVertical,
|
||||
particle,
|
||||
interval,
|
||||
ranges,
|
||||
delay,
|
||||
period,
|
||||
new Particle.DustOptions(
|
||||
Color.fromRGB(
|
||||
Integer.parseInt(colorSplit[0]),
|
||||
Integer.parseInt(colorSplit[1]),
|
||||
Integer.parseInt(colorSplit[2])
|
||||
),
|
||||
(float) section.getDouble("options.scale", 1)
|
||||
)
|
||||
);
|
||||
} else if (particle == Particle.DUST_COLOR_TRANSITION) {
|
||||
String color = section.getString("options.from","0,0,0");
|
||||
String[] colorSplit = color.split(",");
|
||||
String toColor = section.getString("options.to","255,255,255");
|
||||
String[] toColorSplit = toColor.split(",");
|
||||
return new DustParticleSetting(
|
||||
formulaHorizontal,
|
||||
formulaVertical,
|
||||
particle,
|
||||
interval,
|
||||
ranges,
|
||||
delay,
|
||||
period,
|
||||
new Particle.DustTransition(
|
||||
Color.fromRGB(
|
||||
Integer.parseInt(colorSplit[0]),
|
||||
Integer.parseInt(colorSplit[1]),
|
||||
Integer.parseInt(colorSplit[2])
|
||||
),
|
||||
Color.fromRGB(
|
||||
Integer.parseInt(toColorSplit[0]),
|
||||
Integer.parseInt(toColorSplit[1]),
|
||||
Integer.parseInt(toColorSplit[2])
|
||||
),
|
||||
(float) section.getDouble("options.scale", 1)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
return new ParticleSetting(
|
||||
formulaHorizontal,
|
||||
formulaVertical,
|
||||
particle,
|
||||
interval,
|
||||
ranges,
|
||||
delay,
|
||||
period
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public TotemModel[] getTotemModels(ConfigurationSection section) {
|
||||
TotemModel originalModel = parseModel(section);
|
||||
List<TotemModel> modelList = new ArrayList<>();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
originalModel = originalModel.deepClone().rotate90();
|
||||
modelList.add(originalModel);
|
||||
if (i % 2 == 0) {
|
||||
modelList.add(originalModel.mirrorVertically());
|
||||
} else {
|
||||
modelList.add(originalModel.mirrorHorizontally());
|
||||
}
|
||||
}
|
||||
return modelList.toArray(new TotemModel[0]);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public TotemModel parseModel(ConfigurationSection section) {
|
||||
ConfigurationSection layerSection = section.getConfigurationSection("layer");
|
||||
List<TotemBlock[][][]> totemBlocksList = new ArrayList<>();
|
||||
if (layerSection != null) {
|
||||
var set = layerSection.getValues(false).entrySet();
|
||||
TotemBlock[][][][] totemBlocks = new TotemBlock[set.size()][][][];
|
||||
for (Map.Entry<String, Object> entry : set) {
|
||||
if (entry.getValue() instanceof List<?> list) {
|
||||
totemBlocks[Integer.parseInt(entry.getKey())-1] = parseLayer((List<String>) list);
|
||||
}
|
||||
}
|
||||
totemBlocksList.addAll(List.of(totemBlocks));
|
||||
}
|
||||
|
||||
String[] core = section.getString("core","1,1,1").split(",");
|
||||
int x = Integer.parseInt(core[2]) - 1;
|
||||
int z = Integer.parseInt(core[1]) - 1;
|
||||
int y = Integer.parseInt(core[0]) - 1;
|
||||
return new TotemModel(
|
||||
x,y,z,
|
||||
totemBlocksList.toArray(new TotemBlock[0][][][])
|
||||
);
|
||||
}
|
||||
|
||||
public TotemBlock[][][] parseLayer(List<String> lines) {
|
||||
List<TotemBlock[][]> totemBlocksList = new ArrayList<>();
|
||||
for (String line : lines) {
|
||||
totemBlocksList.add(parseSingleLine(line));
|
||||
}
|
||||
return totemBlocksList.toArray(new TotemBlock[0][][]);
|
||||
}
|
||||
|
||||
public TotemBlock[][] parseSingleLine(String line) {
|
||||
List<TotemBlock[]> totemBlocksList = new ArrayList<>();
|
||||
String[] splits = line.split("\\s+");
|
||||
for (String split : splits) {
|
||||
totemBlocksList.add(parseSingleElement(split));
|
||||
}
|
||||
return totemBlocksList.toArray(new TotemBlock[0][]);
|
||||
}
|
||||
|
||||
public TotemBlock[] parseSingleElement(String element) {
|
||||
String[] orBlocks = element.split("\\|\\|");
|
||||
List<TotemBlock> totemBlockList = new ArrayList<>();
|
||||
for (String block : orBlocks) {
|
||||
int index = block.indexOf("{");
|
||||
List<TotemBlockProperty> propertyList = new ArrayList<>();
|
||||
if (index == -1) {
|
||||
index = block.length();
|
||||
} else {
|
||||
String propertyStr = block.substring(index+1, block.length()-1);
|
||||
String[] properties = propertyStr.split(";");
|
||||
for (String property : properties) {
|
||||
String[] split = property.split("=");
|
||||
if (split.length < 2) continue;
|
||||
String key = split[0];
|
||||
String value = split[1];
|
||||
switch (key) {
|
||||
// Block face
|
||||
case "face" -> {
|
||||
BlockFace blockFace = BlockFace.valueOf(value.toUpperCase(Locale.ENGLISH));
|
||||
propertyList.add(new FaceImpl(blockFace));
|
||||
}
|
||||
// Block axis
|
||||
case "axis" -> {
|
||||
Axis axis = Axis.valueOf(value.toUpperCase(Locale.ENGLISH));
|
||||
propertyList.add(new AxisImpl(axis));
|
||||
}
|
||||
// Slab, Stair half
|
||||
case "half" -> {
|
||||
Bisected.Half half = Bisected.Half.valueOf(value.toUpperCase(Locale.ENGLISH));
|
||||
propertyList.add(new HalfImpl(half));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
String type = block.substring(0, index);
|
||||
TotemBlock totemBlock = new TotemBlock(
|
||||
TypeCondition.getTypeCondition(type),
|
||||
propertyList.toArray(new TotemBlockProperty[0])
|
||||
);
|
||||
totemBlockList.add(totemBlock);
|
||||
}
|
||||
return totemBlockList.toArray(new TotemBlock[0]);
|
||||
}
|
||||
// private final BukkitCustomFishingPlugin plugin;
|
||||
// private final HashMap<String, List<TotemConfig>> totemConfigMap;
|
||||
// private final List<String> allMaterials;
|
||||
// private final ConcurrentHashMap<SimpleLocation, ActivatedTotem> activatedTotems;
|
||||
// private SchedulerTask timerCheckTask;
|
||||
//
|
||||
// public BukkitTotemManager(BukkitCustomFishingPlugin plugin) {
|
||||
// this.plugin = plugin;
|
||||
// this.totemConfigMap = new HashMap<>();
|
||||
// this.allMaterials = Arrays.stream(Material.values()).map(Enum::name).toList();
|
||||
// this.activatedTotems = new ConcurrentHashMap<>();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void load() {
|
||||
// this.loadConfig();
|
||||
// Bukkit.getPluginManager().registerEvents(this, plugin.getBoostrap());
|
||||
// this.timerCheckTask = plugin.getScheduler().asyncRepeating(() -> {
|
||||
// long time = System.currentTimeMillis();
|
||||
// ArrayList<SimpleLocation> removed = new ArrayList<>();
|
||||
// for (Map.Entry<SimpleLocation, ActivatedTotem> entry : activatedTotems.entrySet()) {
|
||||
// if (time > entry.getValue().getExpireTime()) {
|
||||
// removed.add(entry.getKey());
|
||||
// entry.getValue().cancel();
|
||||
// } else {
|
||||
// entry.getValue().doTimerAction();
|
||||
// }
|
||||
// }
|
||||
// for (SimpleLocation simpleLocation : removed) {
|
||||
// activatedTotems.remove(simpleLocation);
|
||||
// }
|
||||
// }, 1, 1, TimeUnit.SECONDS);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void unload() {
|
||||
// HandlerList.unregisterAll(this);
|
||||
// for (ActivatedTotem activatedTotem : this.activatedTotems.values())
|
||||
// activatedTotem.cancel();
|
||||
// this.activatedTotems.clear();
|
||||
// if (this.timerCheckTask != null)
|
||||
// this.timerCheckTask.cancel();
|
||||
// this.totemConfigMap.clear();
|
||||
// }
|
||||
//
|
||||
//// /**
|
||||
//// * Get the EffectCarrier associated with an activated totem located near the specified location.
|
||||
//// *
|
||||
//// * @param location The location to search for activated totems.
|
||||
//// * @return The EffectCarrier associated with the nearest activated totem or null if none are found.
|
||||
//// */
|
||||
//// @Override
|
||||
//// @Nullable
|
||||
//// public EffectCarrier getTotemEffect(Location location) {
|
||||
//// for (ActivatedTotem activatedTotem : activatedTotems.values()) {
|
||||
//// if (LocationUtils.getDistance(activatedTotem.getCoreLocation(), location) < activatedTotem.getTotemConfig().radius()) {
|
||||
//// return activatedTotem.getEffectCarrier();
|
||||
//// }
|
||||
//// }
|
||||
//// return null;
|
||||
//// }
|
||||
//
|
||||
// @EventHandler
|
||||
// public void onBreakTotemCore(BlockBreakEvent event) {
|
||||
// if (event.isCancelled())
|
||||
// return;
|
||||
// Location location = event.getBlock().getLocation();
|
||||
// SimpleLocation simpleLocation = SimpleLocation.of(location);
|
||||
// ActivatedTotem activatedTotem = activatedTotems.remove(simpleLocation);
|
||||
// if (activatedTotem != null)
|
||||
// activatedTotem.cancel();
|
||||
// }
|
||||
//
|
||||
// @EventHandler
|
||||
// public void onInteractBlock(PlayerInteractEvent event) {
|
||||
// if (event.isBlockInHand())
|
||||
// return;
|
||||
// if (event.useItemInHand() == Event.Result.DENY)
|
||||
// return;
|
||||
// if (event.getAction() != org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK)
|
||||
// return;
|
||||
// if (event.getHand() != EquipmentSlot.HAND)
|
||||
// return;
|
||||
// Block block = event.getClickedBlock();
|
||||
// assert block != null;
|
||||
// String id = plugin.getBlockManager().getBlockID(block);
|
||||
// List<TotemConfig> configs = totemConfigMap.get(id);
|
||||
// if (configs == null)
|
||||
// return;
|
||||
// TotemConfig config = null;
|
||||
// for (TotemConfig temp : configs) {
|
||||
// if (temp.isRightPattern(block.getLocation())) {
|
||||
// config = temp;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// if (config == null)
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// @SuppressWarnings("DuplicatedCode")
|
||||
// private void loadConfig() {
|
||||
// Deque<File> fileDeque = new ArrayDeque<>();
|
||||
// for (String type : List.of("totem")) {
|
||||
// File typeFolder = new File(plugin.getDataFolder() + File.separator + "contents" + File.separator + type);
|
||||
// if (!typeFolder.exists()) {
|
||||
// if (!typeFolder.mkdirs()) return;
|
||||
// plugin.getBoostrap().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) {
|
||||
//// TotemConfig totemConfig = new TotemConfig.Builder(entry.getKey())
|
||||
//// .setTotemModels(getTotemModels(section.getConfigurationSection("pattern")))
|
||||
//// .setParticleSettings(getParticleSettings(section.getConfigurationSection("particles")))
|
||||
//// .setRequirements(plugin.getRequirementManager().parseRequirements(section.getConfigurationSection("requirements"), true))
|
||||
//// .setRadius(section.getDouble("radius", 8))
|
||||
//// .setDuration(section.getInt("duration", 300))
|
||||
//// .build();
|
||||
////
|
||||
//// HashSet<String> coreMaterials = new HashSet<>();
|
||||
//// for (TotemBlock totemBlock : totemConfig.getTotemCore()) {
|
||||
//// String text = totemBlock.getTypeCondition().getRawText();
|
||||
//// if (text.startsWith("*")) {
|
||||
//// String sub = text.substring(1);
|
||||
//// coreMaterials.addAll(allMaterials.stream().filter(it -> it.endsWith(sub)).toList());
|
||||
//// } else if (text.endsWith("*")) {
|
||||
//// String sub = text.substring(0, text.length() - 1);
|
||||
//// coreMaterials.addAll(allMaterials.stream().filter(it -> it.startsWith(sub)).toList());
|
||||
//// } else {
|
||||
//// coreMaterials.add(text);
|
||||
//// }
|
||||
//// }
|
||||
//// for (String material : coreMaterials) {
|
||||
//// putTotemConfigToMap(material, totemConfig);
|
||||
//// }
|
||||
//// }
|
||||
//// }
|
||||
// }
|
||||
//
|
||||
// private void putTotemConfigToMap(String material, TotemConfig totemConfig) {
|
||||
// List<TotemConfig> configs = this.totemConfigMap.getOrDefault(material, new ArrayList<>());
|
||||
// configs.add(totemConfig);
|
||||
// this.totemConfigMap.put(material, configs);
|
||||
// }
|
||||
//
|
||||
//// public ParticleSetting[] getParticleSettings(ConfigurationSection section) {
|
||||
//// List<ParticleSetting> particleSettings = new ArrayList<>();
|
||||
//// if (section != null)
|
||||
//// for (Map.Entry<String, Object> entry : section.getValues(false).entrySet()) {
|
||||
//// if (entry.getValue() instanceof ConfigurationSection innerSection) {
|
||||
//// particleSettings.add(getParticleSetting(innerSection));
|
||||
//// }
|
||||
//// }
|
||||
//// return particleSettings.toArray(new ParticleSetting[0]);
|
||||
//// }
|
||||
//
|
||||
//// public ParticleSetting getParticleSetting(ConfigurationSection section) {
|
||||
//// Particle particle = Particle.valueOf(section.getString("type","REDSTONE"));
|
||||
//// String formulaHorizontal = section.getString("polar-coordinates-formula.horizontal");
|
||||
//// String formulaVertical = section.getString("polar-coordinates-formula.vertical");
|
||||
//// List<Pair<Double, Double>> ranges = section.getStringList("theta.range")
|
||||
//// .stream().map(it -> {
|
||||
//// String[] split = it.split("~");
|
||||
//// return Pair.of(Double.parseDouble(split[0]) * Math.PI / 180, Double.parseDouble(split[1]) * Math.PI / 180);
|
||||
//// }).toList();
|
||||
////
|
||||
//// double interval = section.getDouble("theta.draw-interval", 3d);
|
||||
//// int delay = section.getInt("task.delay", 0);
|
||||
//// int period = section.getInt("task.period", 0);
|
||||
//// if (particle == Particle.REDSTONE) {
|
||||
//// String color = section.getString("options.color","0,0,0");
|
||||
//// String[] colorSplit = color.split(",");
|
||||
//// return new DustParticleSetting(
|
||||
//// formulaHorizontal,
|
||||
//// formulaVertical,
|
||||
//// particle,
|
||||
//// interval,
|
||||
//// ranges,
|
||||
//// delay,
|
||||
//// period,
|
||||
//// new Particle.DustOptions(
|
||||
//// Color.fromRGB(
|
||||
//// Integer.parseInt(colorSplit[0]),
|
||||
//// Integer.parseInt(colorSplit[1]),
|
||||
//// Integer.parseInt(colorSplit[2])
|
||||
//// ),
|
||||
//// (float) section.getDouble("options.scale", 1)
|
||||
//// )
|
||||
//// );
|
||||
//// } else if (particle == Particle.DUST_COLOR_TRANSITION) {
|
||||
//// String color = section.getString("options.from","0,0,0");
|
||||
//// String[] colorSplit = color.split(",");
|
||||
//// String toColor = section.getString("options.to","255,255,255");
|
||||
//// String[] toColorSplit = toColor.split(",");
|
||||
//// return new DustParticleSetting(
|
||||
//// formulaHorizontal,
|
||||
//// formulaVertical,
|
||||
//// particle,
|
||||
//// interval,
|
||||
//// ranges,
|
||||
//// delay,
|
||||
//// period,
|
||||
//// new Particle.DustTransition(
|
||||
//// Color.fromRGB(
|
||||
//// Integer.parseInt(colorSplit[0]),
|
||||
//// Integer.parseInt(colorSplit[1]),
|
||||
//// Integer.parseInt(colorSplit[2])
|
||||
//// ),
|
||||
//// Color.fromRGB(
|
||||
//// Integer.parseInt(toColorSplit[0]),
|
||||
//// Integer.parseInt(toColorSplit[1]),
|
||||
//// Integer.parseInt(toColorSplit[2])
|
||||
//// ),
|
||||
//// (float) section.getDouble("options.scale", 1)
|
||||
//// )
|
||||
//// );
|
||||
//// } else {
|
||||
//// return new ParticleSetting(
|
||||
//// formulaHorizontal,
|
||||
//// formulaVertical,
|
||||
//// particle,
|
||||
//// interval,
|
||||
//// ranges,
|
||||
//// delay,
|
||||
//// period
|
||||
//// );
|
||||
//// }
|
||||
//// }
|
||||
//
|
||||
// public TotemModel[] getTotemModels(ConfigurationSection section) {
|
||||
// TotemModel originalModel = parseModel(section);
|
||||
// List<TotemModel> modelList = new ArrayList<>();
|
||||
// for (int i = 0; i < 4; i++) {
|
||||
// originalModel = originalModel.deepClone().rotate90();
|
||||
// modelList.add(originalModel);
|
||||
// if (i % 2 == 0) {
|
||||
// modelList.add(originalModel.mirrorVertically());
|
||||
// } else {
|
||||
// modelList.add(originalModel.mirrorHorizontally());
|
||||
// }
|
||||
// }
|
||||
// return modelList.toArray(new TotemModel[0]);
|
||||
// }
|
||||
//
|
||||
// @SuppressWarnings("unchecked")
|
||||
// public TotemModel parseModel(ConfigurationSection section) {
|
||||
// ConfigurationSection layerSection = section.getConfigurationSection("layer");
|
||||
// List<TotemBlock[][][]> totemBlocksList = new ArrayList<>();
|
||||
// if (layerSection != null) {
|
||||
// var set = layerSection.getValues(false).entrySet();
|
||||
// TotemBlock[][][][] totemBlocks = new TotemBlock[set.size()][][][];
|
||||
// for (Map.Entry<String, Object> entry : set) {
|
||||
// if (entry.getValue() instanceof List<?> list) {
|
||||
// totemBlocks[Integer.parseInt(entry.getKey())-1] = parseLayer((List<String>) list);
|
||||
// }
|
||||
// }
|
||||
// totemBlocksList.addAll(List.of(totemBlocks));
|
||||
// }
|
||||
//
|
||||
// String[] core = section.getString("core","1,1,1").split(",");
|
||||
// int x = Integer.parseInt(core[2]) - 1;
|
||||
// int z = Integer.parseInt(core[1]) - 1;
|
||||
// int y = Integer.parseInt(core[0]) - 1;
|
||||
// return new TotemModel(
|
||||
// x,y,z,
|
||||
// totemBlocksList.toArray(new TotemBlock[0][][][])
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// public TotemBlock[][][] parseLayer(List<String> lines) {
|
||||
// List<TotemBlock[][]> totemBlocksList = new ArrayList<>();
|
||||
// for (String line : lines) {
|
||||
// totemBlocksList.add(parseSingleLine(line));
|
||||
// }
|
||||
// return totemBlocksList.toArray(new TotemBlock[0][][]);
|
||||
// }
|
||||
//
|
||||
// public TotemBlock[][] parseSingleLine(String line) {
|
||||
// List<TotemBlock[]> totemBlocksList = new ArrayList<>();
|
||||
// String[] splits = line.split("\\s+");
|
||||
// for (String split : splits) {
|
||||
// totemBlocksList.add(parseSingleElement(split));
|
||||
// }
|
||||
// return totemBlocksList.toArray(new TotemBlock[0][]);
|
||||
// }
|
||||
//
|
||||
// public TotemBlock[] parseSingleElement(String element) {
|
||||
// String[] orBlocks = element.split("\\|\\|");
|
||||
// List<TotemBlock> totemBlockList = new ArrayList<>();
|
||||
// for (String block : orBlocks) {
|
||||
// int index = block.indexOf("{");
|
||||
// List<TotemBlockProperty> propertyList = new ArrayList<>();
|
||||
// if (index == -1) {
|
||||
// index = block.length();
|
||||
// } else {
|
||||
// String propertyStr = block.substring(index+1, block.length()-1);
|
||||
// String[] properties = propertyStr.split(";");
|
||||
// for (String property : properties) {
|
||||
// String[] split = property.split("=");
|
||||
// if (split.length < 2) continue;
|
||||
// String key = split[0];
|
||||
// String value = split[1];
|
||||
// switch (key) {
|
||||
// // Block face
|
||||
// case "face" -> {
|
||||
// BlockFace blockFace = BlockFace.valueOf(value.toUpperCase(Locale.ENGLISH));
|
||||
// propertyList.add(new FaceImpl(blockFace));
|
||||
// }
|
||||
// // Block axis
|
||||
// case "axis" -> {
|
||||
// Axis axis = Axis.valueOf(value.toUpperCase(Locale.ENGLISH));
|
||||
// propertyList.add(new AxisImpl(axis));
|
||||
// }
|
||||
// // Slab, Stair half
|
||||
// case "half" -> {
|
||||
// Bisected.Half half = Bisected.Half.valueOf(value.toUpperCase(Locale.ENGLISH));
|
||||
// propertyList.add(new HalfImpl(half));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// String type = block.substring(0, index);
|
||||
// TotemBlock totemBlock = new TotemBlock(
|
||||
// TypeCondition.getTypeCondition(type),
|
||||
// propertyList.toArray(new TotemBlockProperty[0])
|
||||
// );
|
||||
// totemBlockList.add(totemBlock);
|
||||
// }
|
||||
// return totemBlockList.toArray(new TotemBlock[0]);
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
package net.momirealms.customfishing.bukkit.totem.particle;
|
||||
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import net.momirealms.customfishing.api.common.Pair;
|
||||
import net.momirealms.customfishing.api.scheduler.CancellableTask;
|
||||
import net.momirealms.customfishing.common.plugin.scheduler.SchedulerTask;
|
||||
import net.momirealms.customfishing.common.util.Pair;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.World;
|
||||
@@ -46,7 +46,7 @@ public class DustParticleSetting extends ParticleSetting {
|
||||
}
|
||||
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
public CancellableTask start(Location location, double radius) {
|
||||
public SchedulerTask start(Location location, double radius) {
|
||||
World world = location.getWorld();
|
||||
return BukkitCustomFishingPlugin.get().getScheduler().runTaskAsyncTimer(() -> {
|
||||
for (Pair<Double, Double> range : ranges) {
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
package net.momirealms.customfishing.bukkit.totem.particle;
|
||||
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import net.momirealms.customfishing.api.common.Pair;
|
||||
import net.momirealms.customfishing.api.mechanic.totem.TotemParticle;
|
||||
import net.momirealms.customfishing.api.scheduler.CancellableTask;
|
||||
import net.momirealms.customfishing.common.plugin.scheduler.SchedulerTask;
|
||||
import net.momirealms.customfishing.common.util.Pair;
|
||||
import net.objecthunter.exp4j.Expression;
|
||||
import net.objecthunter.exp4j.ExpressionBuilder;
|
||||
import org.bukkit.Location;
|
||||
@@ -63,9 +63,9 @@ public class ParticleSetting implements TotemParticle {
|
||||
}
|
||||
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
public CancellableTask start(Location location, double radius) {
|
||||
public SchedulerTask start(Location location, double radius) {
|
||||
World world = location.getWorld();
|
||||
return BukkitCustomFishingPlugin.get().getScheduler().runTaskAsyncTimer(() -> {
|
||||
return BukkitCustomFishingPlugin.getInstance().getScheduler().asyncRepeating(() -> {
|
||||
for (Pair<Double, Double> range : ranges) {
|
||||
for (double theta = range.left(); theta <= range.right(); theta += interval) {
|
||||
double r = expressionHorizontal.setVariable("theta", theta).setVariable("radius", radius).evaluate();
|
||||
|
||||
@@ -1,221 +0,0 @@
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.events.PacketContainer;
|
||||
import com.comphenix.protocol.wrappers.*;
|
||||
import com.google.common.collect.Lists;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Utility class for managing armor stands and sending related packets.
|
||||
*/
|
||||
public class ArmorStandUtils {
|
||||
|
||||
private ArmorStandUtils() {}
|
||||
|
||||
/**
|
||||
* Creates a destroy packet for removing an armor stand entity.
|
||||
*
|
||||
* @param id The ID of the armor stand entity to destroy
|
||||
* @return The PacketContainer representing the destroy packet
|
||||
*/
|
||||
public static PacketContainer getDestroyPacket(int id) {
|
||||
PacketContainer destroyPacket = new PacketContainer(PacketType.Play.Server.ENTITY_DESTROY);
|
||||
destroyPacket.getIntLists().write(0, List.of(id));
|
||||
return destroyPacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a spawn packet for an armor stand entity at the specified location.
|
||||
*
|
||||
* @param id The ID of the armor stand entity to spawn
|
||||
* @param location The location where the armor stand entity should be spawned
|
||||
* @return The PacketContainer representing the spawn packet
|
||||
*/
|
||||
public static PacketContainer getSpawnPacket(int id, Location location) {
|
||||
PacketContainer entityPacket = new PacketContainer(PacketType.Play.Server.SPAWN_ENTITY);
|
||||
try {
|
||||
entityPacket.getModifier().write(0, id);
|
||||
entityPacket.getModifier().write(1, UUID.randomUUID());
|
||||
entityPacket.getEntityTypeModifier().write(0, EntityType.ARMOR_STAND);
|
||||
entityPacket.getDoubles().write(0, location.getX());
|
||||
entityPacket.getDoubles().write(1, location.getY());
|
||||
entityPacket.getDoubles().write(2, location.getZ());
|
||||
if (BukkitCustomFishingPlugin.get().getVersionManager().isVersionNewerThan1_19()) {
|
||||
entityPacket.getBytes().write(0, (byte) ((location.getYaw() % 360) * 128 / 180));
|
||||
} else {
|
||||
entityPacket.getIntegers().write(5, (int) ((location.getYaw() % 360) * 128 / 180));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return entityPacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a metadata packet for updating the metadata of an armor stand entity.
|
||||
*
|
||||
* @param id The ID of the armor stand entity
|
||||
* @return The PacketContainer representing the metadata packet
|
||||
*/
|
||||
public static PacketContainer getMetaPacket(int id) {
|
||||
PacketContainer metaPacket = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
|
||||
metaPacket.getIntegers().write(0, id);
|
||||
if (BukkitCustomFishingPlugin.get().getVersionManager().isVersionNewerThan1_19_3()) {
|
||||
WrappedDataWatcher wrappedDataWatcher = createDataWatcher();
|
||||
setValueList(metaPacket, wrappedDataWatcher);
|
||||
} else {
|
||||
metaPacket.getWatchableCollectionModifier().write(0, createDataWatcher().getWatchableObjects());
|
||||
}
|
||||
return metaPacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value list in a PacketContainer's DataWatcher from a WrappedDataWatcher.
|
||||
*
|
||||
* @param metaPacket The PacketContainer representing the metadata packet
|
||||
* @param wrappedDataWatcher The WrappedDataWatcher containing the value list
|
||||
*/
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
private static void setValueList(PacketContainer metaPacket, WrappedDataWatcher wrappedDataWatcher) {
|
||||
List<WrappedDataValue> wrappedDataValueList = Lists.newArrayList();
|
||||
wrappedDataWatcher.getWatchableObjects().stream().filter(Objects::nonNull).forEach(entry -> {
|
||||
final WrappedDataWatcher.WrappedDataWatcherObject dataWatcherObject = entry.getWatcherObject();
|
||||
wrappedDataValueList.add(new WrappedDataValue(dataWatcherObject.getIndex(), dataWatcherObject.getSerializer(), entry.getRawValue()));
|
||||
});
|
||||
metaPacket.getDataValueCollectionModifier().write(0, wrappedDataValueList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a metadata packet for updating the metadata of an armor stand entity with a custom Component.
|
||||
*
|
||||
* @param id The ID of the armor stand entity
|
||||
* @param component The Component to set as metadata
|
||||
* @return The PacketContainer representing the metadata packet
|
||||
*/
|
||||
public static PacketContainer getMetaPacket(int id, Component component) {
|
||||
PacketContainer metaPacket = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
|
||||
metaPacket.getIntegers().write(0, id);
|
||||
if (BukkitCustomFishingPlugin.get().getVersionManager().isVersionNewerThan1_19_3()) {
|
||||
WrappedDataWatcher wrappedDataWatcher = createDataWatcher(component);
|
||||
setValueList(metaPacket, wrappedDataWatcher);
|
||||
} else {
|
||||
metaPacket.getWatchableCollectionModifier().write(0, createDataWatcher(component).getWatchableObjects());
|
||||
}
|
||||
return metaPacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DataWatcher for an invisible armor stand entity.
|
||||
*
|
||||
* @return The created DataWatcher
|
||||
*/
|
||||
public static WrappedDataWatcher createDataWatcher() {
|
||||
WrappedDataWatcher wrappedDataWatcher = new WrappedDataWatcher();
|
||||
WrappedDataWatcher.Serializer serializer1 = WrappedDataWatcher.Registry.get(Boolean.class);
|
||||
WrappedDataWatcher.Serializer serializer2 = WrappedDataWatcher.Registry.get(Byte.class);
|
||||
wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(3, serializer1), false);
|
||||
byte flag = 0x20;
|
||||
wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(0, serializer2), flag);
|
||||
return wrappedDataWatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DataWatcher for an invisible armor stand entity with a custom Component.
|
||||
*
|
||||
* @param component The Component to set in the DataWatcher
|
||||
* @return The created DataWatcher
|
||||
*/
|
||||
public static WrappedDataWatcher createDataWatcher(Component component) {
|
||||
WrappedDataWatcher wrappedDataWatcher = new WrappedDataWatcher();
|
||||
WrappedDataWatcher.Serializer serializer1 = WrappedDataWatcher.Registry.get(Boolean.class);
|
||||
WrappedDataWatcher.Serializer serializer2 = WrappedDataWatcher.Registry.get(Byte.class);
|
||||
wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(2, WrappedDataWatcher.Registry.getChatComponentSerializer(true)), Optional.of(WrappedChatComponent.fromJson(GsonComponentSerializer.gson().serialize(component)).getHandle()));
|
||||
wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(3, serializer1), true);
|
||||
wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(15, serializer2), (byte) 0x01);
|
||||
byte flag = 0x20;
|
||||
wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(0, serializer2), flag);
|
||||
return wrappedDataWatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an equipment packet for equipping an armor stand with an ItemStack.
|
||||
*
|
||||
* @param id The ID of the armor stand entity
|
||||
* @param itemStack The ItemStack to equip
|
||||
* @return The PacketContainer representing the equipment packet
|
||||
*/
|
||||
public static PacketContainer getEquipPacket(int id, ItemStack itemStack) {
|
||||
PacketContainer equipPacket = new PacketContainer(PacketType.Play.Server.ENTITY_EQUIPMENT);
|
||||
equipPacket.getIntegers().write(0, id);
|
||||
List<Pair<EnumWrappers.ItemSlot, ItemStack>> pairs = new ArrayList<>();
|
||||
pairs.add(new Pair<>(EnumWrappers.ItemSlot.HEAD, itemStack));
|
||||
equipPacket.getSlotStackPairLists().write(0, pairs);
|
||||
return equipPacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a fake armor stand entity with item on head to a player at the specified location.
|
||||
*
|
||||
* @param player The player to send the entity to
|
||||
* @param location The location where the entity should appear
|
||||
* @param itemStack The ItemStack to represent the entity
|
||||
* @param seconds The duration (in seconds) the entity should be displayed
|
||||
*/
|
||||
public static void sendFakeItem(Player player, Location location, ItemStack itemStack, int seconds) {
|
||||
int id = new Random().nextInt(Integer.MAX_VALUE);
|
||||
if (BukkitCustomFishingPlugin.get().getVersionManager().isVersionNewerThan1_19_4()) {
|
||||
BukkitCustomFishingPluginImpl.sendPackets(player, getSpawnPacket(id, location.clone().subtract(0,1,0)), getMetaPacket(id), getEquipPacket(id, itemStack));
|
||||
} else {
|
||||
BukkitCustomFishingPluginImpl.sendPacket(player, getSpawnPacket(id, location.clone().subtract(0,1,0)));
|
||||
BukkitCustomFishingPluginImpl.sendPacket(player, getMetaPacket(id));
|
||||
BukkitCustomFishingPluginImpl.sendPacket(player, getEquipPacket(id, itemStack));
|
||||
}
|
||||
BukkitCustomFishingPlugin.get().getScheduler().runTaskAsyncLater(() -> BukkitCustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, getDestroyPacket(id)), seconds * 50L, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a hologram (armor stand with custom text) to a player at the specified location.
|
||||
*
|
||||
* @param player The player to send the hologram to
|
||||
* @param location The location where the hologram should appear
|
||||
* @param component The Component representing the hologram's text
|
||||
* @param seconds The duration (in seconds) the hologram should be displayed
|
||||
*/
|
||||
public static void sendHologram(Player player, Location location, Component component, int seconds) {
|
||||
int id = new Random().nextInt(Integer.MAX_VALUE);
|
||||
if (BukkitCustomFishingPlugin.get().getVersionManager().isVersionNewerThan1_19_4()) {
|
||||
BukkitCustomFishingPluginImpl.sendPackets(player, getSpawnPacket(id, location.clone().subtract(0,1,0)), getMetaPacket(id, component));
|
||||
} else {
|
||||
BukkitCustomFishingPluginImpl.sendPacket(player, getSpawnPacket(id, location.clone().subtract(0,1,0)));
|
||||
BukkitCustomFishingPluginImpl.sendPacket(player, getMetaPacket(id, component));
|
||||
}
|
||||
BukkitCustomFishingPlugin.get().getScheduler().runTaskAsyncLater(() -> BukkitCustomFishingPluginImpl.getProtocolManager().sendServerPacket(player, getDestroyPacket(id)), seconds * 50L, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
@@ -1,256 +0,0 @@
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
import net.momirealms.customfishing.api.mechanic.misc.placeholder.BukkitPlaceholderManager;
|
||||
import net.momirealms.customfishing.api.mechanic.misc.value.MathValue;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Utility class for configuration-related operations.
|
||||
*/
|
||||
public class ConfigUtils {
|
||||
|
||||
private ConfigUtils() {}
|
||||
|
||||
|
||||
/**
|
||||
* Splits a string into a pair of integers using the "~" delimiter.
|
||||
*
|
||||
* @param value The input string
|
||||
* @return A Pair of integers
|
||||
*/
|
||||
public static Pair<Integer, Integer> splitStringIntegerArgs(String value, String regex) {
|
||||
String[] split = value.split(regex);
|
||||
return Pair.of(Integer.parseInt(split[0]), Integer.parseInt(split[1]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a list of strings in the format "key:value" into a list of Pairs with keys and doubles.
|
||||
*
|
||||
* @param list The input list of strings
|
||||
* @return A list of Pairs containing keys and doubles
|
||||
*/
|
||||
public static List<Pair<String, Double>> getWeights(List<String> list) {
|
||||
List<Pair<String, Double>> result = new ArrayList<>(list.size());
|
||||
for (String member : list) {
|
||||
String[] split = member.split(":",2);
|
||||
String key = split[0];
|
||||
result.add(Pair.of(key, Double.parseDouble(split[1])));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a list of enchantment pairs from a configuration section.
|
||||
*
|
||||
* @param section The configuration section to extract enchantment data from.
|
||||
* @return A list of enchantment pairs.
|
||||
*/
|
||||
@NotNull
|
||||
public static List<Pair<String, Short>> getEnchantmentPair(ConfigurationSection section) {
|
||||
List<Pair<String, Short>> list = new ArrayList<>();
|
||||
if (section == null) return list;
|
||||
for (Map.Entry<String, Object> entry : section.getValues(false).entrySet()) {
|
||||
if (entry.getValue() instanceof Integer integer) {
|
||||
list.add(Pair.of(entry.getKey(), Short.parseShort(String.valueOf(Math.max(1, Math.min(Short.MAX_VALUE, integer))))));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static List<Pair<Integer, MathValue>> getEnchantAmountPair(ConfigurationSection section) {
|
||||
List<Pair<Integer, MathValue>> list = new ArrayList<>();
|
||||
if (section == null) return list;
|
||||
for (Map.Entry<String, Object> entry : section.getValues(false).entrySet()) {
|
||||
list.add(Pair.of(Integer.parseInt(entry.getKey()), getValue(entry.getValue())));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static List<Pair<Pair<String, Short>, MathValue>> getEnchantPoolPair(ConfigurationSection section) {
|
||||
List<Pair<Pair<String, Short>, MathValue>> list = new ArrayList<>();
|
||||
if (section == null) return list;
|
||||
for (Map.Entry<String, Object> entry : section.getValues(false).entrySet()) {
|
||||
list.add(Pair.of(getEnchantmentPair(entry.getKey()), getValue(entry.getValue())));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static Pair<String, Short> getEnchantmentPair(String value) {
|
||||
int last = value.lastIndexOf(":");
|
||||
if (last == -1 || last == 0 || last == value.length() - 1) {
|
||||
throw new IllegalArgumentException("Invalid format of the input enchantment");
|
||||
}
|
||||
return Pair.of(value.substring(0, last), Short.parseShort(value.substring(last + 1)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of enchantment tuples from a configuration section.
|
||||
*
|
||||
* @param section The configuration section to extract enchantment data from.
|
||||
* @return A list of enchantment tuples.
|
||||
*/
|
||||
@NotNull
|
||||
public static List<Tuple<Double, String, Short>> getEnchantmentTuple(ConfigurationSection section) {
|
||||
List<Tuple<Double, String, Short>> list = new ArrayList<>();
|
||||
if (section == null) return list;
|
||||
for (Map.Entry<String, Object> entry : section.getValues(false).entrySet()) {
|
||||
if (entry.getValue() instanceof ConfigurationSection inner) {
|
||||
Tuple<Double, String, Short> tuple = Tuple.of(
|
||||
inner.getDouble("chance"),
|
||||
inner.getString("enchant"),
|
||||
Short.valueOf(String.valueOf(inner.getInt("level")))
|
||||
);
|
||||
list.add(tuple);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static String getString(Object o) {
|
||||
if (o instanceof String s) {
|
||||
return s;
|
||||
} else if (o instanceof Integer i) {
|
||||
return String.valueOf(i);
|
||||
} else if (o instanceof Double d) {
|
||||
return String.valueOf(d);
|
||||
}
|
||||
throw new IllegalArgumentException("Illegal string format: " + o);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads data from a YAML configuration file and creates it if it doesn't exist.
|
||||
*
|
||||
* @param file The file path
|
||||
* @return The YamlConfiguration
|
||||
*/
|
||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||
public static YamlConfiguration readData(File file) {
|
||||
if (!file.exists()) {
|
||||
try {
|
||||
file.getParentFile().mkdirs();
|
||||
file.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
LogUtils.warn("Failed to generate data files!</red>");
|
||||
}
|
||||
}
|
||||
return YamlConfiguration.loadConfiguration(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a WeightModifier from a string representation.
|
||||
*
|
||||
* @param text The input string
|
||||
* @return A WeightModifier based on the provided text
|
||||
* @throws IllegalArgumentException if the weight format is invalid
|
||||
*/
|
||||
public static WeightModifier getModifier(String text) {
|
||||
if (text.length() == 0) {
|
||||
throw new IllegalArgumentException("Weight format is invalid.");
|
||||
}
|
||||
switch (text.charAt(0)) {
|
||||
case '/' -> {
|
||||
double arg = Double.parseDouble(text.substring(1));
|
||||
return (player, weight) -> weight / arg;
|
||||
}
|
||||
case '*' -> {
|
||||
double arg = Double.parseDouble(text.substring(1));
|
||||
return (player, weight) -> weight * arg;
|
||||
}
|
||||
case '-' -> {
|
||||
double arg = Double.parseDouble(text.substring(1));
|
||||
return (player, weight) -> weight - arg;
|
||||
}
|
||||
case '%' -> {
|
||||
double arg = Double.parseDouble(text.substring(1));
|
||||
return (player, weight) -> weight % arg;
|
||||
}
|
||||
case '+' -> {
|
||||
double arg = Double.parseDouble(text.substring(1));
|
||||
return (player, weight) -> weight + arg;
|
||||
}
|
||||
case '=' -> {
|
||||
String formula = text.substring(1);
|
||||
return (player, weight) -> getExpressionValue(player, formula, Map.of("{0}", String.valueOf(weight)));
|
||||
}
|
||||
default -> throw new IllegalArgumentException("Invalid weight: " + text);
|
||||
}
|
||||
}
|
||||
|
||||
public static double getExpressionValue(Player player, String formula, Map<String, String> vars) {
|
||||
formula = BukkitPlaceholderManager.getInstance().parse(player, formula, vars);
|
||||
return new ExpressionBuilder(formula).build().evaluate();
|
||||
}
|
||||
|
||||
public static ArrayList<String> getReadableSection(Map<String, Object> map) {
|
||||
ArrayList<String> list = new ArrayList<>();
|
||||
mapToReadableStringList(map, list, 0, false);
|
||||
return list;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void mapToReadableStringList(Map<String, Object> map, List<String> readableList, int loop_times, boolean isMapList) {
|
||||
boolean first = true;
|
||||
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
||||
Object nbt = entry.getValue();
|
||||
if (nbt instanceof List<?> list) {
|
||||
if (isMapList && first) {
|
||||
first = false;
|
||||
readableList.add(" ".repeat(loop_times - 1) + "<white>- <gold>" + entry.getKey() + ":");
|
||||
} else {
|
||||
readableList.add(" ".repeat(loop_times) + "<gold>" + entry.getKey() + ":");
|
||||
}
|
||||
for (Object value : list) {
|
||||
if (value instanceof Map<?,?> nbtMap) {
|
||||
mapToReadableStringList((Map<String, Object>) nbtMap, readableList, loop_times + 2, true);
|
||||
} else {
|
||||
readableList.add(" ".repeat(loop_times + 1) + "<white>- " + value);
|
||||
}
|
||||
}
|
||||
} else if (nbt instanceof Map<?,?> innerMap) {
|
||||
if (isMapList && first) {
|
||||
first = false;
|
||||
readableList.add(" ".repeat(loop_times - 1) + "<white>- <gold>" + entry.getKey() + ":");
|
||||
} else {
|
||||
readableList.add(" ".repeat(loop_times) + "<gold>" + entry.getKey() + ":");
|
||||
}
|
||||
mapToReadableStringList((Map<String, Object>) innerMap, readableList, loop_times + 1, false);
|
||||
} else {
|
||||
if (isMapList && first) {
|
||||
first = false;
|
||||
readableList.add(" ".repeat(loop_times - 1) + "<white>- <gold>" + entry.getKey() + ": <white>" + nbt.toString());
|
||||
} else {
|
||||
readableList.add(" ".repeat(loop_times) + "<gold>" + entry.getKey() + ": <white>" + nbt.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.events.PacketContainer;
|
||||
import com.comphenix.protocol.wrappers.WrappedDataValue;
|
||||
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
|
||||
import com.google.common.collect.Lists;
|
||||
import net.momirealms.customfishing.api.BukkitCustomFishingPlugin;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Utility class for managing fake item entities using PacketContainers.
|
||||
*/
|
||||
public class FakeItemUtils {
|
||||
|
||||
private FakeItemUtils() {}
|
||||
|
||||
/**
|
||||
* Creates a destroy packet for removing a fake item entity.
|
||||
*
|
||||
* @param id The ID of the fake item entity to destroy
|
||||
* @return The PacketContainer representing the destroy packet
|
||||
*/
|
||||
public static PacketContainer getDestroyPacket(int id) {
|
||||
PacketContainer destroyPacket = new PacketContainer(PacketType.Play.Server.ENTITY_DESTROY);
|
||||
destroyPacket.getIntLists().write(0, List.of(id));
|
||||
return destroyPacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a spawn packet for a fake item entity at the specified location.
|
||||
*
|
||||
* @param id The ID of the fake item entity to spawn
|
||||
* @param location The location where the fake item entity should be spawned
|
||||
* @return The PacketContainer representing the spawn packet
|
||||
*/
|
||||
public static PacketContainer getSpawnPacket(int id, Location location) {
|
||||
PacketContainer entityPacket = new PacketContainer(PacketType.Play.Server.SPAWN_ENTITY);
|
||||
entityPacket.getModifier().write(0, id);
|
||||
entityPacket.getModifier().write(1, UUID.randomUUID());
|
||||
entityPacket.getEntityTypeModifier().write(0, EntityType.DROPPED_ITEM);
|
||||
entityPacket.getDoubles().write(0, location.getX());
|
||||
entityPacket.getDoubles().write(1, location.getY() - 0.5);
|
||||
entityPacket.getDoubles().write(2, location.getZ());
|
||||
return entityPacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a metadata packet for updating the metadata of a fake item entity.
|
||||
*
|
||||
* @param id The ID of the fake item entity
|
||||
* @param itemStack The ItemStack to update the metadata with
|
||||
* @return The PacketContainer representing the metadata packet
|
||||
*/
|
||||
public static PacketContainer getMetaPacket(int id, ItemStack itemStack) {
|
||||
PacketContainer metaPacket = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
|
||||
metaPacket.getIntegers().write(0, id);
|
||||
if (BukkitCustomFishingPlugin.getInstance().getVersionManager().isVersionNewerThan1_19_3()) {
|
||||
WrappedDataWatcher wrappedDataWatcher = createDataWatcher(itemStack);
|
||||
setValueList(metaPacket, wrappedDataWatcher);
|
||||
} else {
|
||||
metaPacket.getWatchableCollectionModifier().write(0, createDataWatcher(itemStack).getWatchableObjects());
|
||||
}
|
||||
return metaPacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a teleport packet for moving a fake item entity to the specified location.
|
||||
*
|
||||
* @param id The ID of the fake item entity to teleport
|
||||
* @param location The location to teleport the fake item entity to
|
||||
* @return The PacketContainer representing the teleport packet
|
||||
*/
|
||||
public static PacketContainer getTpPacket(int id, Location location) {
|
||||
PacketContainer tpPacket = new PacketContainer(PacketType.Play.Server.ENTITY_TELEPORT);
|
||||
tpPacket.getModifier().write(0, id);
|
||||
tpPacket.getDoubles().write(0, location.getX());
|
||||
tpPacket.getDoubles().write(1, location.getY() - 0.5);
|
||||
tpPacket.getDoubles().write(2, location.getZ());
|
||||
return tpPacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a velocity packet for applying velocity to a fake item entity.
|
||||
*
|
||||
* @param id The ID of the fake item entity
|
||||
* @param vector The velocity vector to apply
|
||||
* @return The PacketContainer representing the velocity packet
|
||||
*/
|
||||
public static PacketContainer getVelocityPacket(int id, Vector vector) {
|
||||
PacketContainer entityPacket = new PacketContainer(PacketType.Play.Server.ENTITY_VELOCITY);
|
||||
entityPacket.getModifier().write(0, id);
|
||||
entityPacket.getIntegers().write(1, (int) (vector.getX() * 8000));
|
||||
entityPacket.getIntegers().write(2, (int) (vector.getY() * 8000));
|
||||
entityPacket.getIntegers().write(3, (int) (vector.getZ() * 8000));
|
||||
return entityPacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DataWatcher for a given ItemStack.
|
||||
*
|
||||
* @param itemStack The ItemStack to create the DataWatcher for
|
||||
* @return The created DataWatcher
|
||||
*/
|
||||
public static WrappedDataWatcher createDataWatcher(ItemStack itemStack) {
|
||||
WrappedDataWatcher wrappedDataWatcher = new WrappedDataWatcher();
|
||||
wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(8, WrappedDataWatcher.Registry.getItemStackSerializer(false)), itemStack);
|
||||
wrappedDataWatcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(5, WrappedDataWatcher.Registry.get(Boolean.class)), true);
|
||||
return wrappedDataWatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value list in a PacketContainer's DataWatcher from a WrappedDataWatcher.
|
||||
*
|
||||
* @param metaPacket The PacketContainer representing the metadata packet
|
||||
* @param wrappedDataWatcher The WrappedDataWatcher containing the value list
|
||||
*/
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
private static void setValueList(PacketContainer metaPacket, WrappedDataWatcher wrappedDataWatcher) {
|
||||
List<WrappedDataValue> wrappedDataValueList = Lists.newArrayList();
|
||||
wrappedDataWatcher.getWatchableObjects().stream().filter(Objects::nonNull).forEach(entry -> {
|
||||
final WrappedDataWatcher.WrappedDataWatcherObject dataWatcherObject = entry.getWatcherObject();
|
||||
wrappedDataValueList.add(new WrappedDataValue(dataWatcherObject.getIndex(), dataWatcherObject.getSerializer(), entry.getRawValue()));
|
||||
});
|
||||
metaPacket.getDataValueCollectionModifier().write(0, wrappedDataValueList);
|
||||
}
|
||||
}
|
||||
@@ -1,502 +0,0 @@
|
||||
/*
|
||||
* 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.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.api.BukkitCustomFishingPlugin;
|
||||
import net.momirealms.customfishing.api.common.Pair;
|
||||
import net.momirealms.customfishing.api.mechanic.hook.HookConfigImpl;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerItemDamageEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
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.io.BukkitObjectInputStream;
|
||||
import org.bukkit.util.io.BukkitObjectOutputStream;
|
||||
import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Utility class for various item-related operations.
|
||||
*/
|
||||
public class ItemUtils {
|
||||
|
||||
private ItemUtils() {}
|
||||
|
||||
/**
|
||||
* Updates the lore of an NBTItem based on its custom NBT tags.
|
||||
*
|
||||
* @param nbtItem The NBTItem to update
|
||||
* @return The updated NBTItem
|
||||
*/
|
||||
public static NBTItem updateNBTItemLore(NBTItem nbtItem) {
|
||||
NBTCompound cfCompound = nbtItem.getCompound("CustomFishing");
|
||||
if (cfCompound == null)
|
||||
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");
|
||||
HookConfigImpl setting = BukkitCustomFishingPlugin.get().getHookManager().getHookSetting(hookID);
|
||||
if (setting == null) {
|
||||
cfCompound.removeKey("hook_id");
|
||||
cfCompound.removeKey("hook_item");
|
||||
cfCompound.removeKey("hook_dur");
|
||||
} else {
|
||||
for (String newLore : setting.lore()) {
|
||||
ScoreComponent.Builder builder = Component.score().name("cf").objective("hook");
|
||||
builder.append(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
newLore.replace("{dur}", String.valueOf(cfCompound.getInteger("hook_dur")))
|
||||
.replace("{max}", String.valueOf(setting.maxDurability()))
|
||||
));
|
||||
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(AdventureHelper.getInstance().getComponentFromMiniMessage(
|
||||
newLore.replace("{dur}", String.valueOf(current))
|
||||
.replace("{max}", String.valueOf(max))
|
||||
));
|
||||
lore.add(GsonComponentSerializer.gson().serialize(builder.build()));
|
||||
}
|
||||
}
|
||||
return nbtItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the lore of an ItemStack based on its custom NBT tags.
|
||||
*
|
||||
* @param itemStack The ItemStack to update
|
||||
*/
|
||||
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());
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduces the durability of a fishing hook item.
|
||||
*
|
||||
* @param rod The fishing rod ItemStack
|
||||
* @param updateLore Whether to update the lore after reducing durability
|
||||
*/
|
||||
public static void decreaseHookDurability(ItemStack rod, int amount, boolean updateLore) {
|
||||
if (rod == null || rod.getType() != Material.FISHING_ROD)
|
||||
return;
|
||||
NBTItem nbtItem = new NBTItem(rod);
|
||||
NBTCompound cfCompound = nbtItem.getCompound("CustomFishing");
|
||||
if (cfCompound != null && cfCompound.hasTag("hook_dur")) {
|
||||
int hookDur = cfCompound.getInteger("hook_dur");
|
||||
if (hookDur != -1) {
|
||||
hookDur = Math.max(0, hookDur - amount);
|
||||
if (hookDur > 0) {
|
||||
cfCompound.setInteger("hook_dur", hookDur);
|
||||
} else {
|
||||
cfCompound.removeKey("hook_id");
|
||||
cfCompound.removeKey("hook_dur");
|
||||
cfCompound.removeKey("hook_item");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (updateLore) updateNBTItemLore(nbtItem);
|
||||
rod.setItemMeta(nbtItem.getItem().getItemMeta());
|
||||
}
|
||||
|
||||
/**
|
||||
* Increases the durability of a fishing hook by a specified amount and optionally updates its lore.
|
||||
*
|
||||
* @param rod The fishing rod ItemStack to modify.
|
||||
* @param amount The amount by which to increase the durability.
|
||||
* @param updateLore Whether to update the lore of the fishing rod.
|
||||
*/
|
||||
public static void increaseHookDurability(ItemStack rod, int amount, boolean updateLore) {
|
||||
if (rod == null || rod.getType() != Material.FISHING_ROD)
|
||||
return;
|
||||
NBTItem nbtItem = new NBTItem(rod);
|
||||
NBTCompound cfCompound = nbtItem.getCompound("CustomFishing");
|
||||
if (cfCompound != null && cfCompound.hasTag("hook_dur")) {
|
||||
int hookDur = cfCompound.getInteger("hook_dur");
|
||||
if (hookDur != -1) {
|
||||
String id = cfCompound.getString("hook_id");
|
||||
HookConfigImpl setting = BukkitCustomFishingPlugin.get().getHookManager().getHookSetting(id);
|
||||
if (setting == null) {
|
||||
cfCompound.removeKey("hook_id");
|
||||
cfCompound.removeKey("hook_dur");
|
||||
cfCompound.removeKey("hook_item");
|
||||
} else {
|
||||
hookDur = Math.min(setting.maxDurability(), hookDur + amount);
|
||||
cfCompound.setInteger("hook_dur", hookDur);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (updateLore) updateNBTItemLore(nbtItem);
|
||||
rod.setItemMeta(nbtItem.getItem().getItemMeta());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the durability of a fishing hook to a specific amount and optionally updates its lore.
|
||||
*
|
||||
* @param rod The fishing rod ItemStack to modify.
|
||||
* @param amount The new durability value to set.
|
||||
* @param updateLore Whether to update the lore of the fishing rod.
|
||||
*/
|
||||
public static void setHookDurability(ItemStack rod, int amount, boolean updateLore) {
|
||||
if (rod == null || rod.getType() != Material.FISHING_ROD)
|
||||
return;
|
||||
NBTItem nbtItem = new NBTItem(rod);
|
||||
NBTCompound cfCompound = nbtItem.getCompound("CustomFishing");
|
||||
if (cfCompound != null && cfCompound.hasTag("hook_dur")) {
|
||||
int hookDur = cfCompound.getInteger("hook_dur");
|
||||
if (hookDur != -1) {
|
||||
String id = cfCompound.getString("hook_id");
|
||||
HookConfigImpl setting = BukkitCustomFishingPlugin.get().getHookManager().getHookSetting(id);
|
||||
if (setting == null) {
|
||||
cfCompound.removeKey("hook_id");
|
||||
cfCompound.removeKey("hook_dur");
|
||||
cfCompound.removeKey("hook_item");
|
||||
} else {
|
||||
hookDur = Math.min(setting.maxDurability(), amount);
|
||||
cfCompound.setInteger("hook_dur", hookDur);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (updateLore) updateNBTItemLore(nbtItem);
|
||||
rod.setItemMeta(nbtItem.getItem().getItemMeta());
|
||||
}
|
||||
|
||||
/**
|
||||
* Decreases the durability of an item and updates its lore.
|
||||
*
|
||||
* @param itemStack The ItemStack to reduce durability for
|
||||
* @param amount The amount by which to reduce durability
|
||||
* @param updateLore Whether to update the lore after reducing durability
|
||||
*/
|
||||
public static void decreaseDurability(Player player, ItemStack itemStack, int amount, 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("max_dur")) {
|
||||
int unBreakingLevel = itemStack.getEnchantmentLevel(Enchantment.DURABILITY);
|
||||
if (Math.random() > (double) 1 / (unBreakingLevel + 1)) {
|
||||
return;
|
||||
}
|
||||
if (nbtItem.getByte("Unbreakable") == 1) {
|
||||
return;
|
||||
}
|
||||
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 {
|
||||
itemStack.setAmount(0);
|
||||
}
|
||||
} else {
|
||||
ItemMeta previousMeta = itemStack.getItemMeta().clone();
|
||||
PlayerItemDamageEvent itemDamageEvent = new PlayerItemDamageEvent(player, itemStack, amount, amount);
|
||||
Bukkit.getPluginManager().callEvent(itemDamageEvent);
|
||||
if (!itemStack.getItemMeta().equals(previousMeta) || itemDamageEvent.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
int unBreakingLevel = itemStack.getEnchantmentLevel(Enchantment.DURABILITY);
|
||||
if (Math.random() > (double) 1 / (unBreakingLevel + 1)) {
|
||||
return;
|
||||
}
|
||||
if (nbtItem.getByte("Unbreakable") == 1) {
|
||||
return;
|
||||
}
|
||||
int damage = nbtItem.getInteger("Damage") + amount;
|
||||
if (damage > itemStack.getType().getMaxDurability()) {
|
||||
itemStack.setAmount(0);
|
||||
} else {
|
||||
nbtItem.setInteger("Damage", damage);
|
||||
if (updateLore) updateNBTItemLore(nbtItem);
|
||||
itemStack.setItemMeta(nbtItem.getItem().getItemMeta());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increases the durability of an item and updates its lore.
|
||||
*
|
||||
* @param itemStack The ItemStack to increase durability for
|
||||
* @param amount The amount by which to increase durability
|
||||
* @param updateLore Whether to update the lore after increasing durability
|
||||
*/
|
||||
public static void increaseDurability(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());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the durability of an item and updates its lore.
|
||||
*
|
||||
* @param itemStack The ItemStack to set durability for
|
||||
* @param amount The new durability value
|
||||
* @param updateLore Whether to update the lore after setting durability
|
||||
*/
|
||||
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());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current durability of an item.
|
||||
*
|
||||
* @param itemStack The ItemStack to get durability from
|
||||
* @return The current durability value
|
||||
*/
|
||||
public static Pair<Integer, Integer> getCustomDurability(ItemStack itemStack) {
|
||||
if (itemStack == null || itemStack.getType() == Material.AIR)
|
||||
return Pair.of(0, 0);
|
||||
if (itemStack.getItemMeta() instanceof Damageable damageable && damageable.isUnbreakable())
|
||||
return Pair.of(-1, -1);
|
||||
NBTItem nbtItem = new NBTItem(itemStack);
|
||||
NBTCompound cfCompound = nbtItem.getCompound("CustomFishing");
|
||||
if (cfCompound != null && cfCompound.hasTag("max_dur")) {
|
||||
return Pair.of(cfCompound.getInteger("max_dur"), cfCompound.getInteger("cur_dur"));
|
||||
} else {
|
||||
return Pair.of(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives a certain amount of an item to a player, handling stacking and item drops.
|
||||
*
|
||||
* @param player The player to give the item to
|
||||
* @param itemStack The ItemStack to give
|
||||
* @param amount The amount of items to give
|
||||
* @return The actual amount of items given
|
||||
*/
|
||||
public static int giveItem(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;
|
||||
}
|
||||
|
||||
public static String toBase64(ItemStack itemStack) {
|
||||
if (itemStack == null || itemStack.getType() == Material.AIR)
|
||||
return "";
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
try (BukkitObjectOutputStream dataOutput = new BukkitObjectOutputStream(outputStream)) {
|
||||
dataOutput.writeObject(itemStack);
|
||||
byte[] byteArr = outputStream.toByteArray();
|
||||
dataOutput.close();
|
||||
outputStream.close();
|
||||
return Base64Coder.encodeLines(byteArr);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public static ItemStack fromBase64(String base64) {
|
||||
if (base64 == null || base64.equals(""))
|
||||
return new ItemStack(Material.AIR);
|
||||
ByteArrayInputStream inputStream;
|
||||
try {
|
||||
inputStream = new ByteArrayInputStream(Base64Coder.decodeLines(base64));
|
||||
} catch (IllegalArgumentException e) {
|
||||
return new ItemStack(Material.AIR);
|
||||
}
|
||||
ItemStack stack = null;
|
||||
try (BukkitObjectInputStream dataInput = new BukkitObjectInputStream(inputStream)) {
|
||||
stack = (ItemStack) dataInput.readObject();
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
public static ItemStack removeOwner(ItemStack itemStack) {
|
||||
if (itemStack == null || itemStack.getType() == Material.AIR) return itemStack;
|
||||
NBTItem nbtItem = new NBTItem(itemStack);
|
||||
if (nbtItem.hasTag("owner")) {
|
||||
nbtItem.removeKey("owner");
|
||||
return nbtItem.getItem();
|
||||
}
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the amount of items that can't be put in the inventory
|
||||
*/
|
||||
public static int putLootsToBag(Inventory inventory, ItemStack itemStack, int amount) {
|
||||
itemStack = removeOwner(itemStack.clone());
|
||||
ItemMeta meta = itemStack.getItemMeta();
|
||||
int maxStackSize = itemStack.getMaxStackSize();
|
||||
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 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return amount;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,4 @@
|
||||
# Developer: @Xiao-MoMi
|
||||
# Wiki: https://mo-mi.gitbook.io/xiaomomi-plugins/
|
||||
config-version: '32'
|
||||
config-version: '${config_version}'
|
||||
|
||||
# Debug
|
||||
debug: false
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
config-version: '${config_version}'
|
||||
|
||||
# file:
|
||||
# JSON
|
||||
# YAML
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
config-version: '${config_version}'
|
||||
|
||||
enable: true
|
||||
|
||||
# Container title
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
# Don't change this
|
||||
config-version: '31'
|
||||
|
||||
messages:
|
||||
prefix: '<gradient:#0070B3:#A0EACF>[CustomFishing] </gradient>'
|
||||
reload: '<white>Reloaded. Took <green>{time}ms.'
|
||||
item-not-exist: 'Item not found.'
|
||||
give-item: 'Successfully given player {player} {amount}x {item}.'
|
||||
get-item: 'Successfully got {amount}x {item}.'
|
||||
possible-loots: 'Possible loots here: '
|
||||
split-char: ', '
|
||||
competition-not-exist: 'Competition {id} does not exist.'
|
||||
no-competition-ongoing: "There's no competition ongoing."
|
||||
stop-competition: 'Stopped the current competition.'
|
||||
end-competition: 'Ended the current competition.'
|
||||
no-score: 'No Score'
|
||||
no-player: 'No Player'
|
||||
no-rank: 'No Rank'
|
||||
goal-catch-amount: 'Fish count caught'
|
||||
goal-max-size: 'Largest fish caught'
|
||||
goal-total-size: 'Total length of fish caught'
|
||||
goal-total-score: 'Cumulative score of fish caught'
|
||||
unsafe-modification: "Cannot modify a player's fishing bag if they're active on another linked server."
|
||||
never-played: "The player hasn't joined the server before. Can't modify a nonexistent player's fishing bag."
|
||||
data-not-loaded: "<red>Data hasn't loaded. Please re-enter the server. If issues persist, reach out to the server admin."
|
||||
open-market-gui: "Successfully opened the market gui for {player}"
|
||||
open-fishing-bag: "Successfully opened the fishing bag for {player}"
|
||||
format-day: 'd'
|
||||
format-hour: 'h'
|
||||
format-minute: 'm'
|
||||
format-second: 's'
|
||||
|
||||
gui:
|
||||
search: "Search"
|
||||
select-file: 'Select file'
|
||||
select-item: "Select item"
|
||||
dupe-invalid-key: "<red>● Duplicated or invalid key"
|
||||
new-value: "New value: "
|
||||
temp-new-key: 'New key'
|
||||
set-new-key: "Set new key"
|
||||
edit-key: 'Edit {0}'
|
||||
delete-property: "<#00CED1>● Delete property"
|
||||
click-confirm: "<#00FF7F> -> Click to confirm"
|
||||
invalid-number: "<red>● Invalid number"
|
||||
illegal-format: "<red>● Illegal format"
|
||||
scroll-up: '<gray>● Scroll up'
|
||||
scroll-down: '<gray>● Scroll down'
|
||||
cannot-scroll-up: "<red>You've reached the top"
|
||||
cannot-scroll-down: "<red>You can't scroll further down"
|
||||
next-page: '<gray>● Next Page'
|
||||
goto-next-page: '<gray>Go to page <yellow>{0} <gray>/ <yellow>{1}'
|
||||
cannot-goto-next-page: '<red>There are no more pages'
|
||||
previous-page: '<gray>● Previous page'
|
||||
goto-previous-page: '<gray>Go to page <yellow>{0} <gray>/ <yellow>{1}'
|
||||
cannot-goto-previous-page: "<red>You can't go further back"
|
||||
back-to-parent-page: "<#FF8C00>Back to parent page"
|
||||
back-to-parent-folder: "<#FF8C00>Back to parent folder"
|
||||
current-value: "<gray>Current value: <white>"
|
||||
click-to-toggle: "<#00FF7F> -> Click to toggle"
|
||||
left-click-edit: "<#00FF7F> -> Left click to edit"
|
||||
right-click-reset: "<#FF6347> -> Right click to reset"
|
||||
right-click-delete: "<#FF6347> -> Right click to delete"
|
||||
right-click-cancel: "<#00CED1> -> Right click to cancel"
|
||||
loot-show-in-finder: "<#5F9EA0>● Show In Fish Finder"
|
||||
loot-score: "<#FF1493>● Score"
|
||||
loot-nick: "<#00FF00>● Nick"
|
||||
loot-instant-game: "<#7B68EE>● Instant Game"
|
||||
loot-disable-statistics: "<#CD853F>● Disable Statistics"
|
||||
loot-disable-game: "<#8B4513>● Disable Game"
|
||||
item-amount: "<#1E90FF>● Amount"
|
||||
item-custom-model-data: "<#FFC0CB>● Custom Model Data"
|
||||
item-display-name: "<#FAFAD2>● Display Name"
|
||||
item-custom-durability: "<#1E90FF>● Custom Durability"
|
||||
item-enchantment: "<#8A2BE2>● Enchantment"
|
||||
item-head64: "<#2E8B57>● Head64"
|
||||
item-item-flag: "<#E6E6FA>● Item Flag"
|
||||
item-lore: "<#FA8072>● Lore"
|
||||
item-material: "<#FF00FF>● Material"
|
||||
item-nbt: "<#FA8072>● NBT"
|
||||
item-prevent-grab: "<#FF4500>● Prevent Grabbing"
|
||||
item-price: "<#FFD700>● Price"
|
||||
item-price-base: "<gray> - base: <white>"
|
||||
item-price-bonus: "<gray> - bonus: <white>"
|
||||
item-random-durability: "<#FFFF00>● Random Durability"
|
||||
item-size: "<#FFF0F5>● Size"
|
||||
item-stackable: "<#9370DB>● Stackable"
|
||||
item-stored-enchantment: "<#9370DB>● Stored Enchantment"
|
||||
item-tag: "<#2E8B57>● Tag"
|
||||
item-unbreakable: "<#C0C0C0>● Unbreakable"
|
||||
page-amount-title: "Edit Amount"
|
||||
page-model-data-title: "Edit CustomModelData"
|
||||
page-display-name-title: "Edit display name"
|
||||
page-new-display-name: "New name"
|
||||
page-custom-durability-title: "Edit custom durability"
|
||||
page-stored-enchantment-title: "Edit stored enchantment"
|
||||
page-enchantment-title: "Edit enchantment"
|
||||
page-select-one-enchantment: "Select one enchantment"
|
||||
page-add-new-enchantment: "<green>[+] <gray>Add a new enchantment"
|
||||
page-item-flag-title: "Edit item flag"
|
||||
page-lore-title: "Edit lore"
|
||||
page-add-new-lore: "<green>[+] <gray>Add a new line"
|
||||
page-select-one-lore: "Select one line"
|
||||
page-material-title: "Edit Material"
|
||||
page-nbt-compound-key-title: "Edit compound key"
|
||||
page-nbt-list-key-title: "Edit list key"
|
||||
page-nbt-key-title: "Edit key"
|
||||
page-nbt-invalid-key: "<red>Invaild key"
|
||||
page-nbt-add-new-compound: "<green>[+] <gray>Add a new compound"
|
||||
page-nbt-add-new-list: "<green>[+] <gray>Add a new list"
|
||||
page-nbt-add-new-value: "<green>[+] <gray>Add a new value"
|
||||
page-add-new-key: "<green>[+] <gray>Add a new key"
|
||||
page-nbt-preview: "<green>● NBT Preview"
|
||||
page-nbt-back-to-compound: "<gray>Back to parent compound"
|
||||
page-nbt-set-value-title: "Set value"
|
||||
page-nbt-edit-title: "Edit NBT"
|
||||
page-nick-title: "Edit nick"
|
||||
page-new-nick: "New nick"
|
||||
page-price-title: "Edit price"
|
||||
page-base-price: "Base"
|
||||
page-base-bonus: "Bonus"
|
||||
page-score-title: "Edit score"
|
||||
page-size-title: "Edit size"
|
||||
page-size-min: "Minimum"
|
||||
page-size-max: "Maximum"
|
||||
page-size-max-no-less-min: "<red>● Max must be no less than min"
|
||||
@@ -1,125 +0,0 @@
|
||||
# Don't change this
|
||||
config-version: '31'
|
||||
|
||||
messages:
|
||||
prefix: '<gradient:#0070B3:#A0EACF>[CustomFishing] </gradient>'
|
||||
reload: '<white>Recargado! Tardó <green>{time}ms.'
|
||||
item-not-exist: 'Item no encontrado.'
|
||||
give-item: 'Se ha entregado {amount}x {item} al jugador {player}.'
|
||||
get-item: 'Se ha recibido {amount}x {item}.'
|
||||
possible-loots: 'Posibles recompensas: '
|
||||
split-char: ', '
|
||||
competition-not-exist: 'La Competición {id} no existe.'
|
||||
no-competition-ongoing: "No hay una competencia activa."
|
||||
stop-competition: 'Se ha detenido la competición.'
|
||||
end-competition: 'Ha finalizado la competición.'
|
||||
no-score: 'Sin puntaje'
|
||||
no-player: 'Sin jugador'
|
||||
no-rank: 'Sin rango'
|
||||
goal-catch-amount: 'Peces atrapados'
|
||||
goal-max-size: 'Pez más grande capturado'
|
||||
goal-total-size: 'Longitud total de peces capturados'
|
||||
goal-total-score: 'Puntaje acumulado por peces capturados'
|
||||
unsafe-modification: "No se puede modificar la bolsa de pesca de un jugador si sigue activo en otro servidor vinculado."
|
||||
never-played: "Este jugador nunca se ha unido al servidor. No puedes modificar la bolsa de pesca de un jugador inexistente."
|
||||
data-not-loaded: "<red>No se pudo cargar la información. Por favor, vuelve a ingresar al servidor. Si el problema persiste, contacta a un administrador."
|
||||
open-market-gui: "Se ha abierto la interfaz para {player}"
|
||||
open-fishing-bag: "Se ha abierto la bolsa de pesca de {player}"
|
||||
format-day: 'd'
|
||||
format-hour: 'h'
|
||||
format-minute: 'm'
|
||||
format-second: 's'
|
||||
|
||||
gui:
|
||||
search: "Buscar"
|
||||
select-file: 'Seleccionar archivo'
|
||||
select-item: "Seleccionar item"
|
||||
dupe-invalid-key: "<red>● ID inválida o duplicada"
|
||||
new-value: "Nuevo valor: "
|
||||
temp-new-key: 'Nueva ID'
|
||||
set-new-key: "Definir nueva ID"
|
||||
edit-key: 'Editar {0}'
|
||||
delete-property: "<#00CED1>● Eliminar propiedad"
|
||||
click-confirm: "<#00FF7F> -> Click para confirmar"
|
||||
invalid-number: "<red>● Número inválido"
|
||||
illegal-format: "<red>● Formato inválido"
|
||||
scroll-up: '<gray>● Arriba'
|
||||
scroll-down: '<gray>● Abajo'
|
||||
cannot-scroll-up: "<red>Estás en el límite superior"
|
||||
cannot-scroll-down: "<red>Estás en el límite inferior"
|
||||
next-page: '<gray>● Siguiente Página'
|
||||
goto-next-page: '<gray>Ir a la página <yellow>{0} <gray>/ <yellow>{1}'
|
||||
cannot-goto-next-page: '<red>No hay más páginas'
|
||||
previous-page: '<gray>● Página anterior'
|
||||
goto-previous-page: '<gray>Ir a la página <yellow>{0} <gray>/ <yellow>{1}'
|
||||
cannot-goto-previous-page: "<red>No hay más páginas atrás"
|
||||
back-to-parent-page: "<#FF8C00>Volver al menú anterior"
|
||||
back-to-parent-folder: "<#FF8C00>Volver a la carpeta anterior"
|
||||
current-value: "<gray>Valor actual: <white>"
|
||||
click-to-toggle: "<#00FF7F> -> Click para cambiar"
|
||||
left-click-edit: "<#00FF7F> -> Click izquierdo para editar"
|
||||
right-click-reset: "<#FF6347> -> Click derecho para restablecer"
|
||||
right-click-delete: "<#FF6347> -> Click derecho para eliminar"
|
||||
right-click-cancel: "<#00CED1> -> Click derecho para cancelar"
|
||||
loot-show-in-finder: "<#5F9EA0>● Mostar en el rastreador de peces"
|
||||
loot-score: "<#FF1493>● Puntaje"
|
||||
loot-nick: "<#00FF00>● Apodo"
|
||||
loot-instant-game: "<#7B68EE>● Juego Instantáneo"
|
||||
loot-disable-statistics: "<#CD853F>● Deshabilitar Estadísticas"
|
||||
loot-disable-game: "<#8B4513>● Deshabilitar Juego"
|
||||
item-amount: "<#1E90FF>● Cantidad"
|
||||
item-custom-model-data: "<#FFC0CB>● Custom Model Data"
|
||||
item-display-name: "<#FAFAD2>● Nombre a mostrar"
|
||||
item-custom-durability: "<#1E90FF>● Durabilidad"
|
||||
item-enchantment: "<#8A2BE2>● Encantamiento"
|
||||
item-head64: "<#2E8B57>● Head64"
|
||||
item-item-flag: "<#E6E6FA>● Item Flag"
|
||||
item-lore: "<#FA8072>● Descripción"
|
||||
item-material: "<#FF00FF>● Material"
|
||||
item-nbt: "<#FA8072>● NBT"
|
||||
item-prevent-grab: "<#FF4500>● Evitar recoger item"
|
||||
item-price: "<#FFD700>● Precio"
|
||||
item-price-base: "<gray> - base: <white>"
|
||||
item-price-bonus: "<gray> - bonus: <white>"
|
||||
item-random-durability: "<#FFFF00>● Durabilidad Aleatoria"
|
||||
item-size: "<#FFF0F5>● Tamaño"
|
||||
item-stackable: "<#9370DB>● Acumulable"
|
||||
item-stored-enchantment: "<#9370DB>● Encantamiento Almacenado"
|
||||
item-tag: "<#2E8B57>● Etiqueta"
|
||||
item-unbreakable: "<#C0C0C0>● Irrompible"
|
||||
page-amount-title: "Editar Cantidad"
|
||||
page-model-data-title: "Editar CustomModelData"
|
||||
page-display-name-title: "Editar nombre a mostrar"
|
||||
page-new-display-name: "Nuevo nombre"
|
||||
page-custom-durability-title: "Edit durabilidad"
|
||||
page-stored-enchantment-title: "Edit encantamiento almacenado"
|
||||
page-enchantment-title: "Editar enchantmentamiento"
|
||||
page-select-one-enchantment: "Seleccionar un encantamiento"
|
||||
page-add-new-enchantment: "<green>[+] <gray>Añadir un encantamiento"
|
||||
page-item-flag-title: "Editar item flag"
|
||||
page-lore-title: "Editar descripción"
|
||||
page-add-new-lore: "<green>[+] <gray>Añadir nueva línea"
|
||||
page-select-one-lore: "Seleccionar una línea"
|
||||
page-material-title: "Editar Material"
|
||||
page-nbt-compound-key-title: "Editar ID de NBT compuesta"
|
||||
page-nbt-list-key-title: "Editar lista de IDs"
|
||||
page-nbt-key-title: "Editar ID"
|
||||
page-nbt-invalid-key: "<red>ID inválida"
|
||||
page-nbt-add-new-compound: "<green>[+] <gray>Añadir nueva NBT compuesta"
|
||||
page-nbt-add-new-list: "<green>[+] <gray>Añadir nueva lista"
|
||||
page-nbt-add-new-value: "<green>[+] <gray>Añadir nuevo valor"
|
||||
page-add-new-key: "<green>[+] <gray>Añadir nueva ID"
|
||||
page-nbt-preview: "<green>● Vista previa de NBT"
|
||||
page-nbt-back-to-compound: "<gray>Volver al compuesto padre"
|
||||
page-nbt-set-value-title: "Definir nuevo valor"
|
||||
page-nbt-edit-title: "Editar NBT"
|
||||
page-nick-title: "Editar apodo"
|
||||
page-new-nick: "Nuevo apodo"
|
||||
page-price-title: "Editar precio"
|
||||
page-base-price: "Base"
|
||||
page-base-bonus: "Bonus"
|
||||
page-score-title: "Editar puntuación"
|
||||
page-size-title: "Editar tamaño"
|
||||
page-size-min: "Mínimo"
|
||||
page-size-max: "Máximo"
|
||||
page-size-max-no-less-min: "<red>● El valor máximo no puede ser inferior al mínimo"
|
||||
@@ -1,125 +0,0 @@
|
||||
# Don't change this
|
||||
config-version: '30'
|
||||
|
||||
messages:
|
||||
prefix: '<gradient:#0070B3:#A0EACF>[CustomFishing] </gradient>'
|
||||
reload: '<white>Rechargé. A pris <green>{time}ms.</green>'
|
||||
item-not-exist: 'Objet non trouvé.'
|
||||
give-item: 'Joueur {player} a reçu avec succès {amount}x {item}.'
|
||||
get-item: 'A obtenu avec succès {amount}x {item}.'
|
||||
possible-loots: 'Butins possibles ici : '
|
||||
split-char: ', '
|
||||
competition-not-exist: "La compétition {id} n'existe pas."
|
||||
no-competition-ongoing: 'Aucune compétition en cours.'
|
||||
stop-competition: 'Compétition actuelle arrêtée.'
|
||||
end-competition: 'Compétition actuelle terminée.'
|
||||
no-score: 'Pas de score'
|
||||
no-player: 'Pas de joueur'
|
||||
no-rank: 'Pas de classement'
|
||||
goal-catch-amount: 'Nombre de poissons attrapés'
|
||||
goal-max-size: 'Plus gros poisson attrapé'
|
||||
goal-total-size: 'Longueur totale des poissons attrapés'
|
||||
goal-total-score: 'Score cumulatif des poissons attrapés'
|
||||
unsafe-modification: "Impossible de modifier le sac de pêche d'un joueur s'il est actif sur un autre serveur lié."
|
||||
never-played: "Le joueur n'a jamais rejoint le serveur auparavant. Impossible de modifier le sac de pêche d'un joueur inexistant."
|
||||
data-not-loaded: "<red>Les données n'ont pas été chargées. Veuillez réessayer de rejoindre le serveur. Si les problèmes persistent, contactez l'administrateur du serveur."
|
||||
open-market-gui: "L'interface du marché a été ouverte avec succès pour {player}."
|
||||
open-fishing-bag: "Le sac de pêche de {player} a été ouvert avec succès."
|
||||
format-day: 'j'
|
||||
format-hour: 'h'
|
||||
format-minute: 'm'
|
||||
format-second: 's'
|
||||
|
||||
gui:
|
||||
search: "Rechercher"
|
||||
select-file: "Sélectionner un fichier"
|
||||
select-item: "Sélectionner un élément"
|
||||
dupe-invalid-key: "<red>● Clé en double ou invalide"
|
||||
new-value: "Nouvelle valeur : "
|
||||
temp-new-key: "Nouvelle clé"
|
||||
set-new-key: "Définir une nouvelle clé"
|
||||
edit-key: "Modifier {0}"
|
||||
delete-property: "<#00CED1>● Supprimer la propriété"
|
||||
click-confirm: "<#00FF7F> -> Cliquez pour confirmer"
|
||||
invalid-number: "<red>● Nombre invalide"
|
||||
illegal-format: "<red>● Format illégal"
|
||||
scroll-up: "<gray>● Faire défiler vers le haut"
|
||||
scroll-down: "<gray>● Faire défiler vers le bas"
|
||||
cannot-scroll-up: "<red>Vous avez atteint le haut"
|
||||
cannot-scroll-down: "<red>Vous ne pouvez pas faire défiler plus bas"
|
||||
next-page: "<gray>● Page suivante"
|
||||
goto-next-page: "<gray>Aller à la page <yellow>{0} <gray>/ <yellow>{1}"
|
||||
cannot-goto-next-page: "<red>Il n'y a plus de pages"
|
||||
previous-page: "<gray>● Page précédente"
|
||||
goto-previous-page: "<gray>Aller à la page <yellow>{0} <gray>/ <yellow>{1}"
|
||||
cannot-goto-previous-page: "<red>Vous ne pouvez pas revenir en arrière"
|
||||
back-to-parent-page: "<#FF8C00>Retour à la page parente"
|
||||
back-to-parent-folder: "<#FF8C00>Retour au dossier parent"
|
||||
current-value: "<gray>Valeur actuelle : <white>"
|
||||
click-to-toggle: "<#00FF7F> -> Cliquez pour basculer"
|
||||
left-click-edit: "<#00FF7F> -> Cliquez gauche pour modifier"
|
||||
right-click-reset: "<#FF6347> -> Cliquez droit pour réinitialiser"
|
||||
right-click-delete: "<#FF6347> -> Cliquez droit pour supprimer"
|
||||
right-click-cancel: "<#00CED1> -> Cliquez droit pour annuler"
|
||||
loot-show-in-finder: "<#5F9EA0>● Afficher dans le repère de poisson"
|
||||
loot-score: "<#FF1493>● Score"
|
||||
loot-nick: "<#00FF00>● Surnom"
|
||||
loot-instant-game: "<#7B68EE>● Jeu instantané"
|
||||
loot-disable-statistics: "<#CD853F>● Désactiver les statistiques"
|
||||
loot-disable-game: "<#8B4513>● Désactiver le jeu"
|
||||
item-amount: "<#1E90FF>● Quantité"
|
||||
item-custom-model-data: "<#FFC0CB>● Données de modèle personnalisées"
|
||||
item-display-name: "<#FAFAD2>● Nom affiché"
|
||||
item-custom-durability: "<#1E90FF>● Durabilité personnalisée"
|
||||
item-enchantment: "<#8A2BE2>● Enchantement"
|
||||
item-head64: "<#2E8B57>● Tête64"
|
||||
item-item-flag: "<#E6E6FA>● Drapeau d'élément"
|
||||
item-lore: "<#FA8072>● Légende"
|
||||
item-material: "<#FF00FF>● Matériau"
|
||||
item-nbt: "<#FA8072>● NBT"
|
||||
item-prevent-grab: "<#FF4500>● Empêcher la saisie"
|
||||
item-price: "<#FFD700>● Prix"
|
||||
item-price-base: "<gray> - de base : <white>"
|
||||
item-price-bonus: "<gray> - bonus : <white>"
|
||||
item-random-durability: "<#FFFF00>● Durabilité aléatoire"
|
||||
item-size: "<#FFF0F5>● Taille"
|
||||
item-stackable: "<#9370DB>● Empilable"
|
||||
item-stored-enchantment: "<#9370DB>● Enchantement stocké"
|
||||
item-tag: "<#2E8B57>● Étiquette"
|
||||
item-unbreakable: "<#C0C0C0>● Incassable"
|
||||
page-amount-title: "Modifier la quantité"
|
||||
page-model-data-title: "Modifier CustomModelData"
|
||||
page-display-name-title: "Modifier le nom affiché"
|
||||
page-new-display-name: "Nouveau nom"
|
||||
page-custom-durability-title: "Modifier la durabilité personnalisée"
|
||||
page-stored-enchantment-title: "Modifier l'enchantement stocké"
|
||||
page-enchantment-title: "Modifier l'enchantement"
|
||||
page-select-one-enchantment: "Sélectionner un enchantement"
|
||||
page-add-new-enchantment: "<green>[+] <gray>Ajouter un nouvel enchantement"
|
||||
page-item-flag-title: "Modifier le drapeau d'élément"
|
||||
page-lore-title: "Modifier la légende"
|
||||
page-add-new-lore: "<green>[+] <gray>Ajouter une nouvelle ligne"
|
||||
page-select-one-lore: "Sélectionner une ligne"
|
||||
page-material-title: "Modifier le matériau"
|
||||
page-nbt-compound-key-title: "Modifier la clé composée"
|
||||
page-nbt-list-key-title: "Modifier la clé de liste"
|
||||
page-nbt-key-title: "Modifier la clé"
|
||||
page-nbt-invalid-key: "<red>Clé invalide"
|
||||
page-nbt-add-new-compound: "<green>[+] <gray>Ajouter une nouvelle composante"
|
||||
page-nbt-add-new-list: "<green>[+] <gray>Ajouter une nouvelle liste"
|
||||
page-nbt-add-new-value: "<green>[+] <gray>Ajouter une nouvelle valeur"
|
||||
page-add-new-key: "<green>[+] <gray>Ajouter une nouvelle clé"
|
||||
page-nbt-preview: "<green>● Aperçu NBT"
|
||||
page-nbt-back-to-compound: "<gray>Retour à la composante parente"
|
||||
page-nbt-set-value-title: "Définir la valeur"
|
||||
page-nbt-edit-title: "Modifier NBT"
|
||||
page-nick-title: "Modifier le surnom"
|
||||
page-new-nick: "Nouveau surnom"
|
||||
page-price-title: "Modifier le prix"
|
||||
page-base-price: "De base"
|
||||
page-base-bonus: "Bonus"
|
||||
page-score-title: "Modifier le score"
|
||||
page-size-title: "Modifier la taille"
|
||||
page-size-min: "Minimum"
|
||||
page-size-max: "Maximum"
|
||||
page-size-max-no-less-min: "<red>Le maximum ne doit pas être inférieur au minimum"
|
||||
@@ -1,126 +0,0 @@
|
||||
# Don't change this
|
||||
config-version: '30'
|
||||
|
||||
messages:
|
||||
prefix: '<gradient:#0070B3:#A0EACF>[CustomFishing] </gradient>'
|
||||
reload: '<white>Újratöltve. Időtartam: <green>{time}ms.'
|
||||
item-not-exist: 'Tétel nem található.'
|
||||
give-item: 'Sikeresen adva {player} játékosnak {amount}x {item}.'
|
||||
get-item: 'Sikeresen megszerezve {amount}x {item}.'
|
||||
possible-loots: 'Lehetséges kapások itt: '
|
||||
split-char: ', '
|
||||
competition-not-exist: 'A(z) {id} verseny nem létezik.'
|
||||
no-competition-ongoing: "Nincs folyamatban lévő verseny."
|
||||
stop-competition: 'Leállítottad a jelenlegi versenyt.'
|
||||
end-competition: 'Befejezted a jelenlegi versenyt.'
|
||||
no-score: 'Nincs pontszám'
|
||||
no-player: 'Nincs játékos'
|
||||
no-rank: 'Nincs rang'
|
||||
goal-catch-amount: 'Kifogott halak száma'
|
||||
goal-max-size: 'Legnagyobb kifogott hal'
|
||||
goal-total-size: 'Összes kifogott hal hossza'
|
||||
goal-total-score: 'Kifogott halak összpontszáma'
|
||||
unsafe-modification: "Nem lehet módosítani egy játékos horgász táskáját, ha aktív egy másik szerveren."
|
||||
never-played: "A játékos még nem csatlakozott a szerverhez. Nem lehet módosítani egy nem létező játékos horgász táskáját."
|
||||
data-not-loaded: "<red>Az adatok nem lettek betöltve. Kérjük, csatlakozz újra a szerverhez. Ha a probléma továbbra is fennáll, fordulj a szerveradminisztrátorhoz."
|
||||
open-market-gui: "A piac menü sikeresen meg lett nyitva {player} részére"
|
||||
open-fishing-bag: "A horgász táska sikeresen meg lett nyitva {player} részére"
|
||||
format-day: 'n'
|
||||
format-hour: 'ó'
|
||||
format-minute: 'p'
|
||||
format-second: 'mp'
|
||||
|
||||
# We're looking for a translator :D
|
||||
gui:
|
||||
search: "Search"
|
||||
select-file: 'Select file'
|
||||
select-item: "Select item"
|
||||
dupe-invalid-key: "<red>● Duplicated or invalid key"
|
||||
new-value: "New value: "
|
||||
temp-new-key: 'New key'
|
||||
set-new-key: "Set new key"
|
||||
edit-key: 'Edit {0}'
|
||||
delete-property: "<#00CED1>● Delete property"
|
||||
click-confirm: "<#00FF7F> -> Click to confirm"
|
||||
invalid-number: "<red>● Invalid number"
|
||||
illegal-format: "<red>● Illegal format"
|
||||
scroll-up: '<gray>● Scroll up'
|
||||
scroll-down: '<gray>● Scroll down'
|
||||
cannot-scroll-up: "<red>You've reached the top"
|
||||
cannot-scroll-down: "<red>You can't scroll further down"
|
||||
next-page: '<gray>● Next Page'
|
||||
goto-next-page: '<gray>Go to page <yellow>{0} <gray>/ <yellow>{1}'
|
||||
cannot-goto-next-page: '<red>There are no more pages'
|
||||
previous-page: '<gray>● Previous page'
|
||||
goto-previous-page: '<gray>Go to page <yellow>{0} <gray>/ <yellow>{1}'
|
||||
cannot-goto-previous-page: "<red>You can't go further back"
|
||||
back-to-parent-page: "<#FF8C00>Back to parent page"
|
||||
back-to-parent-folder: "<#FF8C00>Back to parent folder"
|
||||
current-value: "<gray>Current value: <white>"
|
||||
click-to-toggle: "<#00FF7F> -> Click to toggle"
|
||||
left-click-edit: "<#00FF7F> -> Left click to edit"
|
||||
right-click-reset: "<#FF6347> -> Right click to reset"
|
||||
right-click-delete: "<#FF6347> -> Right click to delete"
|
||||
right-click-cancel: "<#00CED1> -> Right click to cancel"
|
||||
loot-show-in-finder: "<#5F9EA0>● Show In Fish Finder"
|
||||
loot-score: "<#FF1493>● Score"
|
||||
loot-nick: "<#00FF00>● Nick"
|
||||
loot-instant-game: "<#7B68EE>● Instant Game"
|
||||
loot-disable-statistics: "<#CD853F>● Disable Statistics"
|
||||
loot-disable-game: "<#8B4513>● Disable Game"
|
||||
item-amount: "<#1E90FF>● Amount"
|
||||
item-custom-model-data: "<#FFC0CB>● Custom Model Data"
|
||||
item-display-name: "<#FAFAD2>● Display Name"
|
||||
item-custom-durability: "<#1E90FF>● Custom Durability"
|
||||
item-enchantment: "<#8A2BE2>● Enchantment"
|
||||
item-head64: "<#2E8B57>● Head64"
|
||||
item-item-flag: "<#E6E6FA>● Item Flag"
|
||||
item-lore: "<#FA8072>● Lore"
|
||||
item-material: "<#FF00FF>● Material"
|
||||
item-nbt: "<#FA8072>● NBT"
|
||||
item-prevent-grab: "<#FF4500>● Prevent Grabbing"
|
||||
item-price: "<#FFD700>● Price"
|
||||
item-price-base: "<gray> - base: <white>"
|
||||
item-price-bonus: "<gray> - bonus: <white>"
|
||||
item-random-durability: "<#FFFF00>● Random Durability"
|
||||
item-size: "<#FFF0F5>● Size"
|
||||
item-stackable: "<#9370DB>● Stackable"
|
||||
item-stored-enchantment: "<#9370DB>● Stored Enchantment"
|
||||
item-tag: "<#2E8B57>● Tag"
|
||||
item-unbreakable: "<#C0C0C0>● Unbreakable"
|
||||
page-amount-title: "Edit Amount"
|
||||
page-model-data-title: "Edit CustomModelData"
|
||||
page-display-name-title: "Edit display name"
|
||||
page-new-display-name: "New name"
|
||||
page-custom-durability-title: "Edit custom durability"
|
||||
page-stored-enchantment-title: "Edit stored enchantment"
|
||||
page-enchantment-title: "Edit enchantment"
|
||||
page-select-one-enchantment: "Select one enchantment"
|
||||
page-add-new-enchantment: "<green>[+] <gray>Add a new enchantment"
|
||||
page-item-flag-title: "Edit item flag"
|
||||
page-lore-title: "Edit lore"
|
||||
page-add-new-lore: "<green>[+] <gray>Add a new line"
|
||||
page-select-one-lore: "Select one line"
|
||||
page-material-title: "Edit Material"
|
||||
page-nbt-compound-key-title: "Edit compound key"
|
||||
page-nbt-list-key-title: "Edit list key"
|
||||
page-nbt-key-title: "Edit key"
|
||||
page-nbt-invalid-key: "<red>Invaild key"
|
||||
page-nbt-add-new-compound: "<green>[+] <gray>Add a new compound"
|
||||
page-nbt-add-new-list: "<green>[+] <gray>Add a new list"
|
||||
page-nbt-add-new-value: "<green>[+] <gray>Add a new value"
|
||||
page-add-new-key: "<green>[+] <gray>Add a new key"
|
||||
page-nbt-preview: "<green>● NBT Preview"
|
||||
page-nbt-back-to-compound: "<gray>Back to parent compound"
|
||||
page-nbt-set-value-title: "Set value"
|
||||
page-nbt-edit-title: "Edit NBT"
|
||||
page-nick-title: "Edit nick"
|
||||
page-new-nick: "New nick"
|
||||
page-price-title: "Edit price"
|
||||
page-base-price: "Base"
|
||||
page-base-bonus: "Bonus"
|
||||
page-score-title: "Edit score"
|
||||
page-size-title: "Edit size"
|
||||
page-size-min: "Minimum"
|
||||
page-size-max: "Maximum"
|
||||
page-size-max-no-less-min: "<red>● Max must be no less than min"
|
||||
@@ -1,125 +0,0 @@
|
||||
# Don't change this
|
||||
config-version: '31'
|
||||
|
||||
messages:
|
||||
prefix: '<gradient:#0070B3:#A0EACF>[CustomFishing] </gradient>'
|
||||
reload: '<white>重载完成. 耗时 <green>{time}ms.'
|
||||
item-not-exist: '物品不存在.'
|
||||
give-item: '给予玩家 {player} {amount}x {item}.'
|
||||
get-item: '获得 {amount}x {item}.'
|
||||
possible-loots: '可能的战利品: '
|
||||
split-char: ', '
|
||||
competition-not-exist: '比赛 {id} 不存在.'
|
||||
no-competition-ongoing: "没有正在进行的比赛."
|
||||
stop-competition: '停止了当前的比赛.'
|
||||
end-competition: '结束了当前的比赛.'
|
||||
no-score: '无比分'
|
||||
no-player: '无选手'
|
||||
no-rank: '无排名'
|
||||
goal-catch-amount: '捕鱼总数'
|
||||
goal-max-size: '最大尺寸'
|
||||
goal-total-size: '捕鱼总尺寸'
|
||||
goal-total-score: '捕鱼总分'
|
||||
unsafe-modification: "你不能修改一个正在其他子服游玩的玩家钓鱼背包."
|
||||
never-played: "此玩家从未玩过服务器."
|
||||
data-not-loaded: "<red>数据未能正常加载. 请尝试切换子服或重进. 如果问题依然存在请联系服务器管理员."
|
||||
open-market-gui: "为玩家 {player} 打开了市场"
|
||||
open-fishing-bag: "为玩家 {player} 打开了钓鱼背包"
|
||||
format-day: '天'
|
||||
format-hour: '小时'
|
||||
format-minute: '分'
|
||||
format-second: '秒'
|
||||
|
||||
gui:
|
||||
search: 搜索
|
||||
select-file: 选择文件
|
||||
select-item-to-edit: 选择要编辑的物品
|
||||
dupe-invalid-key: <red>● 重复或无效的键
|
||||
new-value: '新值: '
|
||||
temp-new-key: '新键'
|
||||
set-new-key: '设置新键'
|
||||
edit-key: '修改 {0}'
|
||||
delete-property: <#00CED1>● 删除属性
|
||||
click-confirm: <#00FF7F> -> 点击确认
|
||||
invalid-number: <red>● 无效的数字
|
||||
illegal-format: <red>● 非法的格式
|
||||
scroll-up: <gray>● 向上翻
|
||||
scroll-down: <gray>● 向下翻
|
||||
cannot-scroll-up: <red>你已经到顶了
|
||||
cannot-scroll-down: <red>你不能再往下了
|
||||
next-page: <gray>● 下一页
|
||||
goto-next-page: <gray>前往 <yellow>{0} <gray>/ <yellow>{1}
|
||||
cannot-goto-next-page: <red>没有更多页了
|
||||
previous-page: <gray>● 上一页
|
||||
goto-previous-page: <gray>前往 <yellow>{0} <gray>/ <yellow>{1}
|
||||
cannot-goto-previous-page: <red>已经到达第一页了
|
||||
back-to-parent-page: <#FF8C00>返回上一界面
|
||||
back-to-parent-folder: <#FF8C00>返回父文件夹
|
||||
current-value: '<gray>当前值: <white>'
|
||||
click-to-toggle: <#00FF7F> -> 点击切换
|
||||
left-click-edit: <#00FF7F> -> 左键编辑
|
||||
right-click-reset: <#FF6347> -> 右键重置
|
||||
right-click-delete: <#FF6347> -> 右键删除
|
||||
right-click-cancel: <#00CED1> -> 右键取消
|
||||
loot-show-in-finder: <#5F9EA0>● 在找鱼器中可见
|
||||
loot-score: <#FF1493>● 比赛分数
|
||||
loot-nick: <#00FF00>● 昵称
|
||||
loot-instant-game: <#7B68EE>● 咬钩立即游戏
|
||||
loot-disable-statistics: <#CD853F>● 禁用统计数据
|
||||
loot-disable-game: <#8B4513>● 禁用游戏
|
||||
item-amount: <#1E90FF>● 数量
|
||||
item-custom-model-data: <#FFC0CB>● 自定义模型值
|
||||
item-display-name: <#FAFAD2>● 名称
|
||||
item-custom-durability: <#1E90FF>● 自定义耐久度
|
||||
item-enchantment: <#8A2BE2>● 附魔
|
||||
item-head64: <#2E8B57>● 头颅base64
|
||||
item-item-flag: <#E6E6FA>● 物品标签
|
||||
item-lore: <#FA8072>● 描述
|
||||
item-material: <#FF00FF>● 材质
|
||||
item-nbt: <#FA8072>● NBT
|
||||
item-prevent-grab: <#FF4500>● 防止抢夺
|
||||
item-price: <#FFD700>● 价格
|
||||
item-price-base: '<gray> - 基础: <white>'
|
||||
item-price-bonus: '<gray> - 尺寸增益: <white>'
|
||||
item-random-durability: <#FFFF00>● 随机耐久
|
||||
item-size: <#FFF0F5>● 尺寸
|
||||
item-stackable: <#9370DB>● 是否可以堆叠
|
||||
item-stored-enchantment: <#9370DB>● 存储附魔
|
||||
item-tag: <#2E8B57>● 启用CustomFishing标签
|
||||
item-unbreakable: <#C0C0C0>● 不可破坏
|
||||
page-amount-title: 修改数量
|
||||
page-model-data-title: 修改自定义模型值
|
||||
page-display-name-title: 修改名称
|
||||
page-new-display-name: 新名称
|
||||
page-custom-durability-title: 修改自定义耐久度
|
||||
page-stored-enchantment-title: 修改存储附魔
|
||||
page-enchantment-title: 修改附魔
|
||||
page-select-one-enchantment: 选择一个附魔
|
||||
page-add-new-enchantment: <green>[+] <gray>新增一个附魔
|
||||
page-item-flag-title: 修改物品标签
|
||||
page-lore-title: 修改描述
|
||||
page-add-new-lore: <green>[+] <gray>新增一行描述
|
||||
page-select-one-lore: 选择一行描述
|
||||
page-material-title: 修改材质
|
||||
page-nbt-compound-key-title: 修改复合键名
|
||||
page-nbt-list-key-title: 修改列表名
|
||||
page-nbt-key-title: 修改键
|
||||
page-nbt-invalid-key: <red>无效的键
|
||||
page-nbt-add-new-compound: <green>[+] <gray>新增一个复合NBT
|
||||
page-nbt-add-new-list: <green>[+] <gray>新增一个列表
|
||||
page-nbt-add-new-value: <green>[+] <gray>新增一个值
|
||||
page-add-new-key: <green>[+] <gray>新增一个键
|
||||
page-nbt-preview: <green>● NBT 预览
|
||||
page-nbt-back-to-compound: <gray>返回父复合NBT
|
||||
page-nbt-set-value-title: 设置值
|
||||
page-nbt-edit-title: 修改NBT
|
||||
page-nick-title: 修改昵称
|
||||
page-new-nick: 新昵称
|
||||
page-price-title: 修改价格
|
||||
page-base-price: 基础
|
||||
page-base-bonus: 尺寸增益
|
||||
page-score-title: 修改分数
|
||||
page-size-title: 修改尺寸
|
||||
page-size-min: 最小值
|
||||
page-size-max: 最大值
|
||||
page-size-max-no-less-min: <red>● 最大值必须大于最小值
|
||||
@@ -1,35 +0,0 @@
|
||||
name: CustomFishing
|
||||
version: '${version}'
|
||||
main: net.momirealms.customfishing.CustomFishingPluginImpl
|
||||
api-version: 1.17
|
||||
authors: [ XiaoMoMi ]
|
||||
folia-supported: true
|
||||
depend:
|
||||
- ProtocolLib
|
||||
softdepend:
|
||||
- Vault
|
||||
- PlaceholderAPI
|
||||
- RealisticSeasons
|
||||
- ItemsAdder
|
||||
- MythicMobs
|
||||
- Oraxen
|
||||
- MMOItems
|
||||
- mcMMO
|
||||
- AureliumSkills
|
||||
- AuraSkills
|
||||
- CustomCrops
|
||||
- MMOCore
|
||||
- EcoSkills
|
||||
- BattlePass
|
||||
- ClueScrolls
|
||||
- BetonQuest
|
||||
- AdvancedEnchantments
|
||||
- EcoJobs
|
||||
- Zaphkiel
|
||||
permissions:
|
||||
fishingbag.user:
|
||||
default: true
|
||||
fishingbag.collectloot:
|
||||
default: false
|
||||
customfishing.sellfish:
|
||||
default: true
|
||||
123
core/src/main/resources/translations/en.yml
Normal file
123
core/src/main/resources/translations/en.yml
Normal file
@@ -0,0 +1,123 @@
|
||||
# Don"t change this
|
||||
config-version: "31"
|
||||
|
||||
command.prefix: "<gradient:#0070B3:#A0EACF>[CustomFishing] </gradient>"
|
||||
command.reload.success: "<white>Reloaded. Took <green><arg:0></green>ms.</white>"
|
||||
command.item.failure.not_exist: "<red>Item not exists</red>"
|
||||
command.item.give.success: "Successfully given player <arg:0> <arg:1>x <arg:2>."
|
||||
command.item.get.success: "Successfully got <arg:0>x <arg:1>."
|
||||
command.fish_finder.possible_loots: "Possible loots here: "
|
||||
command.fish_finder.no_loot: "No loot available"
|
||||
command.fish_finder.split_char: ", "
|
||||
command.competition.failure.not_exist: "Competition <arg:0> does not exist."
|
||||
command.competition.failure.no_competition: "There's no competition ongoing."
|
||||
command.competition.stop.success: "Stopped the current competition."
|
||||
command.competition.end.success: "Ended the current competition."
|
||||
command.bag.edit.failure.unsafe: "Cannot edit a player's fishing bag if they"re active on another linked server."
|
||||
command.bag.edit.failure.never_played: 'The player hasn\'t joined the server before. Can't modify a nonexistent player"s fishing bag."
|
||||
command.bag.open.success: "Successfully opened the fishing bag for <arg:0>"
|
||||
command.data.failure.not_load: '<red>Data hasn't loaded. Please re-enter the server. If issues persist, reach out to the server admin.</red>"
|
||||
command.market.open.success: "Successfully opened the market gui for <arg:0>"
|
||||
competition.no_score: "No Score"
|
||||
competition.no_player: "No Player"
|
||||
competition.no_rank: "No Rank"
|
||||
competition.goal.catch_amount: "Fish count caught"
|
||||
competition.goal.max_size: "Largest fish caught"
|
||||
competition.goal.total_score: "Cumulative score of fish caught"
|
||||
competition.goal.total_size: "Total length of fish caught"
|
||||
format.day: "d"
|
||||
format.hour: "h"
|
||||
format.minute: "m"
|
||||
format.second: "s"
|
||||
gui.search: "Search"
|
||||
gui.select_file: "Select file"
|
||||
gui.select_item: "Select item"
|
||||
gui.invalid_key: "<red>● Duplicated or invalid key"
|
||||
gui.new_value: "New value: "
|
||||
gui.temp_new_key: "New key"
|
||||
gui.set_new_key: "Set new key"
|
||||
gui.edit_key: "Edit <arg:0>"
|
||||
gui.delete_property: "<#00CED1>● Delete property"
|
||||
gui.click_confirm: "<#00FF7F> -> Click to confirm"
|
||||
gui.invalid_number: "<red>● Invalid number"
|
||||
gui.illegal_format: "<red>● Illegal format"
|
||||
gui.scroll_up: "<gray>● Scroll up"
|
||||
gui.scroll_down: "<gray>● Scroll down"
|
||||
gui.cannot_scroll_up: "<red>You"ve reached the top"
|
||||
gui.cannot_scroll_down: "<red>You can"t scroll further down"
|
||||
gui.next_page: "<gray>● Next Page"
|
||||
gui.goto_next_page: "<gray>Go to page <yellow><arg:0> <gray>/ <yellow><arg:1>"
|
||||
gui.cannot_goto_next_page: "<red>There are no more pages"
|
||||
gui.previous_page: "<gray>● Previous page"
|
||||
gui.goto_previous_page: "<gray>Go to page <yellow><arg:0> <gray>/ <yellow><arg:1>"
|
||||
gui.cannot_goto_previous_page: "<red>You can"t go further back"
|
||||
gui.back_to_parent_page: "<#FF8C00>Back to parent page"
|
||||
gui.back_to_parent_folder: "<#FF8C00>Back to parent folder"
|
||||
gui.current_value: "<gray>Current value: <white><arg:0>"
|
||||
gui.click_to_toggle: "<#00FF7F> -> Click to toggle"
|
||||
gui.left_click_edit: "<#00FF7F> -> Left click to edit"
|
||||
gui.right_click_reset: "<#FF6347> -> Right click to reset"
|
||||
gui.right_click_delete: "<#FF6347> -> Right click to delete"
|
||||
gui.right_click_cancel: "<#00CED1> -> Right click to cancel"
|
||||
gui.loot_show_in_finder: "<#5F9EA0>● Show In Fish Finder"
|
||||
gui.loot_score: "<#FF1493>● Score"
|
||||
gui.loot_nick: "<#00FF00>● Nick"
|
||||
gui.loot_instant_game: "<#7B68EE>● Instant Game"
|
||||
gui.loot_disable_statistics: "<#CD853F>● Disable Statistics"
|
||||
gui.loot_disable_game: "<#8B4513>● Disable Game"
|
||||
gui.item_amount: "<#1E90FF>● Amount"
|
||||
gui.item_custom_model_data: "<#FFC0CB>● Custom Model Data"
|
||||
gui.item_display_name: "<#FAFAD2>● Display Name"
|
||||
gui.item_custom_durability: "<#1E90FF>● Custom Durability"
|
||||
gui.item_enchantment: "<#8A2BE2>● Enchantment"
|
||||
gui.item_head64: "<#2E8B57>● Head64"
|
||||
gui.item_item_flag: "<#E6E6FA>● Item Flag"
|
||||
gui.item_lore: "<#FA8072>● Lore"
|
||||
gui.item_material: "<#FF00FF>● Material"
|
||||
gui.item_nbt: "<#FA8072>● NBT"
|
||||
gui.item_prevent_grab: "<#FF4500>● Prevent Grabbing"
|
||||
gui.item_price: "<#FFD700>● Price"
|
||||
gui.item_price_base: "<gray> - base: <white>"
|
||||
gui.item_price_bonus: "<gray> - bonus: <white>"
|
||||
gui.item_random_durability: "<#FFFF00>● Random Durability"
|
||||
gui.item_size: "<#FFF0F5>● Size"
|
||||
gui.item_stackable: "<#9370DB>● Stackable"
|
||||
gui.item_stored_enchantment: "<#9370DB>● Stored Enchantment"
|
||||
gui.item_tag: "<#2E8B57>● Tag"
|
||||
gui.item_unbreakable: "<#C0C0C0>● Unbreakable"
|
||||
gui.page_amount_title: "Edit Amount"
|
||||
gui.page_model_data_title: "Edit CustomModelData"
|
||||
gui.page_display_name_title: "Edit display name"
|
||||
gui.page_new_display_name: "New name"
|
||||
gui.page_custom_durability_title: "Edit custom durability"
|
||||
gui.page_stored_enchantment_title: "Edit stored enchantment"
|
||||
gui.page_enchantment_title: "Edit enchantment"
|
||||
gui.page_select_one_enchantment: "Select one enchantment"
|
||||
gui.page_add_new_enchantment: "<green>[+] <gray>Add a new enchantment"
|
||||
gui.page_item_flag_title: "Edit item flag"
|
||||
gui.page_lore_title: "Edit lore"
|
||||
gui.page_add_new_lore: "<green>[+] <gray>Add a new line"
|
||||
gui.page_select_one_lore: "Select one line"
|
||||
gui.page_material_title: "Edit Material"
|
||||
gui.page_nbt_compound_key_title: "Edit compound key"
|
||||
gui.page_nbt_list_key_title: "Edit list key"
|
||||
gui.page_nbt_key_title: "Edit key"
|
||||
gui.page_nbt_invalid_key: "<red>Invaild key"
|
||||
gui.page_nbt_add_new_compound: "<green>[+] <gray>Add a new compound"
|
||||
gui.page_nbt_add_new_list: "<green>[+] <gray>Add a new list"
|
||||
gui.page_nbt_add_new_value: "<green>[+] <gray>Add a new value"
|
||||
gui.page_add_new_key: "<green>[+] <gray>Add a new key"
|
||||
gui.page_nbt_preview: "<green>● NBT Preview"
|
||||
gui.page_nbt_back_to_compound: "<gray>Back to parent compound"
|
||||
gui.page_nbt_set_value_title: "Set value"
|
||||
gui.page_nbt_edit_title: "Edit NBT"
|
||||
gui.page_nick_title: "Edit nick"
|
||||
gui.page_new_nick: "New nick"
|
||||
gui.page_price_title: "Edit price"
|
||||
gui.page_base_price: "Base"
|
||||
gui.page_base_bonus: "Bonus"
|
||||
gui.page_score_title: "Edit score"
|
||||
gui.page_size_title: "Edit size"
|
||||
gui.page_size_min: "Minimum"
|
||||
gui.page_size_max: "Maximum"
|
||||
gui.page_size_max_no_less_min: "<red>● Max must be no less than min</red>"
|
||||
Reference in New Issue
Block a user